#include <errno.h>
#include <signal.h>
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#include <epan/conversation.h>
#include <epan/epan_dissect.h>
#include <epan/tap.h>
+#include "stat_menu.h"
#include "tap_dfilter_dlg.h"
#include <epan/dissectors/packet-data.h>
+#include <epan/timestamp.h>
+
/* Win32 needs the O_BINARY flag for open() */
#ifndef O_BINARY
gboolean auto_scroll_live;
#endif
-static guint32 firstsec, firstusec;
-static guint32 prevsec, prevusec;
+static nstime_t first_ts;
+static nstime_t prev_ts;
static guint32 cum_bytes = 0;
static void cf_reset_state(capture_file *cf);
cf_cb_user_data = NULL;
}
+void
+cf_timestamp_auto_precision(capture_file *cf)
+{
+ int prec = timestamp_get_precision();
+
+
+ /* don't try to get the file's precision if none is opened */
+ if(cf->state == FILE_CLOSED) {
+ return;
+ }
+
+ /* if we are in auto mode, set precision of current file */
+ if(prec == TS_PREC_AUTO ||
+ prec == TS_PREC_AUTO_SEC ||
+ prec == TS_PREC_AUTO_DSEC ||
+ prec == TS_PREC_AUTO_CSEC ||
+ prec == TS_PREC_AUTO_MSEC ||
+ prec == TS_PREC_AUTO_USEC ||
+ prec == TS_PREC_AUTO_NSEC)
+ {
+ switch(wtap_file_tsprecision(cf->wth)) {
+ case(WTAP_FILE_TSPREC_SEC):
+ timestamp_set_precision(TS_PREC_AUTO_SEC);
+ break;
+ case(WTAP_FILE_TSPREC_DSEC):
+ timestamp_set_precision(TS_PREC_AUTO_DSEC);
+ break;
+ case(WTAP_FILE_TSPREC_CSEC):
+ timestamp_set_precision(TS_PREC_AUTO_CSEC);
+ break;
+ case(WTAP_FILE_TSPREC_MSEC):
+ timestamp_set_precision(TS_PREC_AUTO_MSEC);
+ break;
+ case(WTAP_FILE_TSPREC_USEC):
+ timestamp_set_precision(TS_PREC_AUTO_USEC);
+ break;
+ case(WTAP_FILE_TSPREC_NSEC):
+ timestamp_set_precision(TS_PREC_AUTO_NSEC);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ }
+}
+
cf_status_t
cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
{
wtap *wth;
gchar *err_info;
- int fd;
- struct stat cf_stat;
-
wth = wtap_open_offline(fname, err, &err_info, TRUE);
if (wth == NULL)
goto fail;
- /* Find the size of the file. */
- fd = wtap_fd(wth);
- if (fstat(fd, &cf_stat) < 0) {
- *err = errno;
- wtap_close(wth);
- goto fail;
- }
-
/* The open succeeded. Close whatever capture file we had open,
and fill in the information for this file. */
cf_reset_state(cf);
cf->state = FILE_READ_IN_PROGRESS;
cf->wth = wth;
- cf->filed = fd;
- cf->f_len = cf_stat.st_size;
+ cf->f_datalen = 0;
/* Set the file name because we need it to set the follow stream filter.
XXX - is that still true? We need it for other reasons, though,
/* If it's a temporary capture buffer file, mark it as not saved. */
cf->user_saved = !is_tempfile;
- cf->cd_t = wtap_file_type(cf->wth);
+ cf->cd_t = wtap_file_type(cf->wth);
cf->count = 0;
cf->displayed_count = 0;
cf->marked_count = 0;
cf->drops_known = FALSE;
cf->drops = 0;
- cf->esec = 0;
- cf->eusec = 0;
cf->snap = wtap_snapshot_length(cf->wth);
if (cf->snap == 0) {
/* Snapshot length not known. */
cf->snap = WTAP_MAX_PACKET_SIZE;
} else
cf->has_snap = TRUE;
- firstsec = 0, firstusec = 0;
- prevsec = 0, prevusec = 0;
+ nstime_set_zero(&cf->elapsed_time);
+ nstime_set_zero(&first_ts);
+ nstime_set_zero(&prev_ts);
cf->plist_chunk = g_mem_chunk_new("frame_data_chunk",
sizeof(frame_data),
G_ALLOC_AND_FREE);
g_assert(cf->plist_chunk);
+ /* change the time formats now, as we might have a new precision */
+ cf_change_time_formats(cf);
+
fileset_file_opened(fname);
return CF_OK;
packet_list_clear();
packet_list_thaw();
- cf->f_len = 0;
+ cf->f_datalen = 0;
cf->count = 0;
- cf->esec = 0;
- cf->eusec = 0;
+ nstime_set_zero(&cf->elapsed_time);
reset_tap_listeners();
long data_offset;
progdlg_t *progbar = NULL;
gboolean stop_flag;
- /*
- * XXX - should be "off_t", but Wiretap would need more work to handle
- * the full size of "off_t" on platforms where it's more than a "long"
- * as well.
- */
- long file_pos;
+ gint64 size, file_pos;
float prog_val;
- int fd;
- struct stat cf_stat;
GTimeVal start_time;
gchar status_str[100];
- int progbar_nextstep;
- int progbar_quantum;
+ gint64 progbar_nextstep;
+ gint64 progbar_quantum;
cum_bytes=0;
name_ptr = get_basename(cf->filename);
+ /* Find the size of the file. */
+ size = wtap_file_size(cf->wth, NULL);
+
/* Update the progress bar when it gets to this value. */
progbar_nextstep = 0;
/* When we reach the value that triggers a progress bar update,
bump that value by this amount. */
- progbar_quantum = cf->f_len/N_PROGBAR_UPDATES;
+ if (size >= 0)
+ progbar_quantum = size/N_PROGBAR_UPDATES;
+ else
+ progbar_quantum = 0;
packet_list_freeze();
g_get_current_time(&start_time);
while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
- /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
- when we update it, we have to run the GTK+ main loop to get it
- to repaint what's pending, and doing so may involve an "ioctl()"
- to see if there's any pending input from an X server, and doing
- that for every packet can be costly, especially on a big file. */
- if (data_offset >= progbar_nextstep) {
- file_pos = lseek(cf->filed, 0, SEEK_CUR);
- prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
- if (prog_val > 1.0) {
- /* The file probably grew while we were reading it.
- Update "cf->f_len", and try again. */
- fd = wtap_fd(cf->wth);
- if (fstat(fd, &cf_stat) >= 0) {
- cf->f_len = cf_stat.st_size;
- prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
+ if (size >= 0) {
+ /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
+ when we update it, we have to run the GTK+ main loop to get it
+ to repaint what's pending, and doing so may involve an "ioctl()"
+ to see if there's any pending input from an X server, and doing
+ that for every packet can be costly, especially on a big file. */
+ if (data_offset >= progbar_nextstep) {
+ file_pos = wtap_read_so_far(cf->wth, NULL);
+ prog_val = (gfloat) file_pos / (gfloat) size;
+ if (prog_val > 1.0) {
+ /* The file probably grew while we were reading it.
+ Update file size, and try again. */
+ size = wtap_file_size(cf->wth, NULL);
+ if (size >= 0)
+ prog_val = (gfloat) file_pos / (gfloat) size;
+ /* If it's still > 1, either "wtap_file_size()" failed (in which
+ case there's not much we can do about it), or the file
+ *shrank* (in which case there's not much we can do about
+ it); just clip the progress value at 1.0. */
+ if (prog_val > 1.0)
+ prog_val = 1.0;
}
- /* If it's still > 1, either the "fstat()" failed (in which
- case there's not much we can do about it), or the file
- *shrank* (in which case there's not much we can do about
- it); just clip the progress value at 1.0. */
- if (prog_val > 1.0)
- prog_val = 1.0;
- }
- if (progbar == NULL) {
- /* Create the progress bar if necessary */
- progbar = delayed_create_progress_dlg("Loading", name_ptr,
- &stop_flag, &start_time, prog_val);
- }
- if (progbar != NULL) {
- g_snprintf(status_str, sizeof(status_str),
- "%luKB of %luKB", file_pos / 1024, cf->f_len / 1024);
- update_progress_dlg(progbar, prog_val, status_str);
- }
- progbar_nextstep += progbar_quantum;
+ if (progbar == NULL) {
+ /* Create the progress bar if necessary */
+ progbar = delayed_create_progress_dlg("Loading", name_ptr,
+ &stop_flag, &start_time, prog_val);
+ }
+ if (progbar != NULL) {
+ g_snprintf(status_str, sizeof(status_str),
+ "%" PRId64 "KB of %" PRId64 "KB",
+ file_pos / 1024, size / 1024);
+ update_progress_dlg(progbar, prog_val, status_str);
+ }
+ progbar_nextstep += progbar_quantum;
+ }
}
if (stop_flag) {
{
gchar *err_info;
long data_offset;
- int fd;
- struct stat cf_stat;
-
if(cf->wth == NULL) {
cf_close(cf);
/* We're done reading sequentially through the file. */
cf->state = FILE_READ_DONE;
- /* we have to update the f_len field */
- /* Find the size of the file. */
- fd = wtap_fd(cf->wth);
- if (fstat(fd, &cf_stat) >= 0) {
- cf->f_len = cf_stat.st_size;
- }
-
/* We're done reading sequentially through the file; close the
sequential I/O side, to free up memory it requires. */
wtap_sequential_close(cf->wth);
/* If we don't have the time stamp of the first packet in the
capture, it's because this is the first packet. Save the time
stamp of this packet as the time stamp of the first packet. */
- if (!firstsec && !firstusec) {
- firstsec = fdata->abs_secs;
- firstusec = fdata->abs_usecs;
+ if (nstime_is_zero(&first_ts)) {
+ first_ts = fdata->abs_ts;
}
/* if this frames is marked as a reference time frame, reset
firstsec and firstusec to this frame */
if(fdata->flags.ref_time){
- firstsec = fdata->abs_secs;
- firstusec = fdata->abs_usecs;
+ first_ts = fdata->abs_ts;
}
/* If we don't have the time stamp of the previous displayed packet,
it's because this is the first displayed packet. Save the time
stamp of this packet as the time stamp of the previous displayed
packet. */
- if (!prevsec && !prevusec) {
- prevsec = fdata->abs_secs;
- prevusec = fdata->abs_usecs;
+ if (nstime_is_zero(&prev_ts)) {
+ prev_ts = fdata->abs_ts;
}
/* Get the time elapsed between the first packet and this packet. */
- compute_timestamp_diff(&fdata->rel_secs, &fdata->rel_usecs,
- fdata->abs_secs, fdata->abs_usecs, firstsec, firstusec);
+ nstime_delta(&fdata->rel_ts, &fdata->abs_ts, &first_ts);
/* If it's greater than the current elapsed time, set the elapsed time
to it (we check for "greater than" so as not to be confused by
time moving backwards). */
- if ((gint32)cf->esec < fdata->rel_secs
- || ((gint32)cf->esec == fdata->rel_secs && (gint32)cf->eusec < fdata->rel_usecs)) {
- cf->esec = fdata->rel_secs;
- cf->eusec = fdata->rel_usecs;
+ if ((gint32)cf->elapsed_time.secs < fdata->rel_ts.secs
+ || ((gint32)cf->elapsed_time.secs == fdata->rel_ts.secs && (gint32)cf->elapsed_time.nsecs < fdata->rel_ts.nsecs)) {
+ cf->elapsed_time = fdata->rel_ts;
}
/* Get the time elapsed between the previous displayed packet and
this packet. */
- compute_timestamp_diff(&fdata->del_secs, &fdata->del_usecs,
- fdata->abs_secs, fdata->abs_usecs, prevsec, prevusec);
+ nstime_delta(&fdata->del_ts, &fdata->abs_ts, &prev_ts);
/* If either
/* Set the time of the previous displayed frame to the time of this
frame. */
- prevsec = fdata->abs_secs;
- prevusec = fdata->abs_usecs;
+ prev_ts = fdata->abs_ts;
cf->displayed_count++;
} else {
/* Allocate the next list entry, and add it to the list. */
fdata = g_mem_chunk_alloc(cf->plist_chunk);
+ fdata->num = 0;
fdata->next = NULL;
fdata->prev = NULL;
fdata->pfd = NULL;
fdata->cap_len = phdr->caplen;
fdata->file_off = offset;
fdata->lnk_t = phdr->pkt_encap;
- fdata->abs_secs = phdr->ts.tv_sec;
- fdata->abs_usecs = phdr->ts.tv_usec;
fdata->flags.encoding = CHAR_ASCII;
fdata->flags.visited = 0;
fdata->flags.marked = 0;
fdata->flags.ref_time = 0;
+ fdata->abs_ts = *((nstime_t *) &phdr->ts);
+
passed = TRUE;
if (cf->rfcode) {
edt = epan_dissect_new(TRUE, FALSE);
cf->plist_end = fdata;
cf->count++;
- cf->f_len = offset + phdr->caplen;
+ cf->f_datalen = offset + phdr->caplen;
fdata->num = cf->count;
add_packet_to_packet_list(fdata, cf, pseudo_header, buf, TRUE);
} else {
long data_offset;
progdlg_t *progbar = NULL;
gboolean stop_flag;
- /*
- * XXX - should be "off_t", but Wiretap would need more work to handle
- * the full size of "off_t" on platforms where it's more than a "long"
- * as well.
- */
- long f_len, file_pos;
- float prog_val;
- GTimeVal start_time;
- gchar status_str[100];
- int progbar_nextstep;
- int progbar_quantum;
+ gint64 f_len, file_pos;
+ float prog_val;
+ GTimeVal start_time;
+ gchar status_str[100];
+ gint64 progbar_nextstep;
+ gint64 progbar_quantum;
/* open the input files */
if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
pdh = wtap_dump_fdopen(out_fd, file_type,
merge_select_frame_type(in_file_count, in_files),
- merge_max_snapshot_length(in_file_count, in_files), &open_err);
+ merge_max_snapshot_length(in_file_count, in_files),
+ FALSE /* compressed */, &open_err);
if (pdh == NULL) {
close(out_fd);
merge_close_in_files(in_file_count, in_files);
/* Get the sum of the seek positions in all of the files. */
file_pos = 0;
for (i = 0; i < in_file_count; i++)
- file_pos += lseek(wtap_fd(in_files[i].wth), 0, SEEK_CUR);
+ file_pos += wtap_read_so_far(in_files[i].wth, NULL);
prog_val = (gfloat) file_pos / (gfloat) f_len;
if (prog_val > 1.0) {
/* Some file probably grew while we were reading it.
}
if (progbar != NULL) {
g_snprintf(status_str, sizeof(status_str),
- "%luKB of %luKB", file_pos / 1024, f_len / 1024);
+ "%" PRId64 "KB of %" PRId64 "KB",
+ file_pos / 1024, f_len / 1024);
update_progress_dlg(progbar, prog_val, status_str);
}
progbar_nextstep += progbar_quantum;
/* Iterate through the list of frames. Call a routine for each frame
to check whether it should be displayed and, if so, add it to
the display list. */
- firstsec = 0;
- firstusec = 0;
- prevsec = 0;
- prevusec = 0;
+ nstime_set_zero(&first_ts);
+ nstime_set_zero(&prev_ts);
/* Update the progress bar when it gets to this value. */
progbar_nextstep = 0;
PSP_FAILED
} psp_return_t;
-psp_return_t
+static psp_return_t
process_specified_packets(capture_file *cf, packet_range_t *range,
const char *string1, const char *string2,
gboolean (*callback)(capture_file *, frame_data *,
static gboolean
retap_packet(capture_file *cf _U_, frame_data *fdata,
union wtap_pseudo_header *pseudo_header, const guint8 *pd,
- void *argsp _U_)
+ void *argsp)
{
+ column_info *cinfo = argsp;
epan_dissect_t *edt;
/* If we have tap listeners, allocate a protocol tree root node, so that
be evaluated. */
edt = epan_dissect_new(num_tap_filters != 0, FALSE);
tap_queue_init(edt);
- epan_dissect_run(edt, pseudo_header, pd, fdata, NULL);
+ epan_dissect_run(edt, pseudo_header, pd, fdata, cinfo);
tap_push_tapped_queue(edt);
epan_dissect_free(edt);
}
cf_read_status_t
-cf_retap_packets(capture_file *cf)
+cf_retap_packets(capture_file *cf, gboolean do_columns)
{
packet_range_t range;
packet_range_process_init(&range);
switch (process_specified_packets(cf, &range, "Refiltering statistics on",
"all packets", retap_packet,
- NULL)) {
+ do_columns ? &cf->cinfo : NULL)) {
case PSP_FINISHED:
/* Completed successfully. */
return CF_OK;
int first, last;
gboolean sorted_by_frame_column;
+
+ /* adjust timestamp precision if auto is selected */
+ cf_timestamp_auto_precision(cf);
+
/* Are there any columns with time stamps in the "command-line-specified"
format?
int err;
/* init the wtap header for saving */
- hdr.ts.tv_sec = fdata->abs_secs;
- hdr.ts.tv_usec = fdata->abs_usecs;
+ hdr.ts = *(struct wtap_nstime *) &fdata->abs_ts;
hdr.caplen = fdata->cap_len;
hdr.len = fdata->pkt_len;
hdr.pkt_encap = fdata->lnk_t;
}
cf_status_t
-cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_format)
+cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_format, gboolean compressed)
{
gchar *from_filename;
int err;
wtap_dumper *pdh;
save_callback_args_t callback_args;
- cf_callback_invoke(cf_cb_file_safe_started, fname);
+ cf_callback_invoke(cf_cb_file_safe_started, (gpointer) fname);
/* don't write over an existing file. */
/* this should've been already checked by our caller, just to be sure... */
/* Either we're filtering packets, or we're saving in a different
format; we can't do that by copying or moving the capture file,
we have to do it by writing the packets out in Wiretap. */
- pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap, &err);
+ pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap,
+ compressed, &err);
if (pdh == NULL) {
cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
goto fail;
filename);
break;
+ case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+ "Gzip compression not supported by this file type.");
+ break;
+
default:
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
"The file \"%s\" could not be %s: %s.",