diff options
-rw-r--r-- | file.c | 5 | ||||
-rw-r--r-- | merge.c | 378 | ||||
-rw-r--r-- | merge.h | 25 | ||||
-rw-r--r-- | mergecap.c | 81 |
4 files changed, 224 insertions, 265 deletions
@@ -980,9 +980,8 @@ cf_merge_files(const char *out_filename, int out_fd, int in_file_count, gboolean ret; /* open the input files */ - 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_open_in_files(in_file_count, in_filenames, &in_files, + &err, &err_info, &err_fileno)) { free(in_files); cf_open_failure_alert_box(in_filenames[err_fileno], err, err_info, FALSE, 0); return FALSE; @@ -28,99 +28,152 @@ #include "merge.h" /* - * Global variables + * Scan through the arguments and open the input files */ -int merge_verbose = VERBOSE_NONE; +gboolean +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, j; + 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[i].filename = in_file_names[i]; + files[i].wth = wtap_open_offline(in_file_names[i], err, err_info, FALSE); + files[i].err = 0; + files[i].data_offset = 0; + files[i].ok = TRUE; + if (!files[i].wth) { + /* Close the files we've already opened. */ + for (j = 0; j < i; j++) + wtap_close(files[j].wth); + *err_fileno = i; + return FALSE; + } + } + return TRUE; +} /* - * Routine to write frame to output file + * Scan through and close each input file */ -static gboolean -write_frame(wtap *wth, merge_out_file_t *out_file, int *err) +void +merge_close_in_files(int count, merge_in_file_t in_files[]) { - const struct wtap_pkthdr *phdr = wtap_phdr(wth); - struct wtap_pkthdr snap_phdr; - - if (merge_verbose == VERBOSE_ALL) - fprintf(stderr, "Record: %u\n", out_file->count++); - - /* We simply write it, perhaps after truncating it; we could do other - * things, like modify it. */ - if (out_file->snaplen != 0 && phdr->caplen > out_file->snaplen) { - snap_phdr = *phdr; - snap_phdr.caplen = out_file->snaplen; - phdr = &snap_phdr; + int i; + for (i = 0; i < count; i++) { + wtap_close(in_files[i].wth); } +} - if (!wtap_dump(out_file->pdh, phdr, wtap_pseudoheader(wth), wtap_buf_ptr(wth), err)) { - if (merge_verbose == VERBOSE_ERRORS) - fprintf(stderr, "mergecap: Error writing to outfile: %s\n", - wtap_strerror(*err)); +/* + * Open the output file + * + * Return FALSE if file cannot be opened (so caller can report an error + * and clean up) + */ +gboolean +merge_open_outfile(merge_out_file_t *out_file, int fd, int file_type, + int frame_type, int snapshot_len, int *err) +{ + out_file->pdh = wtap_dump_fdopen(fd, file_type, frame_type, snapshot_len, + err); + if (!out_file->pdh) return FALSE; - } + out_file->snaplen = snapshot_len; + out_file->count = 1; return TRUE; } - -static gboolean -append_loop(wtap *wth, int count, merge_out_file_t *out_file, int *err, - gchar **err_info) +/* + * Close the output file + */ +gboolean +merge_close_outfile(merge_out_file_t *out_file, int *err) { - long data_offset; - int loop = 0; - - /* Start by clearing error flag */ - *err = 0; - - while ( (wtap_read(wth, err, err_info, &data_offset)) ) { - if(!write_frame(wth, out_file, err)) - return FALSE; /* failure */ - if (count > 0 && ++loop >= count) - break; - } - - if (*err == 0) { - return TRUE; /* success */ - } else { - return FALSE; /* failure */ - } + if (!wtap_dump_close(out_file->pdh, err)) + return FALSE; + return TRUE; } +/* + * Select an output frame type based on the input files + * From Guy: If all files have the same frame type, then use that. + * Otherwise select WTAP_ENCAP_PER_PACKET. If the selected + * output file type doesn't support per packet frame types, + * then the wtap_dump_open call will fail with a reasonable + * error condition. + */ +int +merge_select_frame_type(int count, merge_in_file_t files[]) +{ + int i; + int selected_frame_type; + selected_frame_type = wtap_file_encap(files[0].wth); + + for (i = 1; i < count; i++) { + int this_frame_type = wtap_file_encap(files[i].wth); + if (selected_frame_type != this_frame_type) { + selected_frame_type = WTAP_ENCAP_PER_PACKET; + break; + } + } + + return selected_frame_type; +} /* - * routine to concatenate files + * Scan through input files and find maximum snapshot length */ -gboolean -merge_append_files(int count, merge_in_file_t in_files[], merge_out_file_t *out_file, int *err) +int +merge_max_snapshot_length(int count, merge_in_file_t in_files[]) { int i; - gchar *err_info; + int max_snapshot = 0; + int snapshot_length; for (i = 0; i < count; i++) { - if (!append_loop(in_files[i].wth, 0, out_file, err, &err_info)) { - if (merge_verbose == VERBOSE_ERRORS) - fprintf(stderr, "mergecap: Error appending %s to outfile: %s\n", - in_files[i].filename, wtap_strerror(*err)); - switch (*err) { - - case WTAP_ERR_UNSUPPORTED: - case WTAP_ERR_UNSUPPORTED_ENCAP: - case WTAP_ERR_BAD_RECORD: - fprintf(stderr, "(%s)\n", err_info); - - break; - } - return FALSE; + snapshot_length = wtap_snapshot_length(in_files[i].wth); + if (snapshot_length == 0) { + /* Snapshot length of input file not known. */ + snapshot_length = WTAP_MAX_PACKET_SIZE; } + if (snapshot_length > max_snapshot) + max_snapshot = snapshot_length; } + return max_snapshot; +} + +/* + * Routine to write frame to output file + */ +static gboolean +write_frame(wtap *wth, merge_out_file_t *out_file, int *err) +{ + const struct wtap_pkthdr *phdr = wtap_phdr(wth); + struct wtap_pkthdr snap_phdr; + + /* We simply write it, perhaps after truncating it; we could do other + * things, like modify it. */ + if (out_file->snaplen != 0 && phdr->caplen > out_file->snaplen) { + snap_phdr = *phdr; + snap_phdr.caplen = out_file->snaplen; + phdr = &snap_phdr; + } + + if (!wtap_dump(out_file->pdh, phdr, wtap_pseudoheader(wth), wtap_buf_ptr(wth), err)) + return FALSE; return TRUE; } - /* * returns TRUE if first argument is earlier than second */ @@ -174,6 +227,10 @@ merge_files(int count, merge_in_file_t in_files[], merge_out_file_t *out_file, i in_files[i].ok = wtap_read(in_files[i].wth, &(in_files[i].err), &(in_files[i].err_info), &(in_files[i].data_offset)); + if (!in_files[i].ok) { + /* Read failure, not write failure. */ + return TRUE; + } } /* now keep writing the earliest frame until we're out of frames */ @@ -187,196 +244,55 @@ merge_files(int count, merge_in_file_t in_files[], merge_out_file_t *out_file, i in_files[i].ok = wtap_read(in_files[i].wth, &(in_files[i].err), &(in_files[i].err_info), &(in_files[i].data_offset)); + if (!in_files[i].ok) { + /* Read failure, not write failure. */ + return TRUE; + } } return TRUE; } - -/* - * Select an output frame type based on the input files - * From Guy: If all files have the same frame type, then use that. - * Otherwise select WTAP_ENCAP_PER_PACKET. If the selected - * output file type doesn't support per packet frame types, - * then the wtap_dump_open call will fail with a reasonable - * error condition. - */ -int -merge_select_frame_type(int count, merge_in_file_t files[]) +static gboolean +append_loop(merge_in_file_t in_files[], int i, int count, + merge_out_file_t *out_file, int *err) { - int i; - int selected_frame_type; + gchar *err_info; + long data_offset; + int loop = 0; - selected_frame_type = wtap_file_encap(files[0].wth); + /* Start by clearing error flag */ + *err = 0; - for (i = 1; i < count; i++) { - int this_frame_type = wtap_file_encap(files[i].wth); - if (selected_frame_type != this_frame_type) { - selected_frame_type = WTAP_ENCAP_PER_PACKET; - if (merge_verbose == VERBOSE_ALL) { - fprintf(stderr, "mergecap: multiple frame encapsulation types detected\n"); - fprintf(stderr, " defaulting to WTAP_ENCAP_PER_PACKET\n"); - fprintf(stderr, " %s had type %s (%s)\n", - files[0].filename, - wtap_encap_string(selected_frame_type), - wtap_encap_short_string(selected_frame_type)); - fprintf(stderr, " %s had type %s (%s)\n", - files[i].filename, - wtap_encap_string(this_frame_type), - wtap_encap_short_string(this_frame_type)); - } + while ( (wtap_read(in_files[i].wth, err, &err_info, &data_offset)) ) { + if(!write_frame(in_files[i].wth, out_file, err)) + return FALSE; /* failure */ + if (count > 0 && ++loop >= count) break; - } - } - - if (merge_verbose == VERBOSE_ALL) { - fprintf(stderr, "mergecap: selected frame_type %s (%s)\n", - wtap_encap_string(selected_frame_type), - wtap_encap_short_string(selected_frame_type)); } - return selected_frame_type; -} - - -/* - * Close the output file - */ -gboolean -merge_close_outfile(merge_out_file_t *out_file, int *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)); - return FALSE; + if (*err != 0) { + /* Read failure, not write failure. */ + in_files[i].ok = FALSE; + in_files[i].err = *err; + in_files[i].err_info = err_info; } return TRUE; } - /* - * Open the output file - * - * Return FALSE if file cannot be opened (so caller can clean up) + * routine to concatenate files */ gboolean -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) { - if (merge_verbose == VERBOSE_ERRORS) - fprintf(stderr, "mergecap: internal error (null out_file)\n"); - return FALSE; - } - - 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"); - fprintf(stderr, " %s\n", wtap_strerror(*err)); - } - return FALSE; - } - - out_file->snaplen = snapshot_len; - out_file->count = 1; - return TRUE; -} - - -/* - * Scan through input files and find maximum snapshot length - */ -int -merge_max_snapshot_length(int count, merge_in_file_t in_files[]) +merge_append_files(int count, merge_in_file_t in_files[], + merge_out_file_t *out_file, int *err) { int i; - int max_snapshot = 0; - int snapshot_length; for (i = 0; i < count; i++) { - snapshot_length = wtap_snapshot_length(in_files[i].wth); - if (snapshot_length == 0) { - /* Snapshot length of input file not known. */ - snapshot_length = WTAP_MAX_PACKET_SIZE; - } - if (snapshot_length > max_snapshot) - max_snapshot = snapshot_length; - } - return max_snapshot; -} - - -/* - * Scan through and close each input file - */ -void -merge_close_in_files(int count, merge_in_file_t in_files[]) -{ - int i; - for (i = 0; i < count; i++) { - wtap_close(in_files[i].wth); - } -} - - -/* - * Scan through the arguments and open the input files - */ -int -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; - 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].err = 0; - files[count].data_offset = 0; - files[count].ok = TRUE; - if (!files[count].wth) { - if (merge_verbose >= VERBOSE_ERRORS) { - fprintf(stderr, "mergecap: skipping %s: %s\n", in_file_names[i], - wtap_strerror(*err)); - switch (*err) { - - case WTAP_ERR_UNSUPPORTED: - case WTAP_ERR_UNSUPPORTED_ENCAP: - case WTAP_ERR_BAD_RECORD: - 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) { - fprintf(stderr, "mergecap: %s is type %s.\n", in_file_names[i], - wtap_file_type_string(wtap_file_type(files[count].wth))); - } - count++; - } + if (!append_loop(in_files, i, 0, out_file, err)) + return FALSE; } - if (merge_verbose == VERBOSE_ALL) - fprintf(stderr, "mergecap: opened %d of %d input files\n", count, - in_file_count); - return count; + return TRUE; } @@ -50,27 +50,17 @@ typedef struct merge_out_file_s { int count; } merge_out_file_t; -/** Verbosity levels. */ -typedef enum { - VERBOSE_NONE, - VERBOSE_ERRORS, - VERBOSE_ALL -} verbose_e; - -/** Current verbosity level, default is VERBOSE_NONE. */ -extern int merge_verbose; - /** Open a number of input files to merge. * * @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 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 + * @param err wiretap error, if failed + * @param err_info wiretap error string, if failed + * @param err_fileno file on which open failed, if failed + * @return TRUE if all files could be opened, FALSE otherwise */ -extern int +extern gboolean 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); @@ -91,7 +81,7 @@ merge_close_in_files(int in_file_count, merge_in_file_t in_files[]); * @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 + * @return TRUE, if the output file could be opened, and FALSE otherwise */ extern gboolean merge_open_outfile(merge_out_file_t *out_file, int fd, int file_type, @@ -144,7 +134,8 @@ merge_files(int in_file_count, merge_in_file_t in_files[], merge_out_file_t *out * @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); +merge_append_files(int in_file_count, merge_in_file_t in_files[], + merge_out_file_t *out_file, int *err); #ifdef __cplusplus } diff --git a/mergecap.c b/mergecap.c index 05a3a159e2..74c41a7918 100644 --- a/mergecap.c +++ b/mergecap.c @@ -122,8 +122,6 @@ usage(void) printf(" \t default is libpcap\n"); } - - int main(int argc, char *argv[]) { @@ -131,19 +129,20 @@ main(int argc, char *argv[]) extern int optind; int opt; gboolean do_append = FALSE; + gboolean verbose = 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; + int i; merge_out_file_t out_file; - int err; + int err, close_err; gchar *err_info; int err_fileno; char *out_filename = NULL; - - merge_verbose = VERBOSE_ERRORS; + gboolean ret; /* Process the options first */ while ((opt = getopt(argc, argv, "hvas:T:F:w:")) != -1) { @@ -176,7 +175,7 @@ main(int argc, char *argv[]) break; case 'v': - merge_verbose = VERBOSE_ALL; + verbose = TRUE; break; case 's': @@ -217,13 +216,28 @@ main(int argc, char *argv[]) } /* open the input files */ - 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"); + if (!merge_open_in_files(in_file_count, &argv[optind], &in_files, + &err, &err_info, &err_fileno)) { + fprintf(stderr, "mergecap: Can't open %s: %s\n", argv[optind + err_fileno], + wtap_strerror(err)); + switch (err) { + + case WTAP_ERR_UNSUPPORTED: + case WTAP_ERR_UNSUPPORTED_ENCAP: + case WTAP_ERR_BAD_RECORD: + fprintf(stderr, "(%s)\n", err_info); + g_free(err_info); + break; + } exit(1); } + if (verbose) { + for (i = 0; i < in_file_count; i++) + fprintf(stderr, "mergecap: %s is type %s.\n", argv[optind + i], + wtap_file_type_string(wtap_file_type(in_files[i].wth))); + } + if (snaplen == 0) { /* * Snapshot length not specified - default to the maximum of the @@ -238,6 +252,35 @@ main(int argc, char *argv[]) * Default to the appropriate frame type for the input files. */ frame_type = merge_select_frame_type(in_file_count, in_files); + if (verbose) { + if (frame_type == WTAP_ENCAP_PER_PACKET) { + /* + * Find out why we had to choose WTAP_ENCAP_PER_PACKET. + */ + int first_frame_type, this_frame_type; + + first_frame_type = wtap_file_encap(in_files[0].wth); + for (i = 1; i < in_file_count; i++) { + this_frame_type = wtap_file_encap(in_files[i].wth); + if (first_frame_type != this_frame_type) { + fprintf(stderr, "mergecap: multiple frame encapsulation types detected\n"); + fprintf(stderr, " defaulting to WTAP_ENCAP_PER_PACKET\n"); + fprintf(stderr, " %s had type %s (%s)\n", + in_files[0].filename, + wtap_encap_string(first_frame_type), + wtap_encap_short_string(first_frame_type)); + fprintf(stderr, " %s had type %s (%s)\n", + in_files[i].filename, + wtap_encap_string(this_frame_type), + wtap_encap_short_string(this_frame_type)); + break; + } + } + } + fprintf(stderr, "mergecap: selected frame_type %s (%s)\n", + wtap_encap_string(frame_type), + wtap_encap_short_string(frame_type)); + } } /* open the outfile */ @@ -258,19 +301,29 @@ main(int argc, char *argv[]) if (!merge_open_outfile(&out_file, out_fd, file_type, frame_type, snaplen, &err)) { merge_close_in_files(in_file_count, in_files); + free(in_files); + fprintf(stderr, "mergecap: Can't open or create %s: %s\n", out_filename, + wtap_strerror(err)); exit(1); } /* do the merge (or append) */ if (do_append) - merge_append_files(in_file_count, in_files, &out_file, &err); + ret = merge_append_files(in_file_count, in_files, &out_file, &err); else - merge_files(in_file_count, in_files, &out_file, &err); + 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, &err); + if (ret) + ret = merge_close_outfile(&out_file, &err); + else + merge_close_outfile(&out_file, &close_err); + if (!ret) { + fprintf(stderr, "mergecap: Error writing to outfile: %s\n", + wtap_strerror(err)); + } free(in_files); - return 0; + return ret ? 0 : 2; } |