aboutsummaryrefslogtreecommitdiffstats
path: root/file.c
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2004-10-29 00:36:52 +0000
committerGuy Harris <guy@alum.mit.edu>2004-10-29 00:36:52 +0000
commite09e12621adefe25905804de8ba7e2687c2c72f2 (patch)
treec12d542a15efb8683f2228ca69aff9142672b6a7 /file.c
parent24f30a8850a1f11ae2470fd5124e827f443fa62b (diff)
The common merge code merely needs to offer the abstraction of routines
that return the next packet from a set of {chronologically sorted, sequential-by-file} packets; it doesn't need to have a loop over all those packets, or any code to write packets. Supply those abstractions, change the code that merges packets to do its own writing, and have the Ethereal version manage a progress bar and have the mergecap version print packet numbers in verbose mode, as the common merge code used to do. svn path=/trunk/; revision=12427
Diffstat (limited to 'file.c')
-rw-r--r--file.c141
1 files changed, 109 insertions, 32 deletions
diff --git a/file.c b/file.c
index 4e3149cbbb..e624f6d096 100644
--- a/file.c
+++ b/file.c
@@ -975,60 +975,136 @@ cf_merge_files(const char *out_filename, int out_fd, int in_file_count,
char *const *in_filenames, int file_type, gboolean do_append)
{
merge_in_file_t *in_files;
- merge_out_file_t out_file;
- int err, close_err;
+ wtap *wth;
+ wtap_dumper *pdh;
+ int open_err, read_err, write_err, close_err;
gchar *err_info;
int err_fileno;
- merge_status_e status;
int i;
char errmsg_errno[1024+1];
gchar err_str[2048+1];
char *errmsg;
+ gboolean got_read_error = FALSE, got_write_error = FALSE;
+ 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;
/* open the input files */
if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
- &err, &err_info, &err_fileno)) {
+ &open_err, &err_info, &err_fileno)) {
free(in_files);
- cf_open_failure_alert_box(in_filenames[err_fileno], err, err_info, FALSE, 0);
+ cf_open_failure_alert_box(in_filenames[err_fileno], open_err, err_info,
+ FALSE, 0);
return FALSE;
}
- if (!merge_open_outfile(&out_file, out_fd, file_type,
+ 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), &err)) {
+ merge_max_snapshot_length(in_file_count, in_files), &open_err);
+ if (pdh == NULL) {
merge_close_in_files(in_file_count, in_files);
free(in_files);
- cf_open_failure_alert_box(out_filename, err, err_info, TRUE, file_type);
+ cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
+ file_type);
return FALSE;
}
+ /* Get the sum of the sizes of all the files. */
+ f_len = 0;
+ for (i = 0; i < in_file_count; i++)
+ f_len += in_files[i].size;
+
+ /* 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 = f_len/N_PROGBAR_UPDATES;
+
+ stop_flag = FALSE;
+ g_get_current_time(&start_time);
+
/* do the merge (or append) */
- if (do_append)
- status = merge_append_files(in_file_count, in_files, &out_file, &err);
- else
- status = merge_files(in_file_count, in_files, &out_file, &err);
+ for (;;) {
+ if (do_append)
+ wth = merge_append_read_packet(in_file_count, in_files, &read_err,
+ &err_info);
+ else
+ wth = merge_read_packet(in_file_count, in_files, &read_err,
+ &err_info);
+ if (wth == NULL) {
+ if (read_err != 0)
+ got_read_error = TRUE;
+ break;
+ }
- merge_close_in_files(in_file_count, in_files);
- if (status == MERGE_SUCCESS) {
- if (!merge_close_outfile(&out_file, &err))
- status = MERGE_WRITE_ERROR;
- } else
- merge_close_outfile(&out_file, &close_err);
+ /* Get the sum of the data offsets in all of the files. */
+ data_offset = 0;
+ for (i = 0; i < in_file_count; i++)
+ data_offset += in_files[i].data_offset;
+
+ if (data_offset >= progbar_nextstep) {
+ /* 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);
+ prog_val = (gfloat) file_pos / (gfloat) f_len;
+ if (prog_val > 1.0) {
+ /* Some file probably grew while we were reading it.
+ That "shouldn't happen", so we'll just clip the progress
+ value at 1.0. */
+ prog_val = 1.0;
+ }
+ if (progbar == NULL) {
+ /* Create the progress bar if necessary */
+ progbar = delayed_create_progress_dlg("Merging", "files",
+ &stop_flag, &start_time, prog_val);
+ }
+ if (progbar != NULL) {
+ g_snprintf(status_str, sizeof(status_str),
+ "%luKB of %luKB", file_pos / 1024, f_len / 1024);
+ update_progress_dlg(progbar, prog_val, status_str);
+ }
+ progbar_nextstep += progbar_quantum;
+ }
- switch (status) {
+ if (!wtap_dump(pdh, wtap_phdr(wth), wtap_pseudoheader(wth),
+ wtap_buf_ptr(wth), &write_err)) {
+ got_write_error = TRUE;
+ break;
+ }
+ }
- case MERGE_SUCCESS:
- break;
+ /* We're done merging the files; destroy the progress bar if it was created. */
+ if (progbar != NULL)
+ destroy_progress_dlg(progbar);
- case MERGE_READ_ERROR:
+ merge_close_in_files(in_file_count, in_files);
+ if (!got_read_error && !got_write_error) {
+ if (!wtap_dump_close(pdh, &write_err))
+ got_write_error = TRUE;
+ } else
+ wtap_dump_close(pdh, &close_err);
+
+ if (got_read_error) {
/*
* Find the file on which we got the error, and report the error.
*/
for (i = 0; i < in_file_count; i++) {
- if (!in_files[i].ok) {
- /* Put up a message box noting that the read failed somewhere along
+ if (in_files[i].state == GOT_ERROR) {
+ /* Put up a message box noting that a read failed somewhere along
the line. */
- switch (err) {
+ switch (read_err) {
case WTAP_ERR_UNSUPPORTED_ENCAP:
snprintf(errmsg_errno, sizeof(errmsg_errno),
@@ -1050,7 +1126,7 @@ cf_merge_files(const char *out_filename, int out_fd, int in_file_count,
case WTAP_ERR_BAD_RECORD:
snprintf(errmsg_errno, sizeof(errmsg_errno),
- "The capture file %%sappears to be damaged or corrupt.\n(%s)",
+ "The capture file %%s appears to be damaged or corrupt.\n(%s)",
err_info);
g_free(err_info);
errmsg = errmsg_errno;
@@ -1059,7 +1135,7 @@ cf_merge_files(const char *out_filename, int out_fd, int in_file_count,
default:
snprintf(errmsg_errno, sizeof(errmsg_errno),
"An error occurred while reading the"
- " capture file %%s: %s.", wtap_strerror(err));
+ " capture file %%s: %s.", wtap_strerror(read_err));
errmsg = errmsg_errno;
break;
}
@@ -1067,13 +1143,14 @@ cf_merge_files(const char *out_filename, int out_fd, int in_file_count,
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, err_str);
}
}
- break;
+ }
- case MERGE_WRITE_ERROR:
- cf_write_failure_alert_box(out_filename, err);
- break;
+ if (got_write_error) {
+ /* Put up an alert box for the write error. */
+ cf_write_failure_alert_box(out_filename, write_err);
}
- return (status == MERGE_SUCCESS);
+
+ return (!got_read_error && !got_write_error);
}
gboolean