aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--file.c5
-rw-r--r--merge.c378
-rw-r--r--merge.h25
-rw-r--r--mergecap.c81
4 files changed, 224 insertions, 265 deletions
diff --git a/file.c b/file.c
index f1a407fc51..f54a520e76 100644
--- a/file.c
+++ b/file.c
@@ -980,9 +980,8 @@ cf_merge_files(const char *out_filename, int out_fd, int in_file_count,
gboolean ret;
/* open the input files */
- in_file_count = merge_open_in_files(in_file_count, in_filenames, &in_files,
- &err, &err_info, &err_fileno);
- if (in_file_count < 2) {
+ if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
+ &err, &err_info, &err_fileno)) {
free(in_files);
cf_open_failure_alert_box(in_filenames[err_fileno], err, err_info, FALSE, 0);
return FALSE;
diff --git a/merge.c b/merge.c
index 2c7c7b566f..5d5f88298b 100644
--- a/merge.c
+++ b/merge.c
@@ -28,99 +28,152 @@
#include "merge.h"
/*
- * Global variables
+ * Scan through the arguments and open the input files
*/
-int merge_verbose = VERBOSE_NONE;
+gboolean
+merge_open_in_files(int in_file_count, char *const *in_file_names,
+ merge_in_file_t **in_files, int *err, gchar **err_info,
+ int *err_fileno)
+{
+ int i, j;
+ int files_size = in_file_count * sizeof(merge_in_file_t);
+ merge_in_file_t *files;
+ files = g_malloc(files_size);
+ *in_files = files;
+
+ 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;
+ if (!files[i].wth) {
+ /* Close the files we've already opened. */
+ for (j = 0; j < i; j++)
+ wtap_close(files[j].wth);
+ *err_fileno = i;
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
/*
- * Routine to write frame to output file
+ * Scan through and close each input file
*/
-static gboolean
-write_frame(wtap *wth, merge_out_file_t *out_file, int *err)
+void
+merge_close_in_files(int count, merge_in_file_t in_files[])
{
- const struct wtap_pkthdr *phdr = wtap_phdr(wth);
- struct wtap_pkthdr snap_phdr;
-
- if (merge_verbose == VERBOSE_ALL)
- fprintf(stderr, "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;
+ int i;
+ for (i = 0; i < count; i++) {
+ wtap_close(in_files[i].wth);
}
+}
- if (!wtap_dump(out_file->pdh, phdr, wtap_pseudoheader(wth), wtap_buf_ptr(wth), err)) {
- if (merge_verbose == VERBOSE_ERRORS)
- fprintf(stderr, "mergecap: Error writing to outfile: %s\n",
- wtap_strerror(*err));
+/*
+ * 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;
}
-
-static gboolean
-append_loop(wtap *wth, int count, merge_out_file_t *out_file, int *err,
- gchar **err_info)
+/*
+ * Close the output file
+ */
+gboolean
+merge_close_outfile(merge_out_file_t *out_file, int *err)
{
- long data_offset;
- int loop = 0;
-
- /* Start by clearing error flag */
- *err = 0;
-
- while ( (wtap_read(wth, err, err_info, &data_offset)) ) {
- if(!write_frame(wth, out_file, err))
- return FALSE; /* failure */
- if (count > 0 && ++loop >= count)
- break;
- }
-
- if (*err == 0) {
- return TRUE; /* success */
- } else {
- return FALSE; /* failure */
- }
+ 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
+ * output file type doesn't support per packet frame types,
+ * then the wtap_dump_open call will fail with a reasonable
+ * error condition.
+ */
+int
+merge_select_frame_type(int count, merge_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;
+ break;
+ }
+ }
+
+ return selected_frame_type;
+}
/*
- * routine to concatenate files
+ * Scan through input files and find maximum snapshot length
*/
-gboolean
-merge_append_files(int count, merge_in_file_t in_files[], merge_out_file_t *out_file, int *err)
+int
+merge_max_snapshot_length(int count, merge_in_file_t in_files[])
{
int i;
- gchar *err_info;
+ int max_snapshot = 0;
+ int snapshot_length;
for (i = 0; i < count; i++) {
- if (!append_loop(in_files[i].wth, 0, out_file, err, &err_info)) {
- if (merge_verbose == VERBOSE_ERRORS)
- fprintf(stderr, "mergecap: Error appending %s to outfile: %s\n",
- in_files[i].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;
- }
- return FALSE;
+ 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;
+}
+
+/*
+ * 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
*/
@@ -174,6 +227,10 @@ merge_files(int count, merge_in_file_t in_files[], merge_out_file_t *out_file, 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) {
+ /* Read failure, not write failure. */
+ return TRUE;
+ }
}
/* now keep writing the earliest frame until we're out of frames */
@@ -187,196 +244,55 @@ merge_files(int count, merge_in_file_t in_files[], merge_out_file_t *out_file, 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) {
+ /* Read failure, not write failure. */
+ return TRUE;
+ }
}
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
- * output file type doesn't support per packet frame types,
- * then the wtap_dump_open call will fail with a reasonable
- * error condition.
- */
-int
-merge_select_frame_type(int count, merge_in_file_t files[])
+static gboolean
+append_loop(merge_in_file_t in_files[], int i, int count,
+ merge_out_file_t *out_file, int *err)
{
- int i;
- int selected_frame_type;
+ gchar *err_info;
+ long data_offset;
+ int loop = 0;
- selected_frame_type = wtap_file_encap(files[0].wth);
+ /* Start by clearing error flag */
+ *err = 0;
- 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 (merge_verbose == VERBOSE_ALL) {
- 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));
- }
+ while ( (wtap_read(in_files[i].wth, err, &err_info, &data_offset)) ) {
+ if(!write_frame(in_files[i].wth, out_file, err))
+ return FALSE; /* failure */
+ if (count > 0 && ++loop >= count)
break;
- }
- }
-
- if (merge_verbose == VERBOSE_ALL) {
- 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
- */
-gboolean
-merge_close_outfile(merge_out_file_t *out_file, int *err)
-{
- if (!wtap_dump_close(out_file->pdh, err)) {
- if (merge_verbose == VERBOSE_ERRORS)
- fprintf(stderr, "mergecap: Error closing output file: %s\n",
- wtap_strerror(*err));
- return FALSE;
+ if (*err != 0) {
+ /* Read failure, not write failure. */
+ in_files[i].ok = FALSE;
+ in_files[i].err = *err;
+ in_files[i].err_info = err_info;
}
return TRUE;
}
-
/*
- * Open the output file
- *
- * Return FALSE if file cannot be opened (so caller can clean up)
+ * routine to concatenate files
*/
gboolean
-merge_open_outfile(merge_out_file_t *out_file, int fd, int file_type,
- int frame_type, int snapshot_len, int *err)
-{
-
- if (!out_file) {
- if (merge_verbose == VERBOSE_ERRORS)
- fprintf(stderr, "mergecap: internal error (null out_file)\n");
- return FALSE;
- }
-
- out_file->pdh = wtap_dump_fdopen(fd, file_type, frame_type, snapshot_len,
- err);
- if (!out_file->pdh) {
- if (merge_verbose == VERBOSE_ERRORS) {
- fprintf(stderr, "mergecap: Can't open/create output file:\n");
- fprintf(stderr, " %s\n", wtap_strerror(*err));
- }
- return FALSE;
- }
-
- out_file->snaplen = snapshot_len;
- out_file->count = 1;
- return TRUE;
-}
-
-
-/*
- * Scan through input files and find maximum snapshot length
- */
-int
-merge_max_snapshot_length(int count, merge_in_file_t in_files[])
+merge_append_files(int count, merge_in_file_t in_files[],
+ merge_out_file_t *out_file, int *err)
{
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
- */
-void
-merge_close_in_files(int count, merge_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
- */
-int
-merge_open_in_files(int in_file_count, char *const *in_file_names,
- merge_in_file_t **in_files, int *err, gchar **err_info,
- int *err_fileno)
-{
- int i;
- int count = 0;
- int files_size = in_file_count * sizeof(merge_in_file_t);
- merge_in_file_t *files;
-
- files = g_malloc(files_size);
- *in_files = files;
-
- for (i = 0; i < in_file_count; i++) {
- files[count].filename = in_file_names[i];
- files[count].wth = wtap_open_offline(in_file_names[i], err, err_info, FALSE);
- files[count].err = 0;
- files[count].data_offset = 0;
- files[count].ok = TRUE;
- if (!files[count].wth) {
- if (merge_verbose >= VERBOSE_ERRORS) {
- fprintf(stderr, "mergecap: skipping %s: %s\n", in_file_names[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 {
- /*
- * We aren't reporting the errors, so return immediately so our
- * caller can report the error.
- */
- *err_fileno = count;
- return 0;
- }
- } else {
- if (merge_verbose == VERBOSE_ALL) {
- fprintf(stderr, "mergecap: %s is type %s.\n", in_file_names[i],
- wtap_file_type_string(wtap_file_type(files[count].wth)));
- }
- count++;
- }
+ if (!append_loop(in_files, i, 0, out_file, err))
+ return FALSE;
}
- if (merge_verbose == VERBOSE_ALL)
- fprintf(stderr, "mergecap: opened %d of %d input files\n", count,
- in_file_count);
- return count;
+ return TRUE;
}
diff --git a/merge.h b/merge.h
index 3102e94f20..e48942c071 100644
--- a/merge.h
+++ b/merge.h
@@ -50,27 +50,17 @@ typedef struct merge_out_file_s {
int count;
} merge_out_file_t;
-/** Verbosity levels. */
-typedef enum {
- VERBOSE_NONE,
- VERBOSE_ERRORS,
- VERBOSE_ALL
-} verbose_e;
-
-/** Current verbosity level, default is VERBOSE_NONE. */
-extern int merge_verbose;
-
/** Open a number of input files to merge.
*
* @param in_file_count number of entries in in_file_names and in_files
* @param in_file_names filenames of the input files
* @param in_files input file array to be filled (>= sizeof(merge_in_file_t) * in_file_count)
- * @param err wiretap error, if failed and VERBOSE_NONE
- * @param err_info wiretap error string, if failed and VERBOSE_NONE
- * @param err_fileno file on which open failed, if VERBOSE_NONE
- * @return number of opened input files
+ * @param err wiretap error, if failed
+ * @param err_info wiretap error string, if failed
+ * @param err_fileno file on which open failed, if failed
+ * @return TRUE if all files could be opened, FALSE otherwise
*/
-extern int
+extern gboolean
merge_open_in_files(int in_file_count, char *const *in_file_names,
merge_in_file_t **in_files, int *err, gchar **err_info,
int *err_fileno);
@@ -91,7 +81,7 @@ merge_close_in_files(int in_file_count, merge_in_file_t in_files[]);
* @param frame_type the frame type to write
* @param snapshot_len the snapshot length of the output file
* @param err wiretap error, if failed
- * @return TRUE, if the output file could be opened
+ * @return TRUE, if the output file could be opened, and FALSE otherwise
*/
extern gboolean
merge_open_outfile(merge_out_file_t *out_file, int fd, int file_type,
@@ -144,7 +134,8 @@ merge_files(int in_file_count, merge_in_file_t in_files[], merge_out_file_t *out
* @return TRUE on success or read failure, FALSE on write failure
*/
extern gboolean
-merge_append_files(int in_file_count, merge_in_file_t in_files[], merge_out_file_t *out_file, int *err);
+merge_append_files(int in_file_count, merge_in_file_t in_files[],
+ merge_out_file_t *out_file, int *err);
#ifdef __cplusplus
}
diff --git a/mergecap.c b/mergecap.c
index 05a3a159e2..74c41a7918 100644
--- a/mergecap.c
+++ b/mergecap.c
@@ -122,8 +122,6 @@ usage(void)
printf(" \t default is libpcap\n");
}
-
-
int
main(int argc, char *argv[])
{
@@ -131,19 +129,20 @@ main(int argc, char *argv[])
extern int optind;
int opt;
gboolean do_append = FALSE;
+ gboolean verbose = FALSE;
int in_file_count = 0;
int snaplen = 0;
int file_type = WTAP_FILE_PCAP; /* default to libpcap format */
int frame_type = -2;
int out_fd;
merge_in_file_t *in_files = NULL;
+ int i;
merge_out_file_t out_file;
- int err;
+ int err, close_err;
gchar *err_info;
int err_fileno;
char *out_filename = NULL;
-
- merge_verbose = VERBOSE_ERRORS;
+ gboolean ret;
/* Process the options first */
while ((opt = getopt(argc, argv, "hvas:T:F:w:")) != -1) {
@@ -176,7 +175,7 @@ main(int argc, char *argv[])
break;
case 'v':
- merge_verbose = VERBOSE_ALL;
+ verbose = TRUE;
break;
case 's':
@@ -217,13 +216,28 @@ main(int argc, char *argv[])
}
/* open the input files */
- in_file_count = merge_open_in_files(in_file_count, &argv[optind], &in_files,
- &err, &err_info, &err_fileno);
- if (in_file_count < 1) {
- fprintf(stderr, "mergecap: No valid input files\n");
+ if (!merge_open_in_files(in_file_count, &argv[optind], &in_files,
+ &err, &err_info, &err_fileno)) {
+ fprintf(stderr, "mergecap: Can't open %s: %s\n", argv[optind + err_fileno],
+ 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;
+ }
exit(1);
}
+ if (verbose) {
+ for (i = 0; i < in_file_count; i++)
+ fprintf(stderr, "mergecap: %s is type %s.\n", argv[optind + i],
+ wtap_file_type_string(wtap_file_type(in_files[i].wth)));
+ }
+
if (snaplen == 0) {
/*
* Snapshot length not specified - default to the maximum of the
@@ -238,6 +252,35 @@ main(int argc, char *argv[])
* Default to the appropriate frame type for the input files.
*/
frame_type = merge_select_frame_type(in_file_count, in_files);
+ if (verbose) {
+ if (frame_type == WTAP_ENCAP_PER_PACKET) {
+ /*
+ * Find out why we had to choose WTAP_ENCAP_PER_PACKET.
+ */
+ int first_frame_type, this_frame_type;
+
+ first_frame_type = wtap_file_encap(in_files[0].wth);
+ for (i = 1; i < in_file_count; i++) {
+ this_frame_type = wtap_file_encap(in_files[i].wth);
+ if (first_frame_type != this_frame_type) {
+ 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",
+ in_files[0].filename,
+ wtap_encap_string(first_frame_type),
+ wtap_encap_short_string(first_frame_type));
+ fprintf(stderr, " %s had type %s (%s)\n",
+ in_files[i].filename,
+ wtap_encap_string(this_frame_type),
+ wtap_encap_short_string(this_frame_type));
+ break;
+ }
+ }
+ }
+ fprintf(stderr, "mergecap: selected frame_type %s (%s)\n",
+ wtap_encap_string(frame_type),
+ wtap_encap_short_string(frame_type));
+ }
}
/* open the outfile */
@@ -258,19 +301,29 @@ main(int argc, char *argv[])
if (!merge_open_outfile(&out_file, out_fd, file_type, frame_type, snaplen,
&err)) {
merge_close_in_files(in_file_count, in_files);
+ free(in_files);
+ fprintf(stderr, "mergecap: Can't open or create %s: %s\n", out_filename,
+ wtap_strerror(err));
exit(1);
}
/* do the merge (or append) */
if (do_append)
- merge_append_files(in_file_count, in_files, &out_file, &err);
+ ret = merge_append_files(in_file_count, in_files, &out_file, &err);
else
- merge_files(in_file_count, in_files, &out_file, &err);
+ ret = merge_files(in_file_count, in_files, &out_file, &err);
merge_close_in_files(in_file_count, in_files);
- merge_close_outfile(&out_file, &err);
+ if (ret)
+ ret = merge_close_outfile(&out_file, &err);
+ else
+ merge_close_outfile(&out_file, &close_err);
+ if (!ret) {
+ fprintf(stderr, "mergecap: Error writing to outfile: %s\n",
+ wtap_strerror(err));
+ }
free(in_files);
- return 0;
+ return ret ? 0 : 2;
}