diff options
Diffstat (limited to 'merge.c')
-rw-r--r-- | merge.c | 222 |
1 files changed, 85 insertions, 137 deletions
@@ -1,4 +1,4 @@ -/* Combine two dump files, either by appending or by merging by timestamp +/* Combine multiple dump files, either by appending or by merging by timestamp * * $Id$ * @@ -14,6 +14,7 @@ #include <stdio.h> #include <stdlib.h> #include <glib.h> +#include <errno.h> #ifdef HAVE_UNISTD_H #include <unistd.h> @@ -23,6 +24,10 @@ #include <sys/time.h> #endif +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif + #include <string.h> #include "wtap.h" #include "merge.h" @@ -38,6 +43,7 @@ merge_open_in_files(int in_file_count, char *const *in_file_names, int i, j; int files_size = in_file_count * sizeof(merge_in_file_t); merge_in_file_t *files; + struct stat statb; files = g_malloc(files_size); *in_files = files; @@ -45,9 +51,8 @@ merge_open_in_files(int in_file_count, char *const *in_file_names, for (i = 0; i < in_file_count; i++) { files[i].filename = in_file_names[i]; files[i].wth = wtap_open_offline(in_file_names[i], err, err_info, FALSE); - files[i].err = 0; files[i].data_offset = 0; - files[i].ok = TRUE; + files[i].state = PACKET_NOT_PRESENT; if (!files[i].wth) { /* Close the files we've already opened. */ for (j = 0; j < i; j++) @@ -55,6 +60,14 @@ merge_open_in_files(int in_file_count, char *const *in_file_names, *err_fileno = i; return FALSE; } + if (fstat(wtap_fd(files[i].wth), &statb) < 0) { + *err = errno; + for (j = 0; j <= i; j++) + wtap_close(files[j].wth); + *err_fileno = i; + return FALSE; + } + files[i].size = statb.st_size; } return TRUE; } @@ -72,37 +85,6 @@ merge_close_in_files(int count, merge_in_file_t in_files[]) } /* - * Open the output file - * - * Return FALSE if file cannot be opened (so caller can report an error - * and clean up) - */ -gboolean -merge_open_outfile(merge_out_file_t *out_file, int fd, int file_type, - int frame_type, int snapshot_len, int *err) -{ - out_file->pdh = wtap_dump_fdopen(fd, file_type, frame_type, snapshot_len, - err); - if (!out_file->pdh) - return FALSE; - - out_file->snaplen = snapshot_len; - out_file->count = 1; - return TRUE; -} - -/* - * Close the output file - */ -gboolean -merge_close_outfile(merge_out_file_t *out_file, int *err) -{ - if (!wtap_dump_close(out_file->pdh, err)) - return FALSE; - return TRUE; -} - -/* * 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 @@ -152,29 +134,6 @@ merge_max_snapshot_length(int count, merge_in_file_t in_files[]) } /* - * Routine to write frame to output file - */ -static gboolean -write_frame(wtap *wth, merge_out_file_t *out_file, int *err) -{ - const struct wtap_pkthdr *phdr = wtap_phdr(wth); - struct wtap_pkthdr snap_phdr; - - /* 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(out_file->pdh, phdr, wtap_pseudoheader(wth), wtap_buf_ptr(wth), err)) - return FALSE; - - return TRUE; -} - -/* * returns TRUE if first argument is earlier than second */ static gboolean @@ -192,105 +151,94 @@ is_earlier(struct timeval *l, struct timeval *r) { return TRUE; } - /* - * returns index of earliest timestamp in set of input files - * or -1 if no valid files remain + * Read the next packet, in chronological order, from the set of files + * to be merged. */ -static int -earliest(int count, merge_in_file_t in_files[]) { +wtap * +merge_read_packet(int in_file_count, merge_in_file_t in_files[], int *err, + gchar **err_info) +{ int i; int ei = -1; struct timeval tv = {LONG_MAX, LONG_MAX}; + struct wtap_pkthdr *phdr; - 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; + /* + * Make sure we have a packet available from each file, if there are any + * packets left in the file in question, and search for the packet + * with the earliest time stamp. + */ + for (i = 0; i < in_file_count; i++) { + if (in_files[i].state == PACKET_NOT_PRESENT) { + /* + * No packet available, and we haven't seen an error or EOF yet, + * so try to read the next packet. + */ + if (!wtap_read(in_files[i].wth, err, err_info, &in_files[i].data_offset)) { + if (*err != 0) { + in_files[i].state = GOT_ERROR; + return NULL; + } + in_files[i].state = AT_EOF; + } else + in_files[i].state = PACKET_PRESENT; + } + + if (in_files[i].state == PACKET_PRESENT) { + phdr = wtap_phdr(in_files[i].wth); + if (is_earlier(&phdr->ts, &tv)) { + tv = phdr->ts; + ei = i; + } } - } - return ei; -} - -/* - * actually merge the files - */ -merge_status_e -merge_files(int count, merge_in_file_t in_files[], merge_out_file_t *out_file, int *err) -{ - 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)); - if (!in_files[i].ok) - return MERGE_READ_ERROR; } - /* 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 - */ - if(!write_frame(in_files[i].wth, out_file, err)) - return MERGE_WRITE_ERROR; - in_files[i].ok = wtap_read(in_files[i].wth, &(in_files[i].err), - &(in_files[i].err_info), - &(in_files[i].data_offset)); - if (!in_files[i].ok) - return MERGE_READ_ERROR; + if (ei == -1) { + /* All the streams are at EOF. Return an EOF indication. */ + *err = 0; + return NULL; } - return MERGE_SUCCESS; -} - -static merge_status_e -append_loop(merge_in_file_t in_files[], int i, int count, - merge_out_file_t *out_file, int *err) -{ - gchar *err_info; - long data_offset; - int loop = 0; - - /* Start by clearing error flag */ - *err = 0; - - while ( (wtap_read(in_files[i].wth, err, &err_info, &data_offset)) ) { - if(!write_frame(in_files[i].wth, out_file, err)) - return MERGE_WRITE_ERROR; - if (count > 0 && ++loop >= count) - break; - } + /* We'll need to read another packet from this file. */ + in_files[ei].state = PACKET_NOT_PRESENT; - if (*err != 0) { - in_files[i].ok = FALSE; - in_files[i].err = *err; - in_files[i].err_info = err_info; - return MERGE_READ_ERROR; - } - return MERGE_SUCCESS; + /* Return a pointer to the wtap structure for the file with that frame. */ + return in_files[ei].wth; } /* - * routine to concatenate files + * Read the next packet, in file sequence order, from the set of files + * to be merged. */ -merge_status_e -merge_append_files(int count, merge_in_file_t in_files[], - merge_out_file_t *out_file, int *err) +wtap * +merge_append_read_packet(int in_file_count, merge_in_file_t in_files[], + int *err, gchar **err_info) { int i; - merge_status_e status; - for (i = 0; i < count; i++) { - status = append_loop(in_files, i, 0, out_file, err); - if (status != MERGE_SUCCESS) - return status; + /* + * Find the first file not at EOF, and read the next packet from it. + */ + for (i = 0; i < in_file_count; i++) { + if (in_files[i].state == AT_EOF) + continue; /* This file is already at EOF */ + if (wtap_read(in_files[i].wth, err, err_info, &in_files[i].data_offset)) + break; /* We have a packet */ + if (*err != 0) { + /* Read error - quit immediately. */ + in_files[i].state = GOT_ERROR; + return NULL; + } + /* EOF - flag this file as being at EOF, and try the next one. */ + in_files[i].state = AT_EOF; + } + if (i == in_file_count) { + /* All the streams are at EOF. Return an EOF indication. */ + *err = 0; + return NULL; } - return MERGE_SUCCESS; + /* Return a pointer to the wtap structure for the file with that frame. */ + return in_files[i].wth; } |