diff options
author | John Thacker <johnthacker@gmail.com> | 2021-09-10 20:46:54 -0400 |
---|---|---|
committer | Wireshark GitLab Utility <gerald+gitlab-utility@wireshark.org> | 2021-09-11 22:37:25 +0000 |
commit | 6fe68991df128960f5ea5c3615a90ef2a5ab22b7 (patch) | |
tree | 676d8de4c4a8ac7fd6f61634f4c2e93339806752 /wiretap | |
parent | 07a31d29189a9e55d17d4aeda2ed9c30a6cd0722 (diff) |
wiretap: Add zstd and lz4 as WTAP compression types
This has a few effects on the behavior of wtap_get_compression_type()
and wtap_get_all_compression_type_extensions():
Make capinfos correctly report the compression type (instead of
saying gzip compressed for zstd and lz4 compressed files).
Makes files with the .zstd and .lz4 extension show up in the file
chooser when "Files of type" is set to something other than "All Files",
such as "All Capture Files" or "Wireshark/... pcapng"
Makes the UI not default to gzip compression when saving a file
compressed as zstd or lz4 (write support for zstd and lz4 doesn't
exist yet, and the GUI doesn't have hooks for it anyway, though
this can help as a prerequisite for later support for writing.)
Also replace a couple of assert() with ws_assert().
Update the PURPOSE in CMakeLists for zstd and lz4 to note that they
can be used to read compressed capture files.
Diffstat (limited to 'wiretap')
-rw-r--r-- | wiretap/file_wrappers.c | 66 | ||||
-rw-r--r-- | wiretap/wtap.h | 4 |
2 files changed, 54 insertions, 16 deletions
diff --git a/wiretap/file_wrappers.c b/wiretap/file_wrappers.c index 6ce847a5eb..6ec35eb1c8 100644 --- a/wiretap/file_wrappers.c +++ b/wiretap/file_wrappers.c @@ -69,16 +69,21 @@ static struct compression_type { #ifdef HAVE_ZLIB { WTAP_GZIP_COMPRESSED, "gz", "gzip compressed" }, #endif +#ifdef HAVE_ZSTD + { WTAP_ZSTD_COMPRESSED, "zst", "zstd compressed" }, +#endif +#ifdef USE_LZ4 + { WTAP_LZ4_COMPRESSED, "lz4", "lz4 compressed" }, +#endif { WTAP_UNCOMPRESSED, NULL, NULL } }; +static wtap_compression_type file_get_compression_type(FILE_T stream); + wtap_compression_type wtap_get_compression_type(wtap *wth) { - gboolean is_compressed; - - is_compressed = file_iscompressed((wth->fh == NULL) ? wth->random_fh : wth->fh); - return is_compressed ? WTAP_GZIP_COMPRESSED : WTAP_UNCOMPRESSED; + return file_get_compression_type((wth->fh == NULL) ? wth->random_fh : wth->fh); } const char * @@ -122,18 +127,12 @@ wtap_get_all_compression_type_extensions_list(void) /* values for wtap_reader compression */ typedef enum { - UNKNOWN, /* unknown - look for a gzip header */ + UNKNOWN, /* unknown - look for a compression header */ UNCOMPRESSED, /* uncompressed - copy input directly */ -#ifdef HAVE_ZLIB ZLIB, /* decompress a zlib stream */ GZIP_AFTER_HEADER, -#endif -#ifdef HAVE_ZSTD ZSTD, -#endif -#ifdef USE_LZ4 LZ4, -#endif } compression_t; /* @@ -179,6 +178,7 @@ struct wtap_reader { gint64 start; /* where the gzip data started, for rewinding */ gint64 raw; /* where the raw data started, for seeking */ compression_t compression; /* type of compression, if any */ + compression_t last_compression; /* last known compression type */ gboolean is_compressed; /* FALSE if completely uncompressed, TRUE otherwise */ /* seek request */ @@ -686,6 +686,7 @@ DIAG_ON(cast-qual) state->err_info = "length field wrong"; } } + state->last_compression = state->compression; state->compression = UNKNOWN; /* ready for next stream, once have is 0 */ g_free(state->fast_seek_cur); state->fast_seek_cur = NULL; @@ -921,7 +922,7 @@ gz_head(FILE_T state) static int /* gz_make */ fill_out_buffer(FILE_T state) { - if (state->compression == UNKNOWN) { /* look for gzip header */ + if (state->compression == UNKNOWN) { /* look for compression header */ if (gz_head(state) == -1) return -1; if (state->out.avail != 0) /* got some data from gz_head() */ @@ -938,7 +939,7 @@ fill_out_buffer(FILE_T state) #endif #ifdef HAVE_ZSTD else if (state->compression == ZSTD) { - assert(state->out.avail == 0); + ws_assert(state->out.avail == 0); if (state->in.avail == 0 && fill_in_buffer(state) == -1) return -1; @@ -959,13 +960,14 @@ fill_out_buffer(FILE_T state) state->out.avail = (guint)output.pos; if (ret == 0) { + state->last_compression = state->compression; state->compression = UNKNOWN; } } #endif #ifdef USE_LZ4 else if (state->compression == LZ4) { - assert(state->out.avail == 0); + ws_assert(state->out.avail == 0); if (state->in.avail == 0 && fill_in_buffer(state) == -1) return -1; @@ -990,6 +992,7 @@ fill_out_buffer(FILE_T state) state->out.avail = (guint)outBufSize; if (ret == 0) { + state->last_compression = state->compression; state->compression = UNKNOWN; } } @@ -1038,7 +1041,7 @@ gz_reset(FILE_T state) { buf_reset(&state->out); /* no output data available */ state->eof = FALSE; /* not at end of file */ - state->compression = UNKNOWN; /* look for gzip header */ + state->compression = UNKNOWN; /* look for compression header */ state->seek_pending = FALSE; /* no seek request pending */ state->err = 0; /* clear error */ @@ -1096,6 +1099,7 @@ file_fdopen(int fd) /* we don't yet know whether it's compressed */ state->is_compressed = FALSE; + state->last_compression = UNKNOWN; /* save the current position for rewinding (only if reading) */ state->start = ws_lseek64(state->fd, 0, SEEK_CUR); @@ -1578,6 +1582,38 @@ file_iscompressed(FILE_T stream) return stream->is_compressed; } +/* Returns a wtap compression type. If we don't know the compression type, + * return WTAP_UNCOMPRESSED, but if our compression state is temporarily + * UNKNOWN because we need to reread compression headers, return the last + * known compression type. + */ +static wtap_compression_type +file_get_compression_type(FILE_T stream) +{ + if (stream->is_compressed) { + switch ((stream->compression == UNKNOWN) ? stream->last_compression : stream->compression) { + + case ZLIB: + case GZIP_AFTER_HEADER: + return WTAP_GZIP_COMPRESSED; + + case ZSTD: + return WTAP_ZSTD_COMPRESSED; + + case LZ4: + return WTAP_LZ4_COMPRESSED; + + case UNCOMPRESSED: + return WTAP_UNCOMPRESSED; + + default: /* UNKNOWN, should never happen if is_compressed is set */ + ws_assert_not_reached(); + return WTAP_UNCOMPRESSED; + } + } + return WTAP_UNCOMPRESSED; +} + int file_read(void *buf, unsigned int len, FILE_T file) { diff --git a/wiretap/wtap.h b/wiretap/wtap.h index a332e66f13..2a59e7f6e0 100644 --- a/wiretap/wtap.h +++ b/wiretap/wtap.h @@ -1774,7 +1774,9 @@ void wtap_rec_cleanup(wtap_rec *rec); */ typedef enum { WTAP_UNCOMPRESSED, - WTAP_GZIP_COMPRESSED + WTAP_GZIP_COMPRESSED, + WTAP_ZSTD_COMPRESSED, + WTAP_LZ4_COMPRESSED } wtap_compression_type; WS_DLL_PUBLIC |