aboutsummaryrefslogtreecommitdiffstats
path: root/wiretap
diff options
context:
space:
mode:
authorJohn Thacker <johnthacker@gmail.com>2021-09-10 20:46:54 -0400
committerWireshark GitLab Utility <gerald+gitlab-utility@wireshark.org>2021-09-11 22:37:25 +0000
commit6fe68991df128960f5ea5c3615a90ef2a5ab22b7 (patch)
tree676d8de4c4a8ac7fd6f61634f4c2e93339806752 /wiretap
parent07a31d29189a9e55d17d4aeda2ed9c30a6cd0722 (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.c66
-rw-r--r--wiretap/wtap.h4
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