forked from osmocom/wireshark
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>
This commit is contained in:
parent
630ccbe2d7
commit
827b7dd756
|
@ -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 */,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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),
|
||||
|
|
4
tshark.c
4
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,
|
||||
|
|
|
@ -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,17 +2265,6 @@ wtap_dump_fdopen_ng(int fd, int file_type_subtype, int encap, int snaplen,
|
|||
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 */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* In case "fopen()" fails but doesn't set "errno", set "errno"
|
||||
to a generic "the open failed" error. */
|
||||
errno = WTAP_ERR_CANT_OPEN;
|
||||
|
@ -2297,6 +2284,68 @@ wtap_dump_fdopen_ng(int fd, int file_type_subtype, int encap, int snaplen,
|
|||
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
|
||||
/*
|
||||
* 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, 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);
|
||||
g_free(wdh);
|
||||
return NULL;
|
||||
}
|
||||
return wdh;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
wtap_dump_open_check(int file_type_subtype, int encap, gboolean compressed, int *err)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 *,
|
||||
|
|
Loading…
Reference in New Issue