diff options
author | guy <guy@f5534014-38df-0310-8fa8-9805f1628bb7> | 2004-10-27 23:28:37 +0000 |
---|---|---|
committer | guy <guy@f5534014-38df-0310-8fa8-9805f1628bb7> | 2004-10-27 23:28:37 +0000 |
commit | 95062e56acfc985ffae5d1dd37a656a602fb0fca (patch) | |
tree | 710dc8246082edefe1ea5a819d05276fdfb80d8e | |
parent | 615a5531224ea76a1d0763201de08edef9dcb12d (diff) |
Change some of the merge.c APIs to return more information on failure,
and use that information to provide better error messages.
Have "merge_open_outfile()" do all the work of filling in the
merge_out_file_t structure, with the values to use passed as arguments.
Get rid of some structure members that used to be used solely to pass
information to "merge_open_outfile()".
Add a "cf_merge_files()" routine to do the merging and reporting of errors.
git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@12420 f5534014-38df-0310-8fa8-9805f1628bb7
-rw-r--r-- | file.c | 35 | ||||
-rw-r--r-- | file.h | 4 | ||||
-rw-r--r-- | gtk/file_dlg.c | 23 | ||||
-rw-r--r-- | gtk/main.c | 68 | ||||
-rw-r--r-- | merge.c | 95 | ||||
-rw-r--r-- | merge.h | 51 | ||||
-rw-r--r-- | mergecap.c | 109 |
7 files changed, 246 insertions, 139 deletions
@@ -75,6 +75,7 @@ #include "file.h" #include "menu.h" #include "util.h" +#include "merge.h" #include "alert_box.h" #include "simple_dialog.h" #include "progress_dlg.h" @@ -968,6 +969,40 @@ read_packet(capture_file *cf, long offset) } gboolean +cf_merge_files(const char *out_file, int out_fd, int in_file_count, + char *const *in_filenames, int filetype, gboolean do_append) +{ + merge_status_e merge_status; + int err; + gchar *err_info; + int err_fileno; + + merge_status = merge_n_files(out_fd, in_file_count, in_filenames, filetype, + do_append, &err, &err_info, &err_fileno); + + switch (merge_status) { + + case MERGE_SUCCESS: + return TRUE; + + case MERGE_OPEN_INPUT_FAILED: + cf_open_failure_alert_box(in_filenames[err_fileno], err, err_info, FALSE, 0); + return FALSE; + + case MERGE_OPEN_OUTPUT_FAILED: + cf_open_failure_alert_box(out_file, err, err_info, TRUE, filetype); + return FALSE; + + /* XXX - what about read failures? */ + + case MERGE_WRITE_FAILED: + cf_write_failure_alert_box(out_file, err); + return FALSE; + } + return TRUE; +} + +gboolean filter_packets(capture_file *cf, gchar *dftext, gboolean force) { dfilter_t *dfcode; @@ -53,6 +53,10 @@ read_status_t cf_finish_tail(capture_file *, int *); gboolean cf_save(char *fname, capture_file * cf, packet_range_t *range, guint save_format); gchar *cf_get_display_name(capture_file *); +gboolean +cf_merge_files(const char *out_file, int out_fd, int in_file_count, + char *const *in_filenames, int filetype, gboolean do_append); + gboolean filter_packets(capture_file *cf, gchar *dfilter, gboolean force); void reftime_packets(capture_file *); void colorize_packets(capture_file *); diff --git a/gtk/file_dlg.c b/gtk/file_dlg.c index 131ade221b..2d2fe30816 100644 --- a/gtk/file_dlg.c +++ b/gtk/file_dlg.c @@ -998,8 +998,8 @@ file_merge_ok_cb(GtkWidget *w, gpointer fs) { int err; gboolean merge_ok; char *in_filenames[2]; - int out_fd; - char tmpname[128+1]; + int out_fd; + char tmpname[128+1]; #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2 cf_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs))); @@ -1030,33 +1030,32 @@ file_merge_ok_cb(GtkWidget *w, gpointer fs) { /* merge or append the two files */ rb = OBJECT_GET_DATA(w, E_MERGE_CHRONO_KEY); if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (rb))) { - /* chonological order */ + /* chronological order */ in_filenames[0] = cfile.filename; in_filenames[1] = cf_name; - merge_ok = merge_n_files(out_fd, 2, in_filenames, filetype, FALSE, &err); + merge_ok = cf_merge_files(tmpname, out_fd, 2, in_filenames, + filetype, FALSE); } else { rb = OBJECT_GET_DATA(w, E_MERGE_PREPEND_KEY); if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (rb))) { /* prepend file */ in_filenames[0] = cfile.filename; in_filenames[1] = cf_name; - merge_ok = merge_n_files(out_fd, 2, in_filenames, filetype, TRUE, &err); + merge_ok = cf_merge_files(tmpname, out_fd, 2, in_filenames, + filetype, TRUE); } else { /* append file */ in_filenames[0] = cf_name; in_filenames[1] = cfile.filename; - merge_ok = merge_n_files(out_fd, 2, in_filenames, filetype, TRUE, &err); + merge_ok = cf_merge_files(tmpname, out_fd, 2, in_filenames, + filetype, TRUE); } } g_free(cf_name); - if(!merge_ok) { - /* merge failed */ - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, - "An error occurred while merging the files: %s.", - wtap_strerror(err)); - close(out_fd); + if (!merge_ok) { + close(out_fd); /* XXX - it's already closed, right? */ if (rfcode != NULL) dfilter_free(rfcode); return; diff --git a/gtk/main.c b/gtk/main.c index 25e5dc30ab..259e1c2cd4 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -1319,53 +1319,51 @@ dnd_merge_files(int in_file_count, char **in_filenames) out_fd = create_tempfile(tmpname, sizeof tmpname, "ether"); /* merge the files in chonological order */ - merge_ok = merge_n_files(out_fd, in_file_count, in_filenames, WTAP_FILE_PCAP, FALSE, &err); - - if(!merge_ok) { - /* merge failed */ - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, - "An error occurred while merging the files: \"%s\".", - wtap_strerror(err)); - close(out_fd); - return; - } + merge_ok = cf_merge_files(tmpname, out_fd, in_file_count, in_filenames, + WTAP_FILE_PCAP, FALSE); - cf_close(&cfile); + if (!merge_ok) { + /* merge failed */ + close(out_fd); /* XXX - isn't it already closed? */ + return; + } - /* Try to open the merged capture file. */ - if ((err = cf_open(tmpname, TRUE /* temporary file */, &cfile)) != 0) { - /* We couldn't open it; don't dismiss the open dialog box, - just leave it around so that the user can, after they - dismiss the alert box popped up for the open error, - try again. */ - return; - } + cf_close(&cfile); - switch (cf_read(&cfile)) { + /* Try to open the merged capture file. */ + if ((err = cf_open(tmpname, TRUE /* temporary file */, &cfile)) != 0) { + /* We couldn't open it; don't dismiss the open dialog box, + just leave it around so that the user can, after they + dismiss the alert box popped up for the open error, + try again. */ + return; + } - case READ_SUCCESS: - case READ_ERROR: - /* Just because we got an error, that doesn't mean we were unable - to read any of the file; we handle what we could get from the - file. */ - break; + switch (cf_read(&cfile)) { - case READ_ABORTED: - /* The user bailed out of re-reading the capture file; the - capture file has been closed - just free the capture file name - string and return (without changing the last containing - directory). */ - return; - } + case READ_SUCCESS: + case READ_ERROR: + /* Just because we got an error, that doesn't mean we were unable + to read any of the file; we handle what we could get from the + file. */ + break; + + case READ_ABORTED: + /* The user bailed out of re-reading the capture file; the + capture file has been closed - just free the capture file name + string and return (without changing the last containing + directory). */ + return; + } - gtk_widget_grab_focus(packet_list); + gtk_widget_grab_focus(packet_list); } /* open/merge the dnd file */ void dnd_open_file_cmd(GtkSelectionData *selection_data) { - int err; + int err; gchar *cf_name, *cf_name_freeme; int in_files; gpointer dialog; @@ -183,7 +183,7 @@ merge_files(int count, merge_in_file_t in_files[], merge_out_file_t *out_file, i * input file */ if(!write_frame(in_files[i].wth, out_file, err)) - return FALSE; + return FALSE; in_files[i].ok = wtap_read(in_files[i].wth, &(in_files[i].err), &(in_files[i].err_info), &(in_files[i].data_offset)); @@ -242,15 +242,16 @@ merge_select_frame_type(int count, merge_in_file_t files[]) /* * Close the output file */ -void -merge_close_outfile(merge_out_file_t *out_file) +gboolean +merge_close_outfile(merge_out_file_t *out_file, int *err) { - int err; - if (!wtap_dump_close(out_file->pdh, &err)) { + if (!wtap_dump_close(out_file->pdh, err)) { if (merge_verbose == VERBOSE_ERRORS) fprintf(stderr, "mergecap: Error closing output file: %s\n", - wtap_strerror(err)); + wtap_strerror(*err)); + return FALSE; } + return TRUE; } @@ -260,7 +261,8 @@ merge_close_outfile(merge_out_file_t *out_file) * Return FALSE if file cannot be opened (so caller can clean up) */ gboolean -merge_open_outfile(merge_out_file_t *out_file, int snapshot_len, int *err) +merge_open_outfile(merge_out_file_t *out_file, int fd, int file_type, + int frame_type, int snapshot_len, int *err) { if (!out_file) { @@ -269,9 +271,8 @@ merge_open_outfile(merge_out_file_t *out_file, int snapshot_len, int *err) return FALSE; } - - out_file->pdh = wtap_dump_fdopen(out_file->fd, out_file->file_type, - out_file->frame_type, snapshot_len, err); + out_file->pdh = wtap_dump_fdopen(fd, file_type, frame_type, snapshot_len, + err); if (!out_file->pdh) { if (merge_verbose == VERBOSE_ERRORS) { fprintf(stderr, "mergecap: Can't open/create output file:\n"); @@ -279,6 +280,9 @@ merge_open_outfile(merge_out_file_t *out_file, int snapshot_len, int *err) } return FALSE; } + + out_file->snaplen = snapshot_len; + out_file->count = 1; return TRUE; } @@ -323,26 +327,26 @@ merge_close_in_files(int count, merge_in_file_t in_files[]) * Scan through the arguments and open the input files */ int -merge_open_in_files(int in_file_count, char *in_file_names[], merge_in_file_t *in_files[], int *err) +merge_open_in_files(int in_file_count, char *const *in_file_names, + merge_in_file_t **in_files, int *err, gchar **err_info, + int *err_fileno) { int i; int count = 0; - gchar *err_info; int files_size = in_file_count * sizeof(merge_in_file_t); merge_in_file_t *files; - files = g_malloc(files_size); *in_files = files; for (i = 0; i < in_file_count; i++) { files[count].filename = in_file_names[i]; - files[count].wth = wtap_open_offline(in_file_names[i], err, &err_info, FALSE); + files[count].wth = wtap_open_offline(in_file_names[i], err, err_info, FALSE); files[count].err = 0; files[count].data_offset = 0; files[count].ok = TRUE; if (!files[count].wth) { - if (merge_verbose == VERBOSE_ERRORS) { + if (merge_verbose >= VERBOSE_ERRORS) { fprintf(stderr, "mergecap: skipping %s: %s\n", in_file_names[i], wtap_strerror(*err)); switch (*err) { @@ -350,10 +354,17 @@ merge_open_in_files(int in_file_count, char *in_file_names[], merge_in_file_t *i case WTAP_ERR_UNSUPPORTED: case WTAP_ERR_UNSUPPORTED_ENCAP: case WTAP_ERR_BAD_RECORD: - fprintf(stderr, "(%s)\n", err_info); - g_free(err_info); + fprintf(stderr, "(%s)\n", *err_info); + g_free(*err_info); break; } + } else { + /* + * We aren't reporting the errors, so return immediately so our + * caller can report the error. + */ + *err_fileno = count; + return 0; } } else { if (merge_verbose == VERBOSE_ALL) { @@ -372,41 +383,34 @@ merge_open_in_files(int in_file_count, char *in_file_names[], merge_in_file_t *i /* - * Convenience function: merge two files into one. + * Convenience function: merge two or more files into one. */ -gboolean -merge_n_files(int out_fd, int in_file_count, char **in_filenames, int filetype, gboolean do_append, int *err) +merge_status_e +merge_n_files(int out_fd, int in_file_count, char *const *in_filenames, + int file_type, gboolean do_append, int *err, gchar **err_info, + int *err_fileno) { - extern char *optarg; - extern int optind; - merge_in_file_t *in_files = NULL; - merge_out_file_t out_file; - gboolean ret; - - /* initialize out_file */ - out_file.fd = out_fd; - out_file.pdh = NULL; /* wiretap dumpfile */ - out_file.file_type = filetype; - out_file.frame_type = -2; /* leave type alone */ - out_file.snaplen = 0; /* no limit */ - out_file.count = 1; /* frames output */ + merge_in_file_t *in_files = NULL; + merge_out_file_t out_file; + gboolean ret; + int close_err; /* open the input files */ - in_file_count = merge_open_in_files(in_file_count, in_filenames, &in_files, err); + in_file_count = merge_open_in_files(in_file_count, in_filenames, &in_files, + err, err_info, err_fileno); if (in_file_count < 2) { if (merge_verbose == VERBOSE_ALL) fprintf(stderr, "mergecap: Not all input files valid\n"); - return FALSE; + free(in_files); + return MERGE_OPEN_INPUT_FAILED; } - /* set the outfile frame type */ - if (out_file.frame_type == -2) - out_file.frame_type = merge_select_frame_type(in_file_count, in_files); - - /* open the outfile */ - if (!merge_open_outfile(&out_file, merge_max_snapshot_length(in_file_count, in_files), err)) { + if (!merge_open_outfile(&out_file, out_fd, file_type, + merge_select_frame_type(in_file_count, in_files), + merge_max_snapshot_length(in_file_count, in_files), err)) { merge_close_in_files(in_file_count, in_files); - return FALSE; + free(in_files); + return MERGE_OPEN_OUTPUT_FAILED; } /* do the merge (or append) */ @@ -416,9 +420,12 @@ merge_n_files(int out_fd, int in_file_count, char **in_filenames, int filetype, ret = merge_files(in_file_count, in_files, &out_file, err); merge_close_in_files(in_file_count, in_files); - merge_close_outfile(&out_file); + if (ret) + ret = merge_close_outfile(&out_file, err); + else + merge_close_outfile(&out_file, &close_err); free(in_files); - return ret; + return ret ? MERGE_SUCCESS : MERGE_WRITE_FAILED; } @@ -1,6 +1,5 @@ /* merge.h - * Definitions for menu routines with toolkit-independent APIs but - * toolkit-dependent implementations. + * Definitions for routines for merging files. * * $Id$ * @@ -46,10 +45,7 @@ typedef struct merge_in_file_s { * Structures to manage our output file. */ typedef struct merge_out_file_s { - int fd; wtap_dumper *pdh; - int file_type; - int frame_type; unsigned int snaplen; int count; } merge_out_file_t; @@ -69,11 +65,15 @@ extern int merge_verbose; * @param in_file_count number of entries in in_file_names and in_files * @param in_file_names filenames of the input files * @param in_files input file array to be filled (>= sizeof(merge_in_file_t) * in_file_count) - * @param err wiretap error, if failed + * @param err wiretap error, if failed and VERBOSE_NONE + * @param err_info wiretap error string, if failed and VERBOSE_NONE + * @param err_fileno file on which open failed, if VERBOSE_NONE * @return number of opened input files */ extern int -merge_open_in_files(int in_file_count, char *in_file_names[], merge_in_file_t *in_files[], int *err); +merge_open_in_files(int in_file_count, char *const *in_file_names, + merge_in_file_t **in_files, int *err, gchar **err_info, + int *err_fileno); /** Close the input files again. * @@ -85,20 +85,26 @@ merge_close_in_files(int in_file_count, merge_in_file_t in_files[]); /** Open the output file. * - * @param out_file the prefilled output file array + * @param out_file the output file array, which we fill in + * @param fd the file descriptor to use for the output file + * @param file_type the file type to write + * @param frame_type the frame type to write * @param snapshot_len the snapshot length of the output file * @param err wiretap error, if failed * @return TRUE, if the output file could be opened */ extern gboolean -merge_open_outfile(merge_out_file_t *out_file, int snapshot_len, int *err); +merge_open_outfile(merge_out_file_t *out_file, int fd, int file_type, + int frame_type, int snapshot_len, int *err); /** Close the output file again. * * @param out_file the output file array + * @param err wiretap error, if failed + * @return TRUE if the close succeeded, FALSE otherwise */ -extern void -merge_close_outfile(merge_out_file_t *out_file); +extern gboolean +merge_close_outfile(merge_out_file_t *out_file, int *err); /** Try to get the frame type from the input files. * @@ -124,7 +130,7 @@ merge_max_snapshot_length(int in_file_count, merge_in_file_t in_files[]); * @param in_files input file array * @param out_file the output file array * @param err wiretap error, if failed - * @return TRUE if function succeeded + * @return TRUE on success or read failure, FALSE on write failure */ extern gboolean merge_files(int in_file_count, merge_in_file_t in_files[], merge_out_file_t *out_file, int *err); @@ -135,11 +141,18 @@ merge_files(int in_file_count, merge_in_file_t in_files[], merge_out_file_t *out * @param in_files input file array * @param out_file the output file array * @param err wiretap error, if failed - * @return TRUE if function succeeded + * @return TRUE on success or read failure, FALSE on write failure */ extern gboolean merge_append_files(int in_file_count, merge_in_file_t in_files[], merge_out_file_t *out_file, int *err); +/** Return status from merge_n_files */ +typedef enum { + MERGE_SUCCESS, + MERGE_OPEN_INPUT_FAILED, + MERGE_OPEN_OUTPUT_FAILED, + MERGE_WRITE_FAILED +} merge_status_e; /* * Convenience function: merge any number of input files into one. @@ -148,11 +161,15 @@ merge_append_files(int in_file_count, merge_in_file_t in_files[], merge_out_file * @param in_file_count number of input files * @param in_filenames array of input filenames * @param do_append TRUE to append, FALSE to merge chronologically - * @param err wiretap error, if failed - * @return TRUE if function succeeded + * @param err wiretap error, if failed and VERBOSE_NONE + * @param err_info wiretap error string, if failed and VERBOSE_NONE + * @param err_fileno file on which open failed, if VERBOSE_NONE + * @return merge_status_e */ -extern gboolean -merge_n_files(int out_fd, int in_file_count, char **in_filenames, int filetype, gboolean do_append, int *err); +extern merge_status_e +merge_n_files(int out_fd, int in_file_count, char *const *in_filenames, + int filetype, gboolean do_append, int *err, gchar **err_info, + int *err_fileno); #ifdef __cplusplus diff --git a/mergecap.c b/mergecap.c index 047979b46b..05a3a159e2 100644 --- a/mergecap.c +++ b/mergecap.c @@ -47,6 +47,47 @@ #define O_BINARY 0 #endif +static int +get_natural_int(const char *string, const char *name) +{ + long number; + char *p; + + number = strtol(string, &p, 10); + if (p == string || *p != '\0') { + fprintf(stderr, "mergecap: The specified %s \"%s\" is not a decimal number\n", + name, string); + exit(1); + } + if (number < 0) { + fprintf(stderr, "mergecap: The specified %s is a negative number\n", + name); + exit(1); + } + if (number > INT_MAX) { + fprintf(stderr, "mergecap: The specified %s is too large (greater than %d)\n", + name, INT_MAX); + exit(1); + } + return number; +} + +static int +get_positive_int(const char *string, const char *name) +{ + long number; + + number = get_natural_int(string, name); + + if (number == 0) { + fprintf(stderr, "mergecap: The specified %s is zero\n", + name); + exit(1); + } + + return number; +} + /* * Show the usage */ @@ -89,22 +130,19 @@ main(int argc, char *argv[]) extern char *optarg; extern int optind; int opt; - char *p; gboolean do_append = FALSE; int in_file_count = 0; + int snaplen = 0; + int file_type = WTAP_FILE_PCAP; /* default to libpcap format */ + int frame_type = -2; + int out_fd; merge_in_file_t *in_files = NULL; merge_out_file_t out_file; int err; + gchar *err_info; + int err_fileno; char *out_filename = NULL; - /* initialize out_file */ - out_file.fd = 0; - out_file.pdh = NULL; /* wiretap dumpfile */ - out_file.file_type = WTAP_FILE_PCAP; /* default to "libpcap" */ - out_file.frame_type = -2; /* leave type alone */ - out_file.snaplen = 0; /* no limit */ - out_file.count = 1; /* frames output */ - merge_verbose = VERBOSE_ERRORS; /* Process the options first */ @@ -120,8 +158,8 @@ main(int argc, char *argv[]) break; case 'T': - out_file.frame_type = wtap_short_string_to_encap(optarg); - if (out_file.frame_type < 0) { + frame_type = wtap_short_string_to_encap(optarg); + if (frame_type < 0) { fprintf(stderr, "mergecap: \"%s\" is not a valid encapsulation type\n", optarg); exit(1); @@ -129,8 +167,8 @@ main(int argc, char *argv[]) break; case 'F': - out_file.file_type = wtap_short_string_to_file_type(optarg); - if (out_file.file_type < 0) { + file_type = wtap_short_string_to_file_type(optarg); + if (file_type < 0) { fprintf(stderr, "mergecap: \"%s\" is not a valid capture file type\n", optarg); exit(1); @@ -142,12 +180,7 @@ main(int argc, char *argv[]) break; case 's': - out_file.snaplen = strtol(optarg, &p, 10); - if (p == optarg || *p != '\0') { - fprintf(stderr, "mergecap: \"%s\" is not a valid snapshot length\n", - optarg); - exit(1); - } + snaplen = get_positive_int(optarg, "snapshot length"); break; case 'h': @@ -184,32 +217,46 @@ main(int argc, char *argv[]) } /* open the input files */ - in_file_count = merge_open_in_files(in_file_count, &argv[optind], &in_files, &err); + in_file_count = merge_open_in_files(in_file_count, &argv[optind], &in_files, + &err, &err_info, &err_fileno); if (in_file_count < 1) { fprintf(stderr, "mergecap: No valid input files\n"); exit(1); } + if (snaplen == 0) { + /* + * Snapshot length not specified - default to the maximum of the + * snapshot lengths of the input files. + */ + snaplen = merge_max_snapshot_length(in_file_count, in_files); + } + /* set the outfile frame type */ - if (out_file.frame_type == -2) - out_file.frame_type = merge_select_frame_type(in_file_count, in_files); + if (frame_type == -2) { + /* + * Default to the appropriate frame type for the input files. + */ + frame_type = merge_select_frame_type(in_file_count, in_files); + } /* open the outfile */ if (strncmp(out_filename, "-", 2) == 0) { /* use stdout as the outfile */ - out_file.fd = 1 /*stdout*/; + out_fd = 1 /*stdout*/; } else { /* open the outfile */ - out_file.fd = open(out_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); - } - if (out_file.fd == -1) { - fprintf(stderr, "mergecap: Couldn't open output file %s: %s\n", - out_filename, strerror(errno)); - exit(1); + out_fd = open(out_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); + if (out_fd == -1) { + fprintf(stderr, "mergecap: Couldn't open output file %s: %s\n", + out_filename, strerror(errno)); + exit(1); + } } /* prepare the outfile */ - if (!merge_open_outfile(&out_file, merge_max_snapshot_length(in_file_count, in_files), &err)) { + if (!merge_open_outfile(&out_file, out_fd, file_type, frame_type, snaplen, + &err)) { merge_close_in_files(in_file_count, in_files); exit(1); } @@ -221,7 +268,7 @@ main(int argc, char *argv[]) merge_files(in_file_count, in_files, &out_file, &err); merge_close_in_files(in_file_count, in_files); - merge_close_outfile(&out_file); + merge_close_outfile(&out_file, &err); free(in_files); |