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