On at least some platforms, a #define of O_BINARY is needed even if
[metze/wireshark/wip.git] / mergecap.c
1 /* Combine two dump files, either by appending or by merging by timestamp
2  *
3  * $Id: mergecap.c,v 1.23 2004/06/30 06:58:57 guy Exp $
4  *
5  * Written by Scott Renfro <scott@renfro.org> based on
6  * editcap by Richard Sharpe and Guy Harris
7  *
8  */
9
10 #ifdef HAVE_CONFIG_H
11 #include "config.h"
12 #endif
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <glib.h>
17
18 #ifdef HAVE_UNISTD_H
19 #include <unistd.h>
20 #endif
21
22 #ifdef HAVE_SYS_TIME_H
23 #include <sys/time.h>
24 #endif
25
26 #include <string.h>
27 #include "wtap.h"
28
29 #ifdef NEED_GETOPT_H
30 #include "getopt.h"
31 #endif
32
33 #include "cvsversion.h"
34 #include "merge.h"
35
36 #ifdef HAVE_IO_H
37 # include <io.h>
38 #endif
39
40 #ifdef HAVE_FCNTL_H
41 #include <fcntl.h>
42 #endif
43
44 /* Win32 needs the O_BINARY flag for open() */
45 #ifndef O_BINARY
46 #define O_BINARY        0
47 #endif
48
49 /*
50  * Show the usage
51  */
52 static void
53 usage(void)
54 {
55   int i;
56   const char *string;
57
58   printf("Usage: mergecap [-hva] [-s <snaplen>] [-T <encap type>]\n");
59   printf("          [-F <capture type>] -w <outfile> <infile> [...]\n\n");
60   printf("  where\t-h produces this help listing.\n");
61   printf("       \t-v verbose operation, default is silent\n");
62   printf("       \t-a files should be concatenated, not merged\n");
63   printf("       \t     Default merges based on frame timestamps\n");
64   printf("       \t-s <snaplen>: truncate packets to <snaplen> bytes of data\n");
65   printf("       \t-w <outfile>: sets output filename to <outfile>\n");
66   printf("       \t-T <encap type> encapsulation type to use:\n");
67   for (i = 0; i < WTAP_NUM_ENCAP_TYPES; i++) {
68       string = wtap_encap_short_string(i);
69       if (string != NULL)
70         printf("       \t     %s - %s\n",
71           string, wtap_encap_string(i));
72   }
73   printf("       \t     default is the same as the first input file\n");
74   printf("       \t-F <capture type> capture file type to write:\n");
75   for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
76     if (wtap_dump_can_open(i))
77       printf("       \t     %s - %s\n",
78         wtap_file_type_short_string(i), wtap_file_type_string(i));
79   }
80   printf("       \t     default is libpcap\n");
81 }
82
83
84
85 int
86 main(int argc, char *argv[])
87 {
88   extern char *optarg;
89   extern int   optind;
90   int          opt;
91   char        *p;
92   gboolean     do_append     = FALSE;
93   int          in_file_count = 0;
94   merge_in_file_t   *in_files      = NULL;
95   merge_out_file_t   out_file;
96   int          err;
97   char        *out_filename;
98
99   /* initialize out_file */
100   out_file.fd         = 0;
101   out_file.pdh        = NULL;              /* wiretap dumpfile */
102   out_file.file_type  = WTAP_FILE_PCAP;    /* default to "libpcap" */
103   out_file.frame_type = -2;                /* leave type alone */
104   out_file.snaplen    = 0;                 /* no limit */
105   out_file.count      = 1;                 /* frames output */
106
107   merge_verbose = VERBOSE_ERRORS;
108
109   /* Process the options first */
110   while ((opt = getopt(argc, argv, "hvas:T:F:w:")) != -1) {
111
112     switch (opt) {
113     case 'w':
114           out_filename = optarg;
115       break;
116
117     case 'a':
118       do_append = !do_append;
119       break;
120
121     case 'T':
122       out_file.frame_type = wtap_short_string_to_encap(optarg);
123       if (out_file.frame_type < 0) {
124         fprintf(stderr, "mergecap: \"%s\" is not a valid encapsulation type\n",
125             optarg);
126         exit(1);
127       }
128       break;
129
130     case 'F':
131       out_file.file_type = wtap_short_string_to_file_type(optarg);
132       if (out_file.file_type < 0) {
133         fprintf(stderr, "mergecap: \"%s\" is not a valid capture file type\n",
134             optarg);
135         exit(1);
136       }
137       break;
138
139     case 'v':
140       merge_verbose = VERBOSE_ALL;
141       break;
142
143     case 's':
144       out_file.snaplen = strtol(optarg, &p, 10);
145       if (p == optarg || *p != '\0') {
146         fprintf(stderr, "mergecap: \"%s\" is not a valid snapshot length\n",
147             optarg);
148         exit(1);
149       }
150       break;
151
152     case 'h':
153       printf("mergecap version %s"
154 #ifdef CVSVERSION
155           " (" CVSVERSION ")"
156 #endif
157           "\n", VERSION);
158       usage();
159       exit(0);
160       break;
161
162     case '?':              /* Bad options if GNU getopt */
163       usage();
164       exit(1);
165       break;
166
167     }
168
169   }
170
171   /* check for proper args; at a minimum, must have an output
172    * filename and one input file
173    */
174   in_file_count = argc - optind;
175   if (!out_filename) {
176     fprintf(stderr, "mergecap: an output filename must be set with -w\n");
177     fprintf(stderr, "          run with -h for help\n");
178     exit(1);
179   }
180
181   /* open the input files */
182   in_file_count = merge_open_in_files(in_file_count, &argv[optind], &in_files, &err);
183   if (in_file_count < 1) {
184     fprintf(stderr, "mergecap: No valid input files\n");
185     exit(1);
186   }
187
188   /* set the outfile frame type */
189   if (out_file.frame_type == -2)
190     out_file.frame_type = merge_select_frame_type(in_file_count, in_files);
191
192   /* open the outfile */
193   if (strncmp(out_filename, "-", 2) == 0) {  
194     /* use stdout as the outfile */
195     out_file.fd = 1 /*stdout*/;
196   } else {
197     /* open the outfile */
198     out_file.fd = open(out_filename, O_BINARY | O_WRONLY);
199   }
200   if(out_file.fd == -1) {
201     fprintf(stderr, "mergecap: couldn't open output file\n");
202     exit(1);
203   }  
204     
205   /* prepare the outfile */
206   if (!merge_open_outfile(&out_file, merge_max_snapshot_length(in_file_count, in_files), &err)) {
207     merge_close_in_files(in_file_count, in_files);
208     exit(1);
209   }
210
211   /* do the merge (or append) */
212   if (do_append)
213     merge_append_files(in_file_count, in_files, &out_file, &err);
214   else
215     merge_files(in_file_count, in_files, &out_file, &err);
216
217   merge_close_in_files(in_file_count, in_files);
218   merge_close_outfile(&out_file);
219
220   free(in_files);
221
222   return 0;
223 }