summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 *,