X-Git-Url: http://git.samba.org/samba.git/?a=blobdiff_plain;f=mergecap.c;h=07552bc1216d50b8e0085fef2a7b2938a8eb972c;hb=0d6143632e8963928daaf1963eb7d18b8b5e4e13;hp=ca36f06b56a4a73552a13dd94ee4aba02d7fa690;hpb=35b18a677e81338c56d573a31f2be886b967261b;p=obnox%2Fwireshark%2Fwip.git diff --git a/mergecap.c b/mergecap.c index ca36f06b56..07552bc121 100644 --- a/mergecap.c +++ b/mergecap.c @@ -1,6 +1,6 @@ /* Combine two dump files, either by appending or by merging by timestamp * - * $Id: mergecap.c,v 1.17 2004/01/25 22:21:39 guy Exp $ + * $Id$ * * Written by Scott Renfro based on * editcap by Richard Sharpe and Guy Harris @@ -13,6 +13,7 @@ #include #include +#include #include #ifdef HAVE_UNISTD_H @@ -30,343 +31,21 @@ #include "getopt.h" #endif -#include "cvsversion.h" +#include "svnversion.h" +#include "merge.h" -/* - * Global variables - */ -static int verbose = 0; /* Not so verbose */ - -/* - * Structures to manage our files - */ -typedef struct in_file_t { - const char *filename; - wtap *wth; - int err; - gchar *err_info; - long data_offset; - gboolean ok; -} in_file_t; - -typedef struct out_file_t { - const char *filename; - wtap_dumper *pdh; - int file_type; - int frame_type; - unsigned int snaplen; - int count; -} out_file_t; -static out_file_t out_file; - -/* - * Routine to write frame to output file - */ -static void -write_frame(guchar *user, const struct wtap_pkthdr *phdr, long offset _U_, - union wtap_pseudo_header *pseudo_header, const guchar *buf) -{ - wtap_dumper *pdh = (wtap_dumper*)user; - int err; - struct wtap_pkthdr snap_phdr; - - if (verbose) - printf("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; - } - - if (!wtap_dump(pdh, phdr, pseudo_header, buf, &err)) { - fprintf(stderr, "mergecap: Error writing to %s: %s\n", - out_file.filename, wtap_strerror(err)); - exit(1); - } -} - - -/* - * routine to concatenate files - */ -static void -append(int count, in_file_t in_files[], out_file_t *out_file) -{ - int i; - int err; - gchar *err_info; - - for (i = 0; i < count; i++) { - if (!wtap_loop(in_files[i].wth, 0, write_frame, - (guchar*)out_file->pdh, &err, &err_info)) { - fprintf(stderr, "mergecap: Error reading %s to append to %s: %s\n", - in_files[i].filename, out_file->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; - } - } - } -} - - -/* - * returns TRUE if first argument is earlier than second - */ -static gboolean -is_earlier(struct timeval *l, struct timeval *r) { - if (l->tv_sec > r->tv_sec) { /* left is later */ - return FALSE; - } else if (l->tv_sec < r->tv_sec) { /* left is earlier */ - return TRUE; - } else if (l->tv_usec > r->tv_usec) { /* tv_sec equal, l.usec later */ - return FALSE; - } - /* either one < two or one == two - * either way, return one - */ - return TRUE; -} - - -/* - * returns index of earliest timestamp in set of input files - * or -1 if no valid files remain - */ -static int -earliest(int count, in_file_t in_files[]) { - int i; - int ei = -1; - struct timeval tv = {LONG_MAX, LONG_MAX}; - - for (i = 0; i < count; i++) { - struct wtap_pkthdr *phdr = wtap_phdr(in_files[i].wth); - - if (in_files[i].ok && is_earlier(&(phdr->ts), &tv)) { - tv = phdr->ts; - ei = i; - } - } - return ei; -} - -/* - * actually merge the files - */ -static void -merge(int count, in_file_t in_files[], out_file_t *out_file) -{ - int i; - - /* prime the pump (read in first frame from each file) */ - for (i = 0; i < count; 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)); - } - - /* now keep writing the earliest frame until we're out of frames */ - while ( -1 != (i = earliest(count, in_files))) { - - /* write out earliest frame, and fetch another from its - * input file - */ - write_frame((guchar*)out_file->pdh, - wtap_phdr(in_files[i].wth), - in_files[i].data_offset, - wtap_pseudoheader(in_files[i].wth), - wtap_buf_ptr(in_files[i].wth)); - in_files[i].ok = wtap_read(in_files[i].wth, &(in_files[i].err), - &(in_files[i].err_info), - &(in_files[i].data_offset)); - } -} - - -/* - * 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. - */ -static int -select_frame_type(int count, 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; - if (verbose) { - 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)); - } - break; - } - } - - if (verbose) { - 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 - */ -static void -close_outfile(out_file_t *out_file) -{ - int err; - if (!wtap_dump_close(out_file->pdh, &err)) { - fprintf(stderr, "mergecap: Error closing file %s: %s\n", - out_file->filename, wtap_strerror(err)); - exit(1); - } -} - - -/* - * Open the output file - * - * Return FALSE if file cannot be opened (so caller can clean up) - */ -static gboolean -open_outfile(out_file_t *out_file, int snapshot_len) -{ - int err; - if (!out_file) { - fprintf(stderr, "mergecap: internal error (null out_file)\n"); - exit(1); - } - - out_file->pdh = wtap_dump_open(out_file->filename, out_file->file_type, - out_file->frame_type, snapshot_len, &err); - if (!out_file->pdh) { - fprintf(stderr, "mergecap: Can't open/create %s:\n", out_file->filename); - fprintf(stderr, " %s\n", wtap_strerror(err)); - return FALSE; - } - return TRUE; -} - - -/* - * Scan through input files and find maximum snapshot length - */ -static int -max_snapshot_length(int count, in_file_t in_files[]) -{ - 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 - */ -static void -close_in_files(int count, 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 - */ -static int -open_in_files(int argc, char *argv[], in_file_t *in_files[]) -{ - int i; - int count = 0; - int err; - gchar *err_info; - in_file_t *files; - int files_size = argc * sizeof(in_file_t); - - - files = malloc(files_size); - if (!files) { - fprintf(stderr, "mergecap: error allocating %d bytes of memory\n", - files_size); - exit(1); - } - *in_files = files; - - for (i = 0; i < argc; i++) { - files[count].filename = argv[i]; - files[count].wth = wtap_open_offline(argv[i], &err, &err_info, FALSE); - files[count].err = 0; - files[count].data_offset = 0; - files[count].ok = TRUE; - if (!files[count].wth) { - fprintf(stderr, "mergecap: skipping %s: %s\n", argv[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 { - if (verbose) { - fprintf(stderr, "mergecap: %s is type %s.\n", argv[i], - wtap_file_type_string(wtap_file_type(files[count].wth))); - } - count++; - } - } - if (verbose) - fprintf(stderr, "mergecap: opened %d of %d input files\n", count, - argc); +#ifdef HAVE_IO_H +# include +#endif - return count; -} +#ifdef HAVE_FCNTL_H +#include +#endif +/* Win32 needs the O_BINARY flag for open() */ +#ifndef O_BINARY +#define O_BINARY 0 +#endif /* * Show the usage @@ -413,22 +92,27 @@ main(int argc, char *argv[]) char *p; gboolean do_append = FALSE; int in_file_count = 0; - in_file_t *in_files = NULL; + merge_in_file_t *in_files = NULL; + merge_out_file_t out_file; + int err; + char *out_filename = NULL; /* initialize out_file */ - out_file.filename = NULL; + 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 */ while ((opt = getopt(argc, argv, "hvas:T:F:w:")) != -1) { switch (opt) { case 'w': - out_file.filename = optarg; + out_filename = optarg; break; case 'a': @@ -454,7 +138,7 @@ main(int argc, char *argv[]) break; case 'v': - verbose = !verbose; /* Just invert */ + merge_verbose = VERBOSE_ALL; break; case 's': @@ -468,8 +152,8 @@ main(int argc, char *argv[]) case 'h': printf("mergecap version %s" -#ifdef CVSVERSION - " (cvs " CVSVERSION ")" +#ifdef SVNVERSION + " (" SVNVERSION ")" #endif "\n", VERSION); usage(); @@ -489,14 +173,14 @@ main(int argc, char *argv[]) * filename and one input file */ in_file_count = argc - optind; - if (!out_file.filename) { + if (!out_filename) { fprintf(stderr, "mergecap: an output filename must be set with -w\n"); fprintf(stderr, " run with -h for help\n"); exit(1); } /* open the input files */ - in_file_count = open_in_files(in_file_count, &argv[optind], &in_files); + in_file_count = merge_open_in_files(in_file_count, &argv[optind], &in_files, &err); if (in_file_count < 1) { fprintf(stderr, "mergecap: No valid input files\n"); exit(1); @@ -504,22 +188,36 @@ main(int argc, char *argv[]) /* set the outfile frame type */ if (out_file.frame_type == -2) - out_file.frame_type = select_frame_type(in_file_count, in_files); + out_file.frame_type = merge_select_frame_type(in_file_count, in_files); /* open the outfile */ - if (!open_outfile(&out_file, max_snapshot_length(in_file_count, in_files))) { - close_in_files(in_file_count, in_files); + if (strncmp(out_filename, "-", 2) == 0) { + /* use stdout as the outfile */ + out_file.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); + } + + /* prepare the outfile */ + if (!merge_open_outfile(&out_file, merge_max_snapshot_length(in_file_count, in_files), &err)) { + merge_close_in_files(in_file_count, in_files); exit(1); } /* do the merge (or append) */ if (do_append) - append(in_file_count, in_files, &out_file); + merge_append_files(in_file_count, in_files, &out_file, &err); else - merge(in_file_count, in_files, &out_file); + merge_files(in_file_count, in_files, &out_file, &err); - close_in_files(in_file_count, in_files); - close_outfile(&out_file); + merge_close_in_files(in_file_count, in_files); + merge_close_outfile(&out_file); free(in_files);