1 /* Combine multiple dump files, either by appending or by merging by timestamp
5 * Written by Scott Renfro <scott@renfro.org> based on
6 * editcap by Richard Sharpe and Guy Harris
23 #ifdef HAVE_SYS_TIME_H
27 #ifdef HAVE_SYS_STAT_H
36 * Scan through the arguments and open the input files
39 merge_open_in_files(int in_file_count, char *const *in_file_names,
40 merge_in_file_t **in_files, int *err, gchar **err_info,
44 int files_size = in_file_count * sizeof(merge_in_file_t);
45 merge_in_file_t *files;
48 files = g_malloc(files_size);
51 for (i = 0; i < in_file_count; i++) {
52 files[i].filename = in_file_names[i];
53 files[i].wth = wtap_open_offline(in_file_names[i], err, err_info, FALSE);
54 files[i].data_offset = 0;
55 files[i].state = PACKET_NOT_PRESENT;
57 /* Close the files we've already opened. */
58 for (j = 0; j < i; j++)
59 wtap_close(files[j].wth);
63 if (fstat(wtap_fd(files[i].wth), &statb) < 0) {
65 for (j = 0; j <= i; j++)
66 wtap_close(files[j].wth);
70 files[i].size = statb.st_size;
76 * Scan through and close each input file
79 merge_close_in_files(int count, merge_in_file_t in_files[])
82 for (i = 0; i < count; i++) {
83 wtap_close(in_files[i].wth);
88 * Select an output frame type based on the input files
89 * From Guy: If all files have the same frame type, then use that.
90 * Otherwise select WTAP_ENCAP_PER_PACKET. If the selected
91 * output file type doesn't support per packet frame types,
92 * then the wtap_dump_open call will fail with a reasonable
96 merge_select_frame_type(int count, merge_in_file_t files[])
99 int selected_frame_type;
101 selected_frame_type = wtap_file_encap(files[0].wth);
103 for (i = 1; i < count; i++) {
104 int this_frame_type = wtap_file_encap(files[i].wth);
105 if (selected_frame_type != this_frame_type) {
106 selected_frame_type = WTAP_ENCAP_PER_PACKET;
111 return selected_frame_type;
115 * Scan through input files and find maximum snapshot length
118 merge_max_snapshot_length(int count, merge_in_file_t in_files[])
121 int max_snapshot = 0;
124 for (i = 0; i < count; i++) {
125 snapshot_length = wtap_snapshot_length(in_files[i].wth);
126 if (snapshot_length == 0) {
127 /* Snapshot length of input file not known. */
128 snapshot_length = WTAP_MAX_PACKET_SIZE;
130 if (snapshot_length > max_snapshot)
131 max_snapshot = snapshot_length;
137 * returns TRUE if first argument is earlier than second
140 is_earlier(struct timeval *l, struct timeval *r) {
141 if (l->tv_sec > r->tv_sec) { /* left is later */
143 } else if (l->tv_sec < r->tv_sec) { /* left is earlier */
145 } else if (l->tv_usec > r->tv_usec) { /* tv_sec equal, l.usec later */
148 /* either one < two or one == two
149 * either way, return one
155 * Read the next packet, in chronological order, from the set of files
159 merge_read_packet(int in_file_count, merge_in_file_t in_files[], int *err,
164 struct timeval tv = {LONG_MAX, LONG_MAX};
165 struct wtap_pkthdr *phdr;
168 * Make sure we have a packet available from each file, if there are any
169 * packets left in the file in question, and search for the packet
170 * with the earliest time stamp.
172 for (i = 0; i < in_file_count; i++) {
173 if (in_files[i].state == PACKET_NOT_PRESENT) {
175 * No packet available, and we haven't seen an error or EOF yet,
176 * so try to read the next packet.
178 if (!wtap_read(in_files[i].wth, err, err_info, &in_files[i].data_offset)) {
180 in_files[i].state = GOT_ERROR;
183 in_files[i].state = AT_EOF;
185 in_files[i].state = PACKET_PRESENT;
188 if (in_files[i].state == PACKET_PRESENT) {
189 phdr = wtap_phdr(in_files[i].wth);
190 if (is_earlier(&phdr->ts, &tv)) {
198 /* All the streams are at EOF. Return an EOF indication. */
203 /* We'll need to read another packet from this file. */
204 in_files[ei].state = PACKET_NOT_PRESENT;
206 /* Return a pointer to the wtap structure for the file with that frame. */
207 return in_files[ei].wth;
211 * Read the next packet, in file sequence order, from the set of files
215 merge_append_read_packet(int in_file_count, merge_in_file_t in_files[],
216 int *err, gchar **err_info)
221 * Find the first file not at EOF, and read the next packet from it.
223 for (i = 0; i < in_file_count; i++) {
224 if (in_files[i].state == AT_EOF)
225 continue; /* This file is already at EOF */
226 if (wtap_read(in_files[i].wth, err, err_info, &in_files[i].data_offset))
227 break; /* We have a packet */
229 /* Read error - quit immediately. */
230 in_files[i].state = GOT_ERROR;
233 /* EOF - flag this file as being at EOF, and try the next one. */
234 in_files[i].state = AT_EOF;
236 if (i == in_file_count) {
237 /* All the streams are at EOF. Return an EOF indication. */
242 /* Return a pointer to the wtap structure for the file with that frame. */
243 return in_files[i].wth;