aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2015-11-10 02:01:43 -0800
committerGuy Harris <guy@alum.mit.edu>2015-11-10 10:11:50 +0000
commit827b7dd75680b26e2bfddb0dac2f42f1dad69e7a (patch)
tree6e2f0010572a5073789163fd0abbf270f739e44a
parent630ccbe2d74338bac6d8abe69705cf0401baa8c1 (diff)
Skip only the actual file descriptor close when writing to stdout.
Have a "this is stdout" flag for a wtap_dumper, and have "open the standard output for dumping" routines that set that flag. When closing a wtap_dumper, do most of the work regardless of whether we're writing to the standard output or not (so that everything gets written out) and only skip the closing of the underlying file descriptor. Change-Id: I9f7e4d142b3bd598055d806b7ded1cb4c378de8e Reviewed-on: https://code.wireshark.org/review/11673 Reviewed-by: Guy Harris <guy@alum.mit.edu>
-rw-r--r--editcap.c8
-rw-r--r--randpkt.c2
-rw-r--r--reordercap.c4
-rw-r--r--tshark.c4
-rw-r--r--wiretap/file_access.c110
-rw-r--r--wiretap/file_wrappers.c16
-rw-r--r--wiretap/file_wrappers.h2
-rw-r--r--wiretap/wtap-int.h1
-rw-r--r--wiretap/wtap.h26
9 files changed, 131 insertions, 42 deletions
diff --git a/editcap.c b/editcap.c
index c2522c59a8..ab929c5eb7 100644
--- a/editcap.c
+++ b/editcap.c
@@ -898,10 +898,10 @@ editcap_dump_open(const char *filename, guint32 snaplen,
if (strcmp(filename, "-") == 0) {
/* Write to the standard output. */
- pdh = wtap_dump_fdopen_ng(1, out_file_type_subtype, out_frame_type,
- snaplen, FALSE /* compressed */,
- shb_hdr, idb_inf, nrb_hdr,
- write_err);
+ pdh = wtap_dump_open_stdout_ng(out_file_type_subtype, out_frame_type,
+ snaplen, FALSE /* compressed */,
+ shb_hdr, idb_inf, nrb_hdr,
+ write_err);
} else {
pdh = wtap_dump_open_ng(filename, out_file_type_subtype, out_frame_type,
snaplen, FALSE /* compressed */,
diff --git a/randpkt.c b/randpkt.c
index b5db8407f3..f61aa7805b 100644
--- a/randpkt.c
+++ b/randpkt.c
@@ -636,7 +636,7 @@ static void randpkt_example_init(randpkt_example* example, char* produce_filenam
if (strcmp(produce_filename, "-") == 0) {
/* Write to the standard output. */
- example->dump = wtap_dump_fdopen(1, WTAP_FILE_TYPE_SUBTYPE_PCAP,
+ example->dump = wtap_dump_open_stdout(WTAP_FILE_TYPE_SUBTYPE_PCAP,
example->sample_wtap_encap, produce_max_bytes, FALSE /* compressed */, &err);
example->filename = "the standard output";
} else {
diff --git a/reordercap.c b/reordercap.c
index efbbfdaf36..fef413dd75 100644
--- a/reordercap.c
+++ b/reordercap.c
@@ -276,8 +276,8 @@ DIAG_ON(cast-qual)
/* Open outfile (same filetype/encap as input file) */
if (strcmp(outfile, "-") == 0) {
- pdh = wtap_dump_fdopen_ng(1, wtap_file_type_subtype(wth), wtap_file_encap(wth),
- 65535, FALSE, shb_hdr, idb_inf, nrb_hdr, &err);
+ pdh = wtap_dump_open_stdout_ng(wtap_file_type_subtype(wth), wtap_file_encap(wth),
+ 65535, FALSE, shb_hdr, idb_inf, nrb_hdr, &err);
outfile = "standard output";
} else {
pdh = wtap_dump_open_ng(outfile, wtap_file_type_subtype(wth), wtap_file_encap(wth),
diff --git a/tshark.c b/tshark.c
index a43417b63e..775a62c06f 100644
--- a/tshark.c
+++ b/tshark.c
@@ -3201,7 +3201,7 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
tshark_debug("tshark: writing PCAP format to %s", save_file);
if (strcmp(save_file, "-")) {
/* Write to the standard output. */
- pdh = wtap_dump_fdopen(1, out_file_type, linktype,
+ pdh = wtap_dump_open_stdout(out_file_type, linktype,
snapshot_length, FALSE /* compressed */, &err);
} else {
pdh = wtap_dump_open(save_file, out_file_type, linktype,
@@ -3212,7 +3212,7 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
tshark_debug("tshark: writing format type %d, to %s", out_file_type, save_file);
if (strcmp(save_file, "-")) {
/* Write to the standard output. */
- pdh = wtap_dump_fdopen_ng(1, out_file_type, linktype,
+ pdh = wtap_dump_open_stdout_ng(out_file_type, linktype,
snapshot_length, FALSE /* compressed */, shb_hdr, idb_inf, nrb_hdr, &err);
} else {
pdh = wtap_dump_open_ng(save_file, out_file_type, linktype,
diff --git a/wiretap/file_access.c b/wiretap/file_access.c
index c667118408..8a965f100d 100644
--- a/wiretap/file_access.c
+++ b/wiretap/file_access.c
@@ -2231,10 +2231,8 @@ wtap_dump_open_ng(const char *filename, int file_type_subtype, int encap,
if (!wtap_dump_open_finish(wdh, file_type_subtype, compressed, err)) {
/* Get rid of the file we created; we couldn't finish
opening it. */
- if (wdh->fh != stdout) {
- wtap_dump_file_close(wdh);
- ws_unlink(filename);
- }
+ wtap_dump_file_close(wdh);
+ ws_unlink(filename);
g_free(wdh);
return NULL;
}
@@ -2267,27 +2265,78 @@ wtap_dump_fdopen_ng(int fd, int file_type_subtype, int encap, int snaplen,
if (wdh == NULL)
return NULL;
+ /* In case "fopen()" fails but doesn't set "errno", set "errno"
+ to a generic "the open failed" error. */
+ errno = WTAP_ERR_CANT_OPEN;
+ fh = wtap_dump_file_fdopen(wdh, fd);
+ if (fh == NULL) {
+ *err = errno;
+ g_free(wdh);
+ return NULL; /* can't create standard I/O stream */
+ }
+ wdh->fh = fh;
+
+ if (!wtap_dump_open_finish(wdh, file_type_subtype, compressed, err)) {
+ wtap_dump_file_close(wdh);
+ g_free(wdh);
+ return NULL;
+ }
+ return wdh;
+}
+
+wtap_dumper *
+wtap_dump_open_stdout(int file_type_subtype, int encap, int snaplen,
+ gboolean compressed, int *err)
+{
+ return wtap_dump_open_stdout_ng(file_type_subtype, encap, snaplen, compressed, NULL, NULL, NULL, err);
+}
+
+wtap_dumper *
+wtap_dump_open_stdout_ng(int file_type_subtype, int encap, int snaplen,
+ gboolean compressed, wtapng_section_t *shb_hdr,
+ wtapng_iface_descriptions_t *idb_inf,
+ wtapng_name_res_t *nrb_hdr, int *err)
+{
+ wtap_dumper *wdh;
+ WFILE_T fh;
+
+ /* Check whether we can open a capture file with that file type
+ and that encapsulation. */
+ if (!wtap_dump_open_check(file_type_subtype, encap, compressed, err))
+ return NULL;
+
+ /* Allocate and initialize a data structure for the output stream. */
+ wdh = wtap_dump_init_dumper(file_type_subtype, encap, snaplen, compressed,
+ shb_hdr, idb_inf, nrb_hdr, err);
+ if (wdh == NULL)
+ return NULL;
+
#ifdef _WIN32
- if (fd == 1) {
- if (_setmode(fileno(stdout), O_BINARY) == -1) {
- /* "Should not happen" */
- *err = errno;
- g_free(wdh);
- return NULL; /* couldn't put standard output in binary mode */
- }
+ /*
+ * Put the standard output into binary mode.
+ *
+ * XXX - even if the file format we're writing is a text
+ * format?
+ */
+ if (_setmode(1, O_BINARY) == -1) {
+ /* "Should not happen" */
+ *err = errno;
+ g_free(wdh);
+ return NULL; /* couldn't put standard output in binary mode */
}
#endif
/* In case "fopen()" fails but doesn't set "errno", set "errno"
to a generic "the open failed" error. */
errno = WTAP_ERR_CANT_OPEN;
- fh = wtap_dump_file_fdopen(wdh, fd);
+ fh = wtap_dump_file_fdopen(wdh, 1);
if (fh == NULL) {
*err = errno;
g_free(wdh);
return NULL; /* can't create standard I/O stream */
}
wdh->fh = fh;
+ wdh->is_stdout = TRUE;
if (!wtap_dump_open_finish(wdh, file_type_subtype, compressed, err)) {
wtap_dump_file_close(wdh);
@@ -2424,21 +2473,15 @@ wtap_dump_close(wtap_dumper *wdh, int *err)
ret = FALSE;
}
errno = WTAP_ERR_CANT_CLOSE;
- /* Don't close stdout */
- if (wdh->fh != stdout) {
- if (wtap_dump_file_close(wdh) == EOF) {
- if (ret) {
- /* The per-format close function succeeded,
- but the fclose didn't. Save the reason
- why, if our caller asked for it. */
- if (err != NULL)
- *err = errno;
- }
- ret = FALSE;
+ if (wtap_dump_file_close(wdh) == EOF) {
+ if (ret) {
+ /* The per-format finish function succeeded,
+ but the stream close didn't. Save the
+ reason why, if our caller asked for it. */
+ if (err != NULL)
+ *err = errno;
}
- } else {
- /* as we don't close stdout, at least try to flush it */
- wtap_dump_flush(wdh);
+ ret = FALSE;
}
if (wdh->priv != NULL)
g_free(wdh->priv);
@@ -2548,11 +2591,22 @@ wtap_dump_file_close(wtap_dumper *wdh)
{
#ifdef HAVE_LIBZ
if(wdh->compressed) {
- return gzwfile_close((GZWFILE_T)wdh->fh);
+ /*
+ * Tell gzwfile_close() whether to close the descriptor
+ * or not.
+ */
+ return gzwfile_close((GZWFILE_T)wdh->fh, wdh->is_stdout);
} else
#endif
{
- return fclose((FILE *)wdh->fh);
+ /*
+ * Don't close the standard output.
+ *
+ * XXX - this really should do everything fclose() does,
+ * including freeing all allocated data structures,
+ * *except* for actually closing the file descriptor.
+ */
+ return wdh->is_stdout ? fflush((FILE *)wdh->fh) : fclose((FILE *)wdh->fh);
}
}
diff --git a/wiretap/file_wrappers.c b/wiretap/file_wrappers.c
index 5b4cbd27da..5918a55f6f 100644
--- a/wiretap/file_wrappers.c
+++ b/wiretap/file_wrappers.c
@@ -1719,9 +1719,15 @@ gzwfile_flush(GZWFILE_T state)
}
/* Flush out all data written, and close the file. Returns a Wiretap
- error on failure; returns 0 on success. */
+ error on failure; returns 0 on success.
+
+ If is_stdout is true, do all of that except for closing the file
+ descriptor, as we don't want to close the standard output file
+ descriptor out from under the program (even though, if the program
+ is writing a capture file to the standard output, it shouldn't be
+ doing anything *else* on the standard output). */
int
-gzwfile_close(GZWFILE_T state)
+gzwfile_close(GZWFILE_T state, gboolean is_stdout)
{
int ret = 0;
@@ -1732,8 +1738,10 @@ gzwfile_close(GZWFILE_T state)
g_free(state->out);
g_free(state->in);
state->err = Z_OK;
- if (ws_close(state->fd) == -1 && ret == 0)
- ret = errno;
+ if (!is_stdout) {
+ if (ws_close(state->fd) == -1 && ret == 0)
+ ret = errno;
+ }
g_free(state);
return ret;
}
diff --git a/wiretap/file_wrappers.h b/wiretap/file_wrappers.h
index 7f3cdc4205..42df4e4e66 100644
--- a/wiretap/file_wrappers.h
+++ b/wiretap/file_wrappers.h
@@ -53,7 +53,7 @@ extern GZWFILE_T gzwfile_open(const char *path);
extern GZWFILE_T gzwfile_fdopen(int fd);
extern guint gzwfile_write(GZWFILE_T state, const void *buf, guint len);
extern int gzwfile_flush(GZWFILE_T state);
-extern int gzwfile_close(GZWFILE_T state);
+extern int gzwfile_close(GZWFILE_T state, gboolean is_stdout);
extern int gzwfile_geterr(GZWFILE_T state);
#endif /* HAVE_LIBZ */
diff --git a/wiretap/wtap-int.h b/wiretap/wtap-int.h
index 91656bdfaa..87d5f4b0e9 100644
--- a/wiretap/wtap-int.h
+++ b/wiretap/wtap-int.h
@@ -95,6 +95,7 @@ typedef gboolean (*subtype_finish_func)(struct wtap_dumper*, int*);
struct wtap_dumper {
WFILE_T fh;
+ gboolean is_stdout;
int file_type_subtype;
int snaplen;
int encap;
diff --git a/wiretap/wtap.h b/wiretap/wtap.h
index 253f3c9a7f..37dfce7918 100644
--- a/wiretap/wtap.h
+++ b/wiretap/wtap.h
@@ -1936,6 +1936,7 @@ wtap_dumper* wtap_dump_fdopen(int fd, int file_type_subtype, int encap, int snap
* wtap_dump_close() is called, but will not be free'd by the dumper. If
* you created them, you must free them yourself after wtap_dump_close().
*
+ * @param fd The file descriptor for which the dumper should be created.
* @param file_type_subtype The WTAP_FILE_TYPE_SUBTYPE_XXX file type.
* @param encap The WTAP_ENCAP_XXX encapsulation type (WTAP_ENCAP_PER_PACKET for multi)
* @param snaplen The maximum packet capture length.
@@ -1951,6 +1952,31 @@ wtap_dumper* wtap_dump_fdopen_ng(int fd, int file_type_subtype, int encap, int s
gboolean compressed, wtapng_section_t *shb_hdr, wtapng_iface_descriptions_t *idb_inf,
wtapng_name_res_t *nrb_hdr, int *err);
+WS_DLL_PUBLIC
+wtap_dumper* wtap_dump_open_stdout(int file_type_subtype, int encap, int snaplen,
+ gboolean compressed, int *err);
+
+/**
+ * @brief Creates a dumper for the standard output.
+ *
+ * @note The shb_hdr, idb_inf, and nrb_hdr arguments will be used until
+ * wtap_dump_close() is called, but will not be free'd by the dumper. If
+ * you created them, you must free them yourself after wtap_dump_close().
+ *
+ * @param file_type_subtype The WTAP_FILE_TYPE_SUBTYPE_XXX file type.
+ * @param encap The WTAP_ENCAP_XXX encapsulation type (WTAP_ENCAP_PER_PACKET for multi)
+ * @param snaplen The maximum packet capture length.
+ * @param compressed True if file should be compressed.
+ * @param shb_hdr The section header block information, or NULL.
+ * @param idb_inf The interface description information, or NULL.
+ * @param nrb_hdr The name resolution comment/custom_opts information, or NULL.
+ * @param[out] err Will be set to an error code on failure.
+ * @return The newly created dumper object, or NULL on failure.
+ */
+WS_DLL_PUBLIC
+wtap_dumper* wtap_dump_open_stdout_ng(int file_type_subtype, int encap, int snaplen,
+ gboolean compressed, wtapng_section_t *shb_hdr, wtapng_iface_descriptions_t *idb_inf,
+ wtapng_name_res_t *nrb_hdr, int *err);
WS_DLL_PUBLIC
gboolean wtap_dump(wtap_dumper *, const struct wtap_pkthdr *, const guint8 *,