wiretap: fix truncated reads while reading compressed file formats

A lot of file dissectors (pcapng, json, etc.) assumed that the packet
size is equal to the file size. This is not true if the file was
compressed and could result in silently truncating reads or failing to
open a file (if the compressed file is larger than the actual data).

Observe that a lot of file dissectors are simply copies of each other.
Move the fixed implementation to wtap.c and reuse the methods everywhere
else. While at it, avoid an unnecessary large allocation/read in
ruby_marshal.

Change-Id: I8e9cd0af9c4d1bd37789a3b509146ae2182a5379
Reviewed-on: https://code.wireshark.org/review/30570
Petri-Dish: Peter Wu <peter@lekensteyn.nl>
Reviewed-by: Dario Lombardo <lomato@gmail.com>
Tested-by: Dario Lombardo <lomato@gmail.com>
Tested-by: Petri Dish Buildbot
Reviewed-by: Michael Mann <mmann78@netscape.net>
This commit is contained in:
Peter Wu 2018-11-10 23:03:16 +01:00 committed by Michael Mann
parent a0bb983834
commit 961f1388e4
10 changed files with 136 additions and 454 deletions

View File

@ -15,6 +15,7 @@ import os.path
import subprocesstest
import sys
import unittest
import fixtures
# XXX Currently unused. It would be nice to be able to use this below.
time_output_args = ('-Tfields', '-e', 'frame.number', '-e', 'frame.time_epoch', '-e', 'frame.time_delta')
@ -110,3 +111,16 @@ class case_fileformat_pcapng(subprocesstest.SubprocessTestCase):
)
self.assertTrue(self.diffOutput(capture_proc.stdout_str, baseline_str, 'tshark', baseline_file))
@fixtures.mark_usefixtures('test_env')
@fixtures.uses_fixtures
class case_fileformat_mime(subprocesstest.SubprocessTestCase):
def test_mime_pcapng_gz(self, cmd_tshark, dirs):
'''Test that the full uncompressed contents is shown.'''
capture_file = os.path.join(dirs.capture_dir, 'icmp.pcapng.gz')
proc = self.runProcess((cmd_tshark,
'-r', capture_file,
'-Xread_format:MIME Files Format',
'-Tfields', '-e', 'frame.len', '-e', 'pcapng.block.length',
))
self.assertEqual(proc.stdout_str.strip(), '480\t128,128,88,88,132,132,132,132')

View File

@ -22,71 +22,6 @@
#define BER_UNI_TAG_SEQ 16 /* SEQUENCE, SEQUENCE OF */
#define BER_UNI_TAG_SET 17 /* SET, SET OF */
static gboolean ber_read_file(wtap *wth, FILE_T fh, wtap_rec *rec,
Buffer *buf, int *err, gchar **err_info)
{
gint64 file_size;
int packet_size;
if ((file_size = wtap_file_size(wth, err)) == -1)
return FALSE;
if (file_size > G_MAXINT) {
/*
* Probably a corrupt capture file; don't blow up trying
* to allocate space for an immensely-large packet.
*/
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("ber: File has %" G_GINT64_MODIFIER "d-byte packet, bigger than maximum of %u",
file_size, G_MAXINT);
return FALSE;
}
packet_size = (int)file_size;
rec->rec_type = REC_TYPE_PACKET;
rec->presence_flags = 0; /* yes, we have no bananas^Wtime stamp */
rec->rec_header.packet_header.caplen = packet_size;
rec->rec_header.packet_header.len = packet_size;
rec->ts.secs = 0;
rec->ts.nsecs = 0;
return wtap_read_packet_bytes(fh, buf, packet_size, err, err_info);
}
static gboolean ber_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
{
gint64 offset;
*err = 0;
offset = file_tell(wth->fh);
/* there is only ever one packet */
if (offset != 0)
return FALSE;
*data_offset = offset;
return ber_read_file(wth, wth->fh, &wth->rec, wth->rec_data, err, err_info);
}
static gboolean ber_seek_read(wtap *wth, gint64 seek_off, wtap_rec *rec,
Buffer *buf, int *err, gchar **err_info)
{
/* there is only one packet */
if(seek_off > 0) {
*err = 0;
return FALSE;
}
if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
return FALSE;
return ber_read_file(wth, wth->random_fh, rec, buf, err, err_info);
}
wtap_open_return_val ber_open(wtap *wth, int *err, gchar **err_info)
{
#define BER_BYTES_TO_CHECK 8
@ -159,8 +94,8 @@ wtap_open_return_val ber_open(wtap *wth, int *err, gchar **err_info)
wth->file_encap = WTAP_ENCAP_BER;
wth->snapshot_length = 0;
wth->subtype_read = ber_read;
wth->subtype_seek_read = ber_seek_read;
wth->subtype_read = wtap_full_file_read;
wth->subtype_seek_read = wtap_full_file_seek_read;
wth->file_tsprec = WTAP_TSPREC_SEC;
return WTAP_OPEN_MINE;

View File

@ -15,76 +15,16 @@
#include "json.h"
#include <wsutil/wsjson.h>
static gboolean json_read_file(wtap *wth, FILE_T fh, wtap_rec *rec,
Buffer *buf, int *err, gchar **err_info)
{
gint64 file_size;
int packet_size;
if ((file_size = wtap_file_size(wth, err)) == -1)
return FALSE;
if (file_size > MAX_FILE_SIZE) {
/*
* Don't blow up trying to allocate space for an
* immensely-large file.
*/
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("json: File has %" G_GINT64_MODIFIER "d-byte packet, bigger than maximum of %u",
file_size, MAX_FILE_SIZE);
return FALSE;
}
packet_size = (int)file_size;
rec->rec_type = REC_TYPE_PACKET;
rec->presence_flags = 0; /* yes, we have no bananas^Wtime stamp */
rec->rec_header.packet_header.caplen = packet_size;
rec->rec_header.packet_header.len = packet_size;
rec->ts.secs = 0;
rec->ts.nsecs = 0;
return wtap_read_packet_bytes(fh, buf, packet_size, err, err_info);
}
static gboolean json_seek_read(wtap *wth, gint64 seek_off, wtap_rec *rec, Buffer *buf,
int *err, gchar **err_info)
{
/* there is only one packet */
if (seek_off > 0) {
*err = 0;
return FALSE;
}
if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
return FALSE;
return json_read_file(wth, wth->random_fh, rec, buf, err, err_info);
}
static gboolean json_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
{
gint64 offset;
*err = 0;
offset = file_tell(wth->fh);
/* there is only ever one packet */
if (offset != 0)
return FALSE;
*data_offset = offset;
return json_read_file(wth, wth->fh, &wth->rec, wth->rec_data, err, err_info);
}
/* Maximum size of json file. */
#define MAX_FILE_SIZE (50*1024*1024)
wtap_open_return_val json_open(wtap *wth, int *err, gchar **err_info)
{
guint8* filebuf;
int bytes_read;
/* XXX checking the full file contents might be a bit expensive, maybe
* resort to simpler heuristics like '{' or '[' (with some other chars)? */
filebuf = (guint8*)g_malloc0(MAX_FILE_SIZE);
if (!filebuf)
return WTAP_OPEN_ERROR;
@ -115,8 +55,8 @@ wtap_open_return_val json_open(wtap *wth, int *err, gchar **err_info)
wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_JSON;
wth->file_encap = WTAP_ENCAP_JSON;
wth->file_tsprec = WTAP_TSPREC_SEC;
wth->subtype_read = json_read;
wth->subtype_seek_read = json_seek_read;
wth->subtype_read = wtap_full_file_read;
wth->subtype_seek_read = wtap_full_file_seek_read;
wth->snapshot_length = 0;
g_free(filebuf);

View File

@ -13,18 +13,6 @@
#include "wtap.h"
/*
* Impose a not-too-large limit on the maximum file size, to avoid eating
* up 99% of the (address space, swap partition, disk space for swap/page
* files); if we were to return smaller chunks and let the dissector do
* reassembly, it would *still* have to allocate a buffer the size of
* the file, so it's not as if we'd neve try to allocate a buffer the
* size of the file.
*
* For now, go for 50MB.
*/
#define MAX_FILE_SIZE (50*1024*1024)
wtap_open_return_val json_open(wtap *wth, int *err, gchar **err_info);
#endif

View File

@ -81,83 +81,6 @@ static const mime_files_t magic_files[] = {
#define N_MAGIC_TYPES (sizeof(magic_files) / sizeof(magic_files[0]))
/*
* Impose a not-too-large limit on the maximum file size, to avoid eating
* up 99% of the (address space, swap partition, disk space for swap/page
* files); if we were to return smaller chunks and let the dissector do
* reassembly, it would *still* have to allocate a buffer the size of
* the file, so it's not as if we'd neve try to allocate a buffer the
* size of the file.
*/
#define MAX_FILE_SIZE G_MAXINT
static gboolean
mime_read_file(wtap *wth, FILE_T fh, wtap_rec *rec,
Buffer *buf, int *err, gchar **err_info)
{
gint64 file_size;
int packet_size;
if ((file_size = wtap_file_size(wth, err)) == -1)
return FALSE;
if (file_size > MAX_FILE_SIZE) {
/*
* Don't blow up trying to allocate space for an
* immensely-large file.
*/
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("mime_file: File has %" G_GINT64_MODIFIER "d-byte packet, bigger than maximum of %u",
file_size, MAX_FILE_SIZE);
return FALSE;
}
packet_size = (int)file_size;
rec->rec_type = REC_TYPE_PACKET;
rec->presence_flags = 0; /* yes, we have no bananas^Wtime stamp */
rec->rec_header.packet_header.caplen = packet_size;
rec->rec_header.packet_header.len = packet_size;
rec->ts.secs = 0;
rec->ts.nsecs = 0;
return wtap_read_packet_bytes(fh, buf, packet_size, err, err_info);
}
static gboolean
mime_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
{
gint64 offset;
*err = 0;
offset = file_tell(wth->fh);
/* there is only ever one packet */
if (offset != 0)
return FALSE;
*data_offset = offset;
return mime_read_file(wth, wth->fh, &wth->rec, wth->rec_data, err, err_info);
}
static gboolean
mime_seek_read(wtap *wth, gint64 seek_off, wtap_rec *rec, Buffer *buf, int *err, gchar **err_info)
{
/* there is only one packet */
if (seek_off > 0) {
*err = 0;
return FALSE;
}
if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
return FALSE;
return mime_read_file(wth, wth->random_fh, rec, buf, err, err_info);
}
wtap_open_return_val
mime_file_open(wtap *wth, int *err, gchar **err_info)
{
@ -206,8 +129,8 @@ mime_file_open(wtap *wth, int *err, gchar **err_info)
wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_MIME;
wth->file_encap = WTAP_ENCAP_MIME;
wth->file_tsprec = WTAP_TSPREC_SEC;
wth->subtype_read = mime_read;
wth->subtype_seek_read = mime_seek_read;
wth->subtype_read = wtap_full_file_read;
wth->subtype_seek_read = wtap_full_file_seek_read;
wth->snapshot_length = 0;
return WTAP_OPEN_MINE;

View File

@ -18,39 +18,6 @@
#include <string.h>
static gboolean rfc7468_read_file(wtap *wth, FILE_T fh, wtap_rec *rec,
Buffer *buf, int *err, gchar **err_info)
{
gint64 file_size;
int packet_size;
if ((file_size = wtap_file_size(wth, err)) == -1)
return FALSE;
if (file_size > G_MAXINT) {
/*
* Probably a corrupt capture file; don't blow up trying
* to allocate space for an immensely-large packet.
*/
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("rfc7468: File has %" G_GINT64_MODIFIER "d-byte packet, bigger than maximum of %u",
file_size, G_MAXINT);
return FALSE;
}
packet_size = (int)file_size;
rec->rec_type = REC_TYPE_PACKET;
rec->presence_flags = 0; /* yes, we have no bananas^Wtime stamp */
rec->rec_header.packet_header.caplen = packet_size;
rec->rec_header.packet_header.len = packet_size;
rec->ts.secs = 0;
rec->ts.nsecs = 0;
return wtap_read_packet_bytes(fh, buf, packet_size, err, err_info);
}
/* 128 bytes should be enough to contain any line. Strictly speaking, 64 is
enough, but we provide some leeway to accomodate nonconformant producers and
trailing whitespace. The 2 extra bytes are for the trailing newline and NUL
@ -79,38 +46,6 @@ static char *read_complete_text_line(char line[MAX_LINE_LENGTH], FILE_T fh, int
return line_end;
}
static gboolean rfc7468_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
{
gint64 offset;
*err = 0;
offset = file_tell(wth->fh);
/* there is only ever one packet */
if (offset != 0)
return FALSE;
*data_offset = offset;
return rfc7468_read_file(wth, wth->fh, &wth->rec, wth->rec_data, err, err_info);
}
static gboolean rfc7468_seek_read(wtap *wth, gint64 seek_off, wtap_rec *rec,
Buffer *buf, int *err, gchar **err_info)
{
/* there is only one packet */
if (seek_off > 0) {
*err = 0;
return FALSE;
}
if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
return FALSE;
return rfc7468_read_file(wth, wth->random_fh, rec, buf, err, err_info);
}
//
// Arbitrary value - we don't want to read all of a huge non-RFC 7468 file
// only to find no pre-encapsulation boundary.
@ -154,8 +89,8 @@ wtap_open_return_val rfc7468_open(wtap *wth, int *err, gchar **err_info)
wth->snapshot_length = 0;
wth->file_tsprec = WTAP_TSPREC_SEC;
wth->subtype_read = rfc7468_read;
wth->subtype_seek_read = rfc7468_seek_read;
wth->subtype_read = wtap_full_file_read;
wth->subtype_seek_read = wtap_full_file_seek_read;
return WTAP_OPEN_MINE;
}

View File

@ -16,83 +16,6 @@
#include "ruby_marshal.h"
/*
* Impose a not-too-large limit on the maximum file size, to avoid eating
* up 99% of the (address space, swap partition, disk space for swap/page
* files); if we were to return smaller chunks and let the dissector do
* reassembly, it would *still* have to allocate a buffer the size of
* the file, so it's not as if we'd neve try to allocate a buffer the
* size of the file.
*
* For now, go for 50MB.
*/
#define MAX_FILE_SIZE (50*1024*1024)
static gboolean ruby_marshal_read_file(wtap *wth, FILE_T fh, wtap_rec *rec,
Buffer *buf, int *err, gchar **err_info)
{
gint64 file_size;
int packet_size;
if ((file_size = wtap_file_size(wth, err)) == -1)
return FALSE;
if (file_size > MAX_FILE_SIZE) {
/*
* Don't blow up trying to allocate space for an
* immensely-large file.
*/
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("ruby_marshal: File has %" G_GINT64_MODIFIER "d-byte packet, bigger than maximum of %u",
file_size, MAX_FILE_SIZE);
return FALSE;
}
packet_size = (int)file_size;
rec->rec_type = REC_TYPE_PACKET;
rec->presence_flags = 0;
rec->rec_header.packet_header.caplen = packet_size;
rec->rec_header.packet_header.len = packet_size;
rec->ts.secs = 0;
rec->ts.nsecs = 0;
return wtap_read_packet_bytes(fh, buf, packet_size, err, err_info);
}
static gboolean ruby_marshal_seek_read(wtap *wth, gint64 seek_off, wtap_rec *rec, Buffer *buf,
int *err, gchar **err_info)
{
/* there is only one packet */
if (seek_off > 0) {
*err = 0;
return FALSE;
}
if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
return FALSE;
return ruby_marshal_read_file(wth, wth->random_fh, rec, buf, err, err_info);
}
static gboolean ruby_marshal_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
{
gint64 offset;
*err = 0;
offset = file_tell(wth->fh);
/* there is only ever one packet */
if (offset != 0)
return FALSE;
*data_offset = offset;
return ruby_marshal_read_file(wth, wth->fh, &wth->rec, wth->rec_data, err, err_info);
}
static gboolean is_ruby_marshal(const guint8* filebuf)
{
if (filebuf[0] != RUBY_MARSHAL_MAJOR)
@ -128,44 +51,32 @@ static gboolean is_ruby_marshal(const guint8* filebuf)
wtap_open_return_val ruby_marshal_open(wtap *wth, int *err, gchar **err_info)
{
guint8* filebuf;
/* The size of this buffer should match the expectations of is_ruby_marshal */
guint8 filebuf[3];
int bytes_read;
filebuf = (guint8*)g_malloc0(MAX_FILE_SIZE);
if (!filebuf)
return WTAP_OPEN_ERROR;
bytes_read = file_read(filebuf, MAX_FILE_SIZE, wth->fh);
bytes_read = file_read(filebuf, sizeof(filebuf), wth->fh);
if (bytes_read < 0) {
/* Read error. */
*err = file_error(wth->fh, err_info);
g_free(filebuf);
return WTAP_OPEN_ERROR;
}
if (bytes_read == 0) {
/* empty file, not *anybody's* */
g_free(filebuf);
return WTAP_OPEN_NOT_MINE;
}
if (!is_ruby_marshal(filebuf)) {
g_free(filebuf);
if (bytes_read != sizeof(filebuf) || !is_ruby_marshal(filebuf)) {
return WTAP_OPEN_NOT_MINE;
}
if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
g_free(filebuf);
return WTAP_OPEN_ERROR;
}
wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_RUBY_MARSHAL;
wth->file_encap = WTAP_ENCAP_RUBY_MARSHAL;
wth->file_tsprec = WTAP_TSPREC_SEC;
wth->subtype_read = ruby_marshal_read;
wth->subtype_seek_read = ruby_marshal_seek_read;
wth->subtype_read = wtap_full_file_read;
wth->subtype_seek_read = wtap_full_file_seek_read;
wth->snapshot_length = 0;
g_free(filebuf);
return WTAP_OPEN_MINE;
}

View File

@ -14,72 +14,6 @@
#include <wsutil/buffer.h>
#include "tnef.h"
static gboolean tnef_read_file(wtap *wth, FILE_T fh, wtap_rec *rec,
Buffer *buf, int *err, gchar **err_info)
{
gint64 file_size;
int packet_size;
if ((file_size = wtap_file_size(wth, err)) == -1)
return FALSE;
if (file_size > WTAP_MAX_PACKET_SIZE_STANDARD) {
/*
* Probably a corrupt capture file; don't blow up trying
* to allocate space for an immensely-large packet.
*/
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("tnef: File has %" G_GINT64_MODIFIER "d-byte packet, bigger than maximum of %u",
file_size, WTAP_MAX_PACKET_SIZE_STANDARD);
return FALSE;
}
packet_size = (int)file_size;
rec->rec_type = REC_TYPE_PACKET;
rec->presence_flags = 0; /* yes, we have no bananas^Wtime stamp */
rec->rec_header.packet_header.caplen = packet_size;
rec->rec_header.packet_header.len = packet_size;
rec->ts.secs = 0;
rec->ts.nsecs = 0;
return wtap_read_packet_bytes(fh, buf, packet_size, err, err_info);
}
static gboolean tnef_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
{
gint64 offset;
*err = 0;
offset = file_tell(wth->fh);
/* there is only ever one packet */
if (offset)
return FALSE;
*data_offset = offset;
return tnef_read_file(wth, wth->fh, &wth->rec, wth->rec_data, err, err_info);
}
static gboolean tnef_seek_read(wtap *wth, gint64 seek_off,
wtap_rec *rec,
Buffer *buf, int *err, gchar **err_info)
{
/* there is only one packet */
if(seek_off > 0) {
*err = 0;
return FALSE;
}
if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
return FALSE;
return tnef_read_file(wth, wth->random_fh, rec, buf, err, err_info);
}
wtap_open_return_val tnef_open(wtap *wth, int *err, gchar **err_info)
{
guint32 magic;
@ -99,8 +33,8 @@ wtap_open_return_val tnef_open(wtap *wth, int *err, gchar **err_info)
wth->file_encap = WTAP_ENCAP_TNEF;
wth->snapshot_length = 0;
wth->subtype_read = tnef_read;
wth->subtype_seek_read = tnef_seek_read;
wth->subtype_read = wtap_full_file_read;
wth->subtype_seek_read = wtap_full_file_seek_read;
wth->file_tsprec = WTAP_TSPREC_SEC;
return WTAP_OPEN_MINE;

View File

@ -309,6 +309,19 @@ gboolean
wtap_read_packet_bytes(FILE_T fh, Buffer *buf, guint length, int *err,
gchar **err_info);
/*
* Implementation of wth->subtype_read that reads the full file contents
* as a single packet.
*/
gboolean
wtap_full_file_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset);
/*
* Implementation of wth->subtype_seek_read that reads the full file contents
* as a single packet.
*/
gboolean
wtap_full_file_seek_read(wtap *wth, gint64 seek_off, wtap_rec *rec, Buffer *buf, int *err, gchar **err_info);
#endif /* __WTAP_INT_H__ */
/*

View File

@ -1450,6 +1450,95 @@ wtap_seek_read(wtap *wth, gint64 seek_off, wtap_rec *rec, Buffer *buf,
return TRUE;
}
static gboolean
wtap_full_file_read_file(wtap *wth, FILE_T fh, wtap_rec *rec, Buffer *buf, int *err, gchar **err_info)
{
gint64 file_size;
int packet_size = 0;
const int block_size = 1024 * 1024;
if ((file_size = wtap_file_size(wth, err)) == -1)
return FALSE;
if (file_size > G_MAXINT) {
/*
* Avoid allocating space for an immensely-large file.
*/
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("%s: File has %" G_GINT64_MODIFIER "d-byte packet, bigger than maximum of %u",
wtap_encap_short_string(wth->file_encap), file_size, G_MAXINT);
return FALSE;
}
/*
* Compressed files might expand to a larger size than the actual file
* size. Try to read the full size and then read in smaller increments
* to avoid frequent memory reallocations.
*/
int buffer_size = block_size * (1 + (int)file_size / block_size);
for (;;) {
if (buffer_size <= 0) {
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("%s: Uncompressed file is bigger than maximum of %u",
wtap_encap_short_string(wth->file_encap), G_MAXINT);
return FALSE;
}
ws_buffer_assure_space(buf, buffer_size);
int nread = file_read(ws_buffer_start_ptr(buf) + packet_size, buffer_size - packet_size, fh);
if (nread < 0) {
*err = file_error(fh, err_info);
if (*err == 0)
*err = WTAP_ERR_BAD_FILE;
return FALSE;
}
packet_size += nread;
if (packet_size != buffer_size) {
/* EOF */
break;
}
buffer_size += block_size;
}
rec->rec_type = REC_TYPE_PACKET;
rec->presence_flags = 0; /* yes, we have no bananas^Wtime stamp */
rec->ts.secs = 0;
rec->ts.nsecs = 0;
rec->rec_header.packet_header.caplen = packet_size;
rec->rec_header.packet_header.len = packet_size;
return TRUE;
}
gboolean
wtap_full_file_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
{
gint64 offset = file_tell(wth->fh);
/* There is only one packet with the full file contents. */
if (offset != 0) {
*err = 0;
return FALSE;
}
*data_offset = offset;
return wtap_full_file_read_file(wth, wth->fh, &wth->rec, wth->rec_data, err, err_info);
}
gboolean
wtap_full_file_seek_read(wtap *wth, gint64 seek_off, wtap_rec *rec, Buffer *buf, int *err, gchar **err_info)
{
/* There is only one packet with the full file contents. */
if (seek_off > 0) {
*err = 0;
return FALSE;
}
if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
return FALSE;
return wtap_full_file_read_file(wth, wth->random_fh, rec, buf, err, err_info);
}
/*
* Initialize the library.
*/