X-Git-Url: http://git.samba.org/?p=metze%2Fwireshark%2Fwip.git;a=blobdiff_plain;f=mergecap.c;h=3a2f39a02fadfb3c5128e6a18096b7572398aa11;hp=8ebed8789e82048e368f948e8d57cb4486594fc4;hb=913a02854483b005505651287da569800e4391f8;hpb=3551a86c36fa9f27dede601320a812d2ce0ae941 diff --git a/mergecap.c b/mergecap.c index 8ebed8789e..3a2f39a02f 100644 --- a/mergecap.c +++ b/mergecap.c @@ -1,156 +1,133 @@ -/* Combine two dump files, either by appending or by merging by timestamp - * - * $Id$ +/* Combine dump files, either by appending or by merging by timestamp * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * SPDX-License-Identifier: GPL-2.0-or-later * * Mergecap written by Scott Renfro based on * editcap by Richard Sharpe and Guy Harris * */ -#include "config.h" +#include #include #include #include #include -#ifdef HAVE_UNISTD_H -#include -#endif - -#ifdef HAVE_SYS_TIME_H -#include +#ifdef HAVE_GETOPT_H +#include #endif #include -#include "wtap.h" -#ifndef HAVE_GETOPT -#include "wsutil/wsgetopt.h" -#endif +#include -#include "svnversion.h" -#include "merge.h" -#include "wsutil/file_util.h" - -#ifdef HAVE_FCNTL_H -#include +#ifndef HAVE_GETOPT_LONG +#include #endif -#ifdef _WIN32 -#include -#endif /* _WIN32 */ +#include +#include +#include +#include +#include +#include -static int -get_natural_int(const char *string, const char *name) -{ - int number; - char *p; - - number = (int) strtol(string, &p, 10); - if (p == string || *p != '\0') { - fprintf(stderr, "mergecap: The specified %s \"%s\" isn't 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; -} +#include +#include -static int -get_positive_int(const char *string, const char *name) -{ - int number; +#ifdef HAVE_PLUGINS +#include +#endif - number = get_natural_int(string, name); +#include - if (number == 0) { - fprintf(stderr, "mergecap: The specified %s is zero\n", - name); - exit(1); - } +#include - return number; -} +#include "ui/failure_message.h" /* * Show the usage */ static void -usage(void) +print_usage(FILE *output) { - - fprintf(stderr, "Mergecap %s" -#ifdef SVNVERSION - " (" SVNVERSION " from " SVNPATH ")" + fprintf(output, "\n"); + fprintf(output, "Usage: mergecap [options] -w |- [ ...]\n"); + fprintf(output, "\n"); + fprintf(output, "Output:\n"); + fprintf(output, " -a concatenate rather than merge files.\n"); + fprintf(output, " default is to merge based on frame timestamps.\n"); + fprintf(output, " -s truncate packets to bytes of data.\n"); + fprintf(output, " -w |- set the output filename to or '-' for stdout.\n"); +#ifdef PCAP_NG_DEFAULT + fprintf(output, " -F set the output file type; default is pcapng.\n"); +#else + fprintf(output, " -F set the output file type; default is pcap.\n"); #endif - "\n", VERSION); - fprintf(stderr, "Merge two or more capture files into one.\n"); - fprintf(stderr, "See http://www.wireshark.org for more information.\n"); - fprintf(stderr, "\n"); - fprintf(stderr, "Usage: mergecap [options] -w |- [ ...]\n"); + fprintf(output, " an empty \"-F\" option will list the file types.\n"); + fprintf(output, " -I set the merge mode for Interface Description Blocks; default is 'all'.\n"); + fprintf(output, " an empty \"-I\" option will list the merge modes.\n"); + fprintf(output, "\n"); + fprintf(output, "Miscellaneous:\n"); + fprintf(output, " -h display this help and exit.\n"); + fprintf(output, " -v verbose output.\n"); +} + +/* + * Report an error in command-line arguments. + */ +static void +mergecap_cmdarg_err(const char *fmt, va_list ap) +{ + fprintf(stderr, "mergecap: "); + vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); - fprintf(stderr, "Output:\n"); - fprintf(stderr, " -a concatenate rather than merge files.\n"); - fprintf(stderr, " default is to merge based on frame timestamps.\n"); - fprintf(stderr, " -s truncate packets to bytes of data.\n"); - fprintf(stderr, " -w |- set the output filename to or '-' for stdout.\n"); - fprintf(stderr, " -F set the output file type; default is pcapng.\n"); - fprintf(stderr, " an empty \"-F\" option will list the file types.\n"); - fprintf(stderr, " -T set the output file encapsulation type;\n"); - fprintf(stderr, " default is the same as the first input file.\n"); - fprintf(stderr, " an empty \"-T\" option will list the encapsulation types.\n"); +} + +/* + * Report additional information for an error in command-line arguments. + */ +static void +mergecap_cmdarg_err_cont(const char *fmt, va_list ap) +{ + vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); - fprintf(stderr, "Miscellaneous:\n"); - fprintf(stderr, " -h display this help and exit.\n"); - fprintf(stderr, " -v verbose output.\n"); } struct string_elem { - const char *sstr; /* The short string */ - const char *lstr; /* The long string */ + const char *sstr; /* The short string */ + const char *lstr; /* The long string */ }; static gint string_compare(gconstpointer a, gconstpointer b) { - return strcmp(((const struct string_elem *)a)->sstr, - ((const struct string_elem *)b)->sstr); + return strcmp(((const struct string_elem *)a)->sstr, + ((const struct string_elem *)b)->sstr); } static void string_elem_print(gpointer data, gpointer not_used _U_) { - fprintf(stderr, " %s - %s\n", - ((struct string_elem *)data)->sstr, - ((struct string_elem *)data)->lstr); + fprintf(stderr, " %s - %s\n", ((struct string_elem *)data)->sstr, + ((struct string_elem *)data)->lstr); +} + +/* + * General errors and warnings are reported with an console message + * in mergecap. + */ +static void +failure_warning_message(const char *msg_format, va_list ap) +{ + fprintf(stderr, "mergecap: "); + vfprintf(stderr, msg_format, ap); + fprintf(stderr, "\n"); } static void @@ -159,13 +136,13 @@ list_capture_types(void) { struct string_elem *captypes; GSList *list = NULL; - captypes = g_malloc(sizeof(struct string_elem) * WTAP_NUM_FILE_TYPES); + captypes = g_new(struct string_elem,WTAP_NUM_FILE_TYPES_SUBTYPES); fprintf(stderr, "mergecap: The available capture file types for the \"-F\" flag are:\n"); - for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) { + for (i = 0; i < WTAP_NUM_FILE_TYPES_SUBTYPES; i++) { if (wtap_dump_can_open(i)) { - captypes[i].sstr = wtap_file_type_short_string(i); - captypes[i].lstr = wtap_file_type_string(i); + captypes[i].sstr = wtap_file_type_subtype_short_string(i); + captypes[i].lstr = wtap_file_type_subtype_string(i); list = g_slist_insert_sorted(list, &captypes[i], string_compare); } } @@ -175,99 +152,190 @@ list_capture_types(void) { } static void -list_encap_types(void) { - int i; - struct string_elem *encaps; - GSList *list = NULL; - - encaps = g_malloc(sizeof(struct string_elem) * WTAP_NUM_ENCAP_TYPES); - fprintf(stderr, "mergecap: The available encapsulation types for the \"-T\" flag are:\n"); - for (i = 0; i < WTAP_NUM_ENCAP_TYPES; i++) { - encaps[i].sstr = wtap_encap_short_string(i); - if (encaps[i].sstr != NULL) { - encaps[i].lstr = wtap_encap_string(i); - list = g_slist_insert_sorted(list, &encaps[i], string_compare); +list_idb_merge_modes(void) { + int i; + + fprintf(stderr, "mergecap: The available IDB merge modes for the \"-I\" flag are:\n"); + for (i = 0; i < IDB_MERGE_MODE_MAX; i++) { + fprintf(stderr, " %s\n", merge_idb_merge_mode_to_string(i)); + } +} + +static gboolean +merge_callback(merge_event event, int num, + const merge_in_file_t in_files[], const guint in_file_count, + void *data _U_) +{ + guint i; + + switch (event) { + + case MERGE_EVENT_INPUT_FILES_OPENED: + for (i = 0; i < in_file_count; i++) { + fprintf(stderr, "mergecap: %s is type %s.\n", in_files[i].filename, + wtap_file_type_subtype_string(wtap_file_type_subtype(in_files[i].wth))); + } + break; + + case MERGE_EVENT_FRAME_TYPE_SELECTED: + /* for this event, num = frame_type */ + if (num == 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_description(first_frame_type), + wtap_encap_name(first_frame_type)); + fprintf(stderr, " %s had type %s (%s)\n", + in_files[i].filename, + wtap_encap_description(this_frame_type), + wtap_encap_name(this_frame_type)); + break; + } } - } - g_slist_foreach(list, string_elem_print, NULL); - g_slist_free(list); - g_free(encaps); + } + fprintf(stderr, "mergecap: selected frame_type %s (%s)\n", + wtap_encap_description(num), + wtap_encap_name(num)); + break; + + case MERGE_EVENT_READY_TO_MERGE: + fprintf(stderr, "mergecap: ready to merge records\n"); + break; + + case MERGE_EVENT_RECORD_WAS_READ: + /* for this event, num = count */ + fprintf(stderr, "Record: %d\n", num); + break; + + case MERGE_EVENT_DONE: + fprintf(stderr, "mergecap: merging complete\n"); + break; + } + + /* false = do not stop merging */ + return FALSE; } int main(int argc, char *argv[]) { - int opt; - - gboolean do_append = FALSE; - gboolean verbose = FALSE; - int in_file_count = 0; - guint snaplen = 0; + char *init_progfile_dir_error; + int opt; + static const struct option long_options[] = { + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'V'}, + {0, 0, 0, 0 } + }; + gboolean do_append = FALSE; + gboolean verbose = FALSE; + int in_file_count = 0; + guint32 snaplen = 0; #ifdef PCAP_NG_DEFAULT - int file_type = WTAP_FILE_PCAPNG; /* default to pcap format */ + int file_type = WTAP_FILE_TYPE_SUBTYPE_PCAPNG; /* default to pcapng format */ #else - int file_type = WTAP_FILE_PCAP; /* default to pcapng format */ + int file_type = WTAP_FILE_TYPE_SUBTYPE_PCAP; /* default to pcap format */ #endif - int frame_type = -2; - int out_fd; - merge_in_file_t *in_files = NULL, *in_file; - int i; - struct wtap_pkthdr *phdr, snap_phdr; - wtap_dumper *pdh; - int open_err, read_err=0, write_err, close_err; - gchar *err_info; - int err_fileno; - char *out_filename = NULL; - gboolean got_read_error = FALSE, got_write_error = FALSE; - int count; + int err = 0; + gchar *err_info = NULL; + int err_fileno; + guint32 err_framenum; + char *out_filename = NULL; + merge_result status = MERGE_OK; + idb_merge_mode mode = IDB_MERGE_MODE_MAX; + merge_progress_callback_t cb; + + cmdarg_err_init(mergecap_cmdarg_err, mergecap_cmdarg_err_cont); #ifdef _WIN32 - arg_list_utf_16to8(argc, argv); + create_app_running_mutex(); #endif /* _WIN32 */ + /* Initialize the version information. */ + ws_init_version_info("Mergecap (Wireshark)", NULL, NULL, NULL); + + /* + * Get credential information for later use. + */ + init_process_policies(); + + /* + * Attempt to get the pathname of the directory containing the + * executable file. + */ + init_progfile_dir_error = init_progfile_dir(argv[0]); + if (init_progfile_dir_error != NULL) { + fprintf(stderr, + "mergecap: Can't get pathname of directory containing the mergecap program: %s.\n", + init_progfile_dir_error); + g_free(init_progfile_dir_error); + } + + init_report_message(failure_warning_message, failure_warning_message, + NULL, NULL, NULL); + + wtap_init(TRUE); + /* Process the options first */ - while ((opt = getopt(argc, argv, "hvas:T:F:w:")) != -1) { + while ((opt = getopt_long(argc, argv, "aF:hI:s:vVw:", long_options, NULL)) != -1) { switch (opt) { - case 'w': - out_filename = optarg; - break; - case 'a': do_append = !do_append; break; - case 'T': - frame_type = wtap_short_string_to_encap(optarg); - if (frame_type < 0) { - fprintf(stderr, "mergecap: \"%s\" isn't a valid encapsulation type\n", - optarg); - list_encap_types(); - exit(1); - } - break; - case 'F': - file_type = wtap_short_string_to_file_type(optarg); + file_type = wtap_short_string_to_file_type_subtype(optarg); if (file_type < 0) { - fprintf(stderr, "mergecap: \"%s\" isn't a valid capture file type\n", - optarg); + fprintf(stderr, "mergecap: \"%s\" isn't a valid capture file type\n", + optarg); list_capture_types(); - exit(1); + status = MERGE_ERR_INVALID_OPTION; + goto clean_exit; } break; + case 'h': + show_help_header("Merge two or more capture files into one."); + print_usage(stdout); + goto clean_exit; + break; + + case 'I': + mode = merge_string_to_idb_merge_mode(optarg); + if (mode == IDB_MERGE_MODE_MAX) { + fprintf(stderr, "mergecap: \"%s\" isn't a valid IDB merge mode\n", + optarg); + list_idb_merge_modes(); + status = MERGE_ERR_INVALID_OPTION; + goto clean_exit; + } + break; + + case 's': + snaplen = get_nonzero_guint32(optarg, "snapshot length"); + break; + case 'v': verbose = TRUE; break; - case 's': - snaplen = get_positive_int(optarg, "snapshot length"); + case 'V': + show_version(); + goto clean_exit; break; - case 'h': - usage(); - exit(0); + case 'w': + out_filename = optarg; break; case '?': /* Bad options if GNU getopt */ @@ -275,19 +343,21 @@ main(int argc, char *argv[]) case'F': list_capture_types(); break; - case'T': - list_encap_types(); + case'I': + list_idb_merge_modes(); break; default: - usage(); + print_usage(stderr); } - exit(1); + status = MERGE_ERR_INVALID_OPTION; + goto clean_exit; break; - } - } + cb.callback_func = merge_callback; + cb.data = NULL; + /* check for proper args; at a minimum, must have an output * filename and one input file */ @@ -295,214 +365,102 @@ main(int argc, char *argv[]) if (!out_filename) { fprintf(stderr, "mergecap: an output filename must be set with -w\n"); fprintf(stderr, " run with -h for help\n"); - return 1; + status = MERGE_ERR_INVALID_OPTION; + goto clean_exit; } if (in_file_count < 1) { fprintf(stderr, "mergecap: No input files were specified\n"); return 1; } - /* open the input files */ - if (!merge_open_in_files(in_file_count, &argv[optind], &in_files, - &open_err, &err_info, &err_fileno)) { - fprintf(stderr, "mergecap: Can't open %s: %s\n", argv[optind + err_fileno], - wtap_strerror(open_err)); - switch (open_err) { - - case WTAP_ERR_UNSUPPORTED: - case WTAP_ERR_UNSUPPORTED_ENCAP: - case WTAP_ERR_BAD_FILE: - fprintf(stderr, "(%s)\n", err_info); - g_free(err_info); - break; - } - return 2; + /* setting IDB merge mode must use PCAPNG output */ + if (mode != IDB_MERGE_MODE_MAX && file_type != WTAP_FILE_TYPE_SUBTYPE_PCAPNG) { + fprintf(stderr, "The IDB merge mode can only be used with PCAPNG output format\n"); + status = MERGE_ERR_INVALID_OPTION; + goto clean_exit; } - 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 - * snapshot lengths of the input files. - */ - snaplen = merge_max_snapshot_length(in_file_count, in_files); - } - - /* set the outfile frame type */ - 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); - 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)); - } + /* if they didn't set IDB merge mode, set it to our default */ + if (mode == IDB_MERGE_MODE_MAX) { + mode = IDB_MERGE_MODE_ALL_SAME; } /* open the outfile */ - if (strncmp(out_filename, "-", 2) == 0) { - /* use stdout as the outfile */ - out_fd = 1 /*stdout*/; + if (strcmp(out_filename, "-") == 0) { + /* merge the files to the standard output */ + status = merge_files_to_stdout(file_type, + (const char *const *) &argv[optind], + in_file_count, do_append, mode, snaplen, + get_appname_and_version(), + verbose ? &cb : NULL, + &err, &err_info, &err_fileno, &err_framenum); } else { - /* open the outfile */ - out_fd = ws_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, g_strerror(errno)); - exit(1); - } - } - - /* prepare the outfile */ - if(file_type == WTAP_FILE_PCAPNG ){ - wtapng_section_t *shb_hdr; - GString *comment_gstr; - - shb_hdr = g_new(wtapng_section_t,1); - comment_gstr = g_string_new("File created by merging: \n"); - - for (i = 0; i < in_file_count; i++) { - g_string_append_printf(comment_gstr, "File%d: %s \n",i+1,in_files[i].filename); - } - shb_hdr->section_length = -1; - /* options */ - shb_hdr->opt_comment = comment_gstr->str; /* NULL if not available */ - shb_hdr->shb_hardware = NULL; /* NULL if not available, UTF-8 string containing the description of the hardware used to create this section. */ - shb_hdr->shb_os = NULL; /* NULL if not available, UTF-8 string containing the name of the operating system used to create this section. */ - shb_hdr->shb_user_appl = "mergecap"; /* NULL if not available, UTF-8 string containing the name of the application used to create this section. */ - - pdh = wtap_dump_fdopen_ng(out_fd, file_type, frame_type, snaplen, - FALSE /* compressed */, shb_hdr, NULL /* wtapng_iface_descriptions_t *idb_inf */, &open_err); - g_string_free(comment_gstr, TRUE); - }else{ - pdh = wtap_dump_fdopen(out_fd, file_type, frame_type, snaplen, FALSE /* compressed */, &open_err); - } - if (pdh == NULL) { - merge_close_in_files(in_file_count, in_files); - g_free(in_files); - fprintf(stderr, "mergecap: Can't open or create %s: %s\n", out_filename, - wtap_strerror(open_err)); - exit(1); + /* merge the files to the outfile */ + status = merge_files(out_filename, file_type, + (const char *const *) &argv[optind], in_file_count, + do_append, mode, snaplen, get_appname_and_version(), + verbose ? &cb : NULL, + &err, &err_info, &err_fileno, &err_framenum); } - /* do the merge (or append) */ - count = 1; - for (;;) { - if (do_append) - in_file = merge_append_read_packet(in_file_count, in_files, &read_err, - &err_info); - else - in_file = merge_read_packet(in_file_count, in_files, &read_err, - &err_info); - if (in_file == NULL) { - /* EOF */ + switch (status) { + case MERGE_OK: break; - } - if (read_err != 0) { - /* I/O error reading from in_file */ - got_read_error = TRUE; + case MERGE_USER_ABORTED: + /* we don't catch SIGINT/SIGTERM (yet?), so we couldn't have aborted */ + g_assert(FALSE); break; - } - if (verbose) - fprintf(stderr, "Record: %u\n", count++); + case MERGE_ERR_CANT_OPEN_INFILE: + cfile_open_failure_message("mergecap", argv[optind + err_fileno], + err, err_info); + break; - /* We simply write it, perhaps after truncating it; we could do other - * things, like modify it. */ - phdr = wtap_phdr(in_file->wth); - if (snaplen != 0 && phdr->caplen > snaplen) { - snap_phdr = *phdr; - snap_phdr.caplen = snaplen; - phdr = &snap_phdr; - } + case MERGE_ERR_CANT_OPEN_OUTFILE: + cfile_dump_open_failure_message("mergecap", out_filename, err, file_type); + break; - if (!wtap_dump(pdh, phdr, wtap_pseudoheader(in_file->wth), - wtap_buf_ptr(in_file->wth), &write_err)) { - got_write_error = TRUE; + case MERGE_ERR_CANT_READ_INFILE: + cfile_read_failure_message("mergecap", argv[optind + err_fileno], + err, err_info); break; - } - } - 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].state == GOT_ERROR) { - fprintf(stderr, "mergecap: Error reading %s: %s\n", - in_files[i].filename, wtap_strerror(read_err)); - switch (read_err) { - - case WTAP_ERR_UNSUPPORTED: - case WTAP_ERR_UNSUPPORTED_ENCAP: - case WTAP_ERR_BAD_FILE: - fprintf(stderr, "(%s)\n", err_info); - g_free(err_info); - break; - } - } - } - } + case MERGE_ERR_BAD_PHDR_INTERFACE_ID: + cmdarg_err("Record %u of \"%s\" has an interface ID that does not match any IDB in its file.", + err_framenum, argv[optind + err_fileno]); + break; - if (got_write_error) { - switch (write_err) { + case MERGE_ERR_CANT_WRITE_OUTFILE: + cfile_write_failure_message("mergecap", argv[optind + err_fileno], + out_filename, err, err_info, err_framenum, + file_type); + break; - case WTAP_ERR_UNSUPPORTED_ENCAP: - /* - * This is a problem with the particular frame we're writing; - * note that, and give the frame number. - */ - fprintf(stderr, "mergecap: Frame %u of \"%s\" has a network type that can't be saved in a file with that format\n.", - in_file->packet_num, in_file->filename); - break; + case MERGE_ERR_CANT_CLOSE_OUTFILE: + cfile_close_failure_message(out_filename, err); + break; default: - fprintf(stderr, "mergecap: Error writing to outfile: %s\n", - wtap_strerror(write_err)); + cmdarg_err("Unknown merge_files error %d", status); break; - } } - g_free(in_files); - - return (!got_read_error && !got_write_error) ? 0 : 2; +clean_exit: + wtap_cleanup(); + free_progdirs(); + return (status == MERGE_OK) ? 0 : 2; } + +/* + * Editor modelines - http://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 2 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=2 tabstop=8 expandtab: + * :indentSize=2:tabSize=8:noTabs=true: + */