Take the error message generation out of the merge_files routines.
authorGuy Harris <guy@alum.mit.edu>
Thu, 20 Apr 2017 20:25:21 +0000 (13:25 -0700)
committerGuy Harris <guy@alum.mit.edu>
Thu, 20 Apr 2017 20:25:59 +0000 (20:25 +0000)
Have them just return the information needed for the caller to produce
an error message, and have the callers use the new cfile_ routines for
reporting errors.

This requires that the "write failure alert box" routine take the
*input* file name as an argument, so that, on a merge, if the problem is
that a record from a given input file can't be written out to the type
of output file we're generating, the input file name can be given, along
with the record number in that file.

Change-Id: If5a5e00539e7e652008a523dec92c0b359a48e71
Reviewed-on: https://code.wireshark.org/review/21257
Reviewed-by: Guy Harris <guy@alum.mit.edu>
CMakeLists.txt
Makefile.am
file.c
mergecap.c
ui/alert_box.c
ui/alert_box.h
wiretap/merge.c
wiretap/merge.h

index b0ef9dea855b9244dccac466ee652a143c96ef68..dc2b9550e8863261ec8efe2966dffc9d92736d9e 100644 (file)
@@ -2407,6 +2407,7 @@ endif()
 
 if(BUILD_mergecap)
        set(mergecap_LIBS
+               ui
                wiretap
                ${ZLIB_LIBRARIES}
                ${CMAKE_DL_LIBS}
index aa0c626c724dcd0bd67c90c24488679cec5e35b2..83f2e5ce6b1b32080119bff0c6e705ccf2b64a56 100644 (file)
@@ -630,6 +630,7 @@ mergecap_CPPFLAGS = $(AM_CPPFLAGS) $(GLIB_CFLAGS)
 
 # Libraries with which to link mergecap.
 mergecap_LDADD = \
+       ui/libui.a                      \
        wiretap/libwiretap.la           \
        wsutil/libwsutil.la             \
        @GLIB_LIBS@
diff --git a/file.c b/file.c
index fe28c9ae2dc27880cc17ad3ae85f77931b81188d..a05cd24ac7c25d4ca890e07fbba856ca1e3bba79 100644 (file)
--- a/file.c
+++ b/file.c
@@ -1349,6 +1349,7 @@ cf_merge_files_to_tempfile(gpointer pd_window, char **out_filenamep,
   int                        err      = 0;
   gchar                     *err_info = NULL;
   guint                      err_fileno;
+  guint32                    err_framenum;
   merge_result               status;
   merge_progress_callback_t  cb;
   callback_data_t           *cb_data = g_new0(callback_data_t, 1);
@@ -1366,7 +1367,7 @@ cf_merge_files_to_tempfile(gpointer pd_window, char **out_filenamep,
                                    in_file_count, do_append,
                                    IDB_MERGE_MODE_ALL_SAME, 0 /* snaplen */,
                                    "Wireshark", &cb, &err, &err_info,
-                                   &err_fileno);
+                                   &err_fileno, &err_framenum);
 
   g_free(cb.data);
 
@@ -1386,12 +1387,27 @@ cf_merge_files_to_tempfile(gpointer pd_window, char **out_filenamep,
       cfile_dump_open_failure_alert_box(*out_filenamep, err, file_type);
       break;
 
-    case MERGE_ERR_CANT_READ_INFILE:      /* fall through */
+    case MERGE_ERR_CANT_READ_INFILE:
+      cfile_read_failure_alert_box(in_filenames[err_fileno], err, err_info);
+      break;
+
     case MERGE_ERR_BAD_PHDR_INTERFACE_ID:
+      simple_error_message_box("Record %u of \"%s\" has an interface ID that does not match any IDB in its file.",
+                               err_framenum, in_filenames[err_fileno]);
+      break;
+
     case MERGE_ERR_CANT_WRITE_OUTFILE:
+       cfile_write_failure_alert_box(in_filenames[err_fileno],
+                                     *out_filenamep, err, err_info,
+                                     err_framenum, file_type);
+       break;
+
     case MERGE_ERR_CANT_CLOSE_OUTFILE:
+        cfile_close_failure_alert_box(*out_filenamep, err);
+        break;
+
     default:
-      simple_error_message_box("%s", err_info ? err_info : "unknown error");
+      simple_error_message_box("Unknown merge_files error %d", status);
       break;
   }
 
@@ -4050,7 +4066,7 @@ save_record(capture_file *cf, frame_data *fdata,
 #endif
   /* and save the packet */
   if (!wtap_dump(args->pdh, &hdr, pd, &err, &err_info)) {
-    cfile_write_failure_alert_box(args->fname, err, err_info, fdata->num,
+    cfile_write_failure_alert_box(NULL, args->fname, err, err_info, fdata->num,
                                   args->file_type);
     return FALSE;
   }
index daddbda1fba56bf8a8d099bebad93dabd9d8e32b..74f733fa1bde589ab82819535f1d78f6fc8b0e62 100644 (file)
@@ -63,6 +63,8 @@
 #include <wsutil/unicode-utils.h>
 #endif /* _WIN32 */
 
+#include "ui/failure_message.h"
+
 /*
  * Show the usage
  */
@@ -262,6 +264,7 @@ main(int argc, char *argv[])
   int                 err                = 0;
   gchar              *err_info           = NULL;
   int                 err_fileno;
+  guint32             err_framenum;
   char               *out_filename       = NULL;
   merge_result        status             = MERGE_OK;
   idb_merge_mode      mode               = IDB_MERGE_MODE_MAX;
@@ -441,13 +444,13 @@ main(int argc, char *argv[])
                                    (const char *const *) &argv[optind],
                                    in_file_count, do_append, mode, snaplen,
                                    "mergecap", verbose ? &cb : NULL,
-                                   &err, &err_info, &err_fileno);
+                                   &err, &err_info, &err_fileno, &err_framenum);
   } else {
     /* merge the files to the outfile */
     status = merge_files(out_filename, file_type,
                          (const char *const *) &argv[optind], in_file_count,
                          do_append, mode, snaplen, "mergecap", verbose ? &cb : NULL,
-                         &err, &err_info, &err_fileno);
+                         &err, &err_info, &err_fileno, &err_framenum);
   }
 
   switch (status) {
@@ -460,26 +463,36 @@ main(int argc, char *argv[])
       break;
 
     case MERGE_ERR_CANT_OPEN_INFILE:
-      fprintf(stderr, "mergecap: Can't open %s: %s (%s)\n", argv[optind + err_fileno],
-              wtap_strerror(err), err_info ? err_info : "no more information");
+      cfile_open_failure_message("mergecap", argv[optind + err_fileno],
+                                 err, err_info);
       break;
 
     case MERGE_ERR_CANT_OPEN_OUTFILE:
-      if (use_stdout) {
-        fprintf(stderr, "mergecap: Can't set up the standard output: %s\n",
-                    wtap_strerror(err));
-      } else {
-        fprintf(stderr, "mergecap: Can't open or create %s: %s\n", out_filename,
-                    wtap_strerror(err));
-      }
+      cfile_dump_open_failure_message("mergecap", out_filename, err, file_type);
+      break;
+
+    case MERGE_ERR_CANT_READ_INFILE:
+      cfile_read_failure_message("mergecap", argv[optind + err_fileno],
+                                 err, err_info);
       break;
 
-    case MERGE_ERR_CANT_READ_INFILE:      /* fall through */
     case MERGE_ERR_BAD_PHDR_INTERFACE_ID:
+      cmdarg_err("Record %u of \"%s\" has an interface ID that does not match any IDB in its file.",
+                 err_framenum, argv[optind + err_fileno]);
+      break;
+
     case MERGE_ERR_CANT_WRITE_OUTFILE:
+       cfile_write_failure_message("mergecap", argv[optind + err_fileno],
+                                   out_filename, err, err_info, err_framenum,
+                                   file_type);
+       break;
+
     case MERGE_ERR_CANT_CLOSE_OUTFILE:
+        cfile_close_failure_message(out_filename, err);
+        break;
+
     default:
-      fprintf(stderr, "mergecap: %s\n", err_info ? err_info : "unknown error");
+      cmdarg_err("Unknown merge_files error %d", status);
       break;
   }
 
index 8f870269e9bfd635725f8e883d12625ca97ecf03..d387dacb8d232dc84d9c38152ee1ab14ca79925e 100644 (file)
@@ -307,21 +307,30 @@ cfile_read_failure_alert_box(const char *filename, int err, gchar *err_info)
 
 /*
  * Alert box for a failed attempt to write to a capture file.
- * "err" is assumed to be a UNIX-style errno or a WTAP_ERR_ value;
- * "err_info" is assumed to be a string giving further information for
- * some WTAP_ERR_ values; "framenum" is the frame number of the record
- * on which the error occurred; "file_type_subtype" is a
- * WTAP_FILE_TYPE_SUBTYPE_ value for the type and subtype of file being
- * written.
+ * "in_filename" is the name of the file from which the record being
+ * written came; "out_filename" is the name of the file to which we're
+ * writing; "err" is assumed "err" is assumed to be a UNIX-style errno
+ * or a WTAP_ERR_ value; "err_info" is assumed to be a string giving
+ * further information for some WTAP_ERR_ values; "framenum" is the frame
+ * number of the record on which the error occurred; "file_type_subtype"
+ * is a WTAP_FILE_TYPE_SUBTYPE_ value for the type and subtype of file
+ * being written.
  */
 void
-cfile_write_failure_alert_box(const char *filename, int err, gchar *err_info,
-                              guint32 framenum, int file_type_subtype)
+cfile_write_failure_alert_box(const char *in_filename, const char *out_filename,
+                              int err, gchar *err_info, guint32 framenum,
+                              int file_type_subtype)
 {
-    char *display_basename;
+    char *in_file_string;
+    char *out_display_basename;
 
     if (err < 0) {
         /* Wiretap error. */
+        if (in_filename == NULL)
+            in_file_string = g_strdup("");
+        else
+            in_file_string = g_strdup_printf(" of file \"%s\"", in_filename);
+
         switch (err) {
 
         case WTAP_ERR_UNWRITABLE_ENCAP:
@@ -331,8 +340,9 @@ cfile_write_failure_alert_box(const char *filename, int err, gchar *err_info,
              * the frame number and file type/subtype.
              */
             simple_error_message_box(
-                        "Frame %u has a network type that can't be saved in a \"%s\" file.",
-                        framenum, wtap_file_type_subtype_string(file_type_subtype));
+                        "Frame %u%s has a network type that can't be saved in a \"%s\" file.",
+                        framenum, in_file_string,
+                        wtap_file_type_subtype_string(file_type_subtype));
             break;
 
         case WTAP_ERR_PACKET_TOO_LARGE:
@@ -342,8 +352,9 @@ cfile_write_failure_alert_box(const char *filename, int err, gchar *err_info,
              * the frame number and file type/subtype.
              */
             simple_error_message_box(
-                        "Frame %u is larger than Wireshark supports in a \"%s\" file.",
-                        framenum, wtap_file_type_subtype_string(file_type_subtype));
+                        "Frame %u%s is larger than Wireshark supports in a \"%s\" file.",
+                        framenum, in_file_string,
+                        wtap_file_type_subtype_string(file_type_subtype));
             break;
 
         case WTAP_ERR_UNWRITABLE_REC_TYPE:
@@ -353,43 +364,46 @@ cfile_write_failure_alert_box(const char *filename, int err, gchar *err_info,
              * the record number and file type/subtype.
              */
             simple_error_message_box(
-                        "Record %u has a record type that can't be saved in a \"%s\" file.",
-                        framenum, wtap_file_type_subtype_string(file_type_subtype));
+                        "Record %u%s has a record type that can't be saved in a \"%s\" file.",
+                        framenum, in_file_string,
+                        wtap_file_type_subtype_string(file_type_subtype));
             break;
 
         case WTAP_ERR_UNWRITABLE_REC_DATA:
             /*
-             * This is a problem with the particular frame we're writing and
+             * This is a problem with the particular record we're writing and
              * the file type and subtype we're writing; note that, and report
-             * the frame number and file type/subtype.
+             * the record number and file type/subtype.
              */
             simple_error_message_box(
-                        "Record %u has data that can't be saved in a \"%s\" file.\n"
+                        "Record %u%s has data that can't be saved in a \"%s\" file.\n"
                         "(%s)",
-                        framenum, wtap_file_type_subtype_string(file_type_subtype),
+                        framenum, in_file_string,
+                        wtap_file_type_subtype_string(file_type_subtype),
                         err_info != NULL ? err_info : "no information supplied");
             g_free(err_info);
             break;
 
         case WTAP_ERR_SHORT_WRITE:
-            display_basename = g_filename_display_basename(filename);
+            out_display_basename = g_filename_display_basename(out_filename);
             simple_error_message_box(
                         "A full write couldn't be done to the file \"%s\".",
-                        display_basename);
-            g_free(display_basename);
+                        out_display_basename);
+            g_free(out_display_basename);
             break;
 
         default:
-            display_basename = g_filename_display_basename(filename);
+            out_display_basename = g_filename_display_basename(out_filename);
             simple_error_message_box(
                         "An error occurred while writing to the file \"%s\": %s.",
-                        display_basename, wtap_strerror(err));
-            g_free(display_basename);
+                        out_display_basename, wtap_strerror(err));
+            g_free(out_display_basename);
             break;
-       }
+        }
+        g_free(in_file_string);
     } else {
         /* OS error. */
-        write_failure_alert_box(filename, err);
+        write_failure_alert_box(out_filename, err);
     }
 }
 
index 74d326147409fd0af78121a68cec14d4fa805d65..5d392e7107cb8b005e996e703d313b8798f1ba44 100644 (file)
@@ -69,15 +69,19 @@ extern void cfile_read_failure_alert_box(const char *filename, int err,
 
 /*
  * Alert box for a failed attempt to write to a capture file.
- * "err" is assumed to be a UNIX-style errno or a WTAP_ERR_ value;
- * "err_info" is assumed to be a string giving further information for
- * some WTAP_ERR_ values; "framenum" is the frame number of the record
- * on which the error occurred; "file_type_subtype" is a
- * WTAP_FILE_TYPE_SUBTYPE_ value for the type and subtype of file being
- * written.
+ * "in_filename" is the name of the file from which the record being
+ * written came; "out_filename" is the name of the file to which we're
+ * writing; "err" is assumed "err" is assumed to be a UNIX-style errno
+ * or a WTAP_ERR_ value; "err_info" is assumed to be a string giving
+ * further information for some WTAP_ERR_ values; "framenum" is the frame
+ * number of the record on which the error occurred; "file_type_subtype"
+ * is a WTAP_FILE_TYPE_SUBTYPE_ value for the type and subtype of file
+ * being written.
  */
-extern void cfile_write_failure_alert_box(const char *filename, int err,
-                                          gchar *err_info, guint32 framenum,
+extern void cfile_write_failure_alert_box(const char *in_filename,
+                                          const char *out_filename,
+                                          int err, gchar *err_info,
+                                          guint32 framenum,
                                           int file_type_subtype);
 
 /*
index 8ad6530c60a1c6a16f016176d0554d647542b5fc..8605b7fbeb204ab7d08d15ae6e1b5e91d55cfbb2 100644 (file)
@@ -811,166 +811,13 @@ map_phdr_interface_id(struct wtap_pkthdr *phdr, const merge_in_file_t *in_file)
     return TRUE;
 }
 
-static gchar*
-get_read_error_string(const merge_in_file_t *in_files, const guint in_file_count,
-                      const int *err, gchar **err_info)
-{
-    GString *err_message = g_string_new("");
-    gchar   *display_basename = NULL;
-    guint    i;
-
-    g_assert(in_files != NULL);
-    g_assert(err != NULL);
-    g_assert(err_info != NULL);
-
-    if (*err_info == NULL) {
-        *err_info = g_strdup("no information supplied");
-    }
-
-    /*
-     * Find the file on which we got the error, and report the error.
-     */
-    for (i = 0; i < in_file_count; i++) {
-        if (in_files[i].state == GOT_ERROR) {
-            display_basename = g_filename_display_basename(in_files[i].filename);
-
-            switch (*err) {
-
-                case WTAP_ERR_SHORT_READ:
-                    g_string_printf(err_message,
-                         "The capture file %s appears to have been cut short"
-                          " in the middle of a packet.", display_basename);
-                    break;
-
-                case WTAP_ERR_BAD_FILE:
-                    g_string_printf(err_message,
-                         "The capture file %s appears to be damaged or corrupt.\n(%s)",
-                         display_basename, *err_info);
-                    break;
-
-                case WTAP_ERR_DECOMPRESS:
-                    g_string_printf(err_message,
-                         "The compressed capture file %s appears to be damaged or corrupt.\n"
-                         "(%s)", display_basename, *err_info);
-                    break;
-
-                default:
-                    g_string_printf(err_message,
-                         "An error occurred while reading the"
-                         " capture file %s: %s.",
-                         display_basename,  wtap_strerror(*err));
-                    break;
-            }
-
-            g_free(display_basename);
-            break;
-        }
-    }
-
-    g_free(*err_info);
-    *err_info = g_string_free(err_message, FALSE);
-
-    return *err_info;
-}
-
-static gchar*
-get_write_error_string(const merge_in_file_t *in_file, const int file_type,
-                       const gchar* out_filename, const int *err, gchar **err_info)
-{
-    GString *err_message = g_string_new("");
-    gchar *display_basename = NULL;
-    int write_err;
-
-    /* in_file may be NULL */
-    g_assert(err != NULL);
-    g_assert(err_info != NULL);
-
-    if (*err_info == NULL) {
-        *err_info = g_strdup("no information supplied");
-    }
-
-    write_err = *err;
-
-    display_basename = g_filename_display_basename(in_file ? in_file->filename : "UNKNOWN");
-
-    if (write_err < 0) {
-
-        switch (write_err) {
-
-            case WTAP_ERR_UNWRITABLE_ENCAP:
-                /*
-                 * This is a problem with the particular frame we're writing and
-                 * the file type and subtype we're wwriting; note that, and
-                 * report the frame number and file type/subtype.
-                 */
-                g_string_printf(err_message,
-                    "Frame %u of \"%s\" has a network type that can't be saved in a \"%s\" file.\n",
-                    in_file ? in_file->packet_num : 0, display_basename,
-                    wtap_file_type_subtype_string(file_type));
-                break;
-
-            case WTAP_ERR_PACKET_TOO_LARGE:
-                /*
-                 * This is a problem with the particular frame we're writing and
-                 * the file type and subtype we're writing; note that, and report
-                 * the frame number and file type/subtype.
-                 */
-                g_string_printf(err_message,
-                    "Frame %u of \"%s\" is too large for a \"%s\" file.",
-                    in_file ? in_file->packet_num : 0, display_basename,
-                    wtap_file_type_subtype_string(file_type));
-                break;
-
-            case WTAP_ERR_UNWRITABLE_REC_TYPE:
-                /*
-                 * This is a problem with the particular record we're writing and
-                 * the file type and subtype we're writing; note that, and report
-                 * the record number and file type/subtype.
-                 */
-                g_string_printf(err_message,
-                    "Record %u of \"%s\" has a record type that can't be saved in a \"%s\" file.",
-                    in_file ? in_file->packet_num : 0, display_basename,
-                    wtap_file_type_subtype_string(file_type));
-                break;
-
-            case WTAP_ERR_UNWRITABLE_REC_DATA:
-                /*
-                 * This is a problem with the particular record we're writing and
-                 * the file type and subtype we're writing; note that, and report
-                 * the frame number and file type/subtype.
-                 */
-                g_string_printf(err_message,
-                    "Record %u of \"%s\" has data that can't be saved in a \"%s\" file.\n(%s)",
-                    in_file ? in_file->packet_num : 0, display_basename,
-                    wtap_file_type_subtype_string(file_type), *err_info);
-                break;
-
-            default:
-                g_string_printf(err_message,
-                    "An error occurred while writing to the file \"%s\": %s.",
-                    out_filename, wtap_strerror(write_err));
-                break;
-        }
-    }
-    else {
-        /* OS error. */
-        g_string_printf(err_message, file_write_error_message(write_err), out_filename);
-    }
-
-    g_free(display_basename);
-    g_free(*err_info);
-    *err_info = g_string_free(err_message, FALSE);
-
-    return *err_info;
-}
-
 static merge_result
-merge_process_packets(const gchar* out_filename, wtap_dumper *pdh,
-                      const int file_type,
+merge_process_packets(wtap_dumper *pdh, const int file_type,
                       merge_in_file_t *in_files, const guint in_file_count,
                       const gboolean do_append, guint snaplen,
                       merge_progress_callback_t* cb,
-                      int *err, gchar **err_info)
+                      int *err, gchar **err_info, guint *err_fileno,
+                      guint32 *err_framenum)
 {
     merge_result        status = MERGE_OK;
     merge_in_file_t    *in_file;
@@ -1066,37 +913,12 @@ merge_process_packets(const gchar* out_filename, wtap_dumper *pdh,
         (void)wtap_dump_close(pdh, &close_err);
     }
 
-    if (status != MERGE_OK) {
-        GString *err_message = NULL;
-        gchar   *display_basename = NULL;
-
-        switch(status) {
-
-            case MERGE_ERR_CANT_READ_INFILE:
-                *err_info = get_read_error_string(in_files, in_file_count, err, err_info);
-                break;
-
-            case MERGE_ERR_CANT_WRITE_OUTFILE: /* fall through */
-            case MERGE_ERR_CANT_CLOSE_OUTFILE:
-                *err_info = get_write_error_string(in_file, file_type, out_filename, err, err_info);
-                break;
-
-            case MERGE_ERR_BAD_PHDR_INTERFACE_ID:
-                display_basename = g_filename_display_basename(in_file ? in_file->filename : "UNKNOWN");
-                if (*err_info != NULL)
-                    g_free(*err_info);
-                err_message = g_string_new("");
-                g_string_printf(err_message,
-                    "Record %u of \"%s\" has an interface ID which does not match any IDB in its file.",
-                    in_file ? in_file->packet_num : 0, display_basename);
-                g_free(display_basename);
-                *err_info = g_string_free(err_message, FALSE);
-                break;
-
-            case MERGE_USER_ABORTED: /* not really an error */
-            default:
-                break;
-        }
+    if (status == MERGE_OK || in_file == NULL) {
+        *err_fileno = 0;
+        *err_framenum = 0;
+    } else {
+        *err_fileno = (guint)(in_file - in_files);
+        *err_framenum = in_file ? in_file->packet_num : 0;
     }
 
     return status;
@@ -1105,16 +927,15 @@ merge_process_packets(const gchar* out_filename, wtap_dumper *pdh,
 /*
  * Merges the files to an output file whose name is supplied as an argument,
  * based on given input, and invokes callback during execution. Returns
- * MERGE_OK on success, or a MERGE_ERR_XXX on failure; note that the passed-in
- * 'err' variable will be more specific to what failed, and err_info will
- * have pretty output.
+ * MERGE_OK on success, or a MERGE_ERR_XXX on failure.
  */
 merge_result
 merge_files(const gchar* out_filename, const int file_type,
             const char *const *in_filenames, const guint in_file_count,
             const gboolean do_append, const idb_merge_mode mode,
             guint snaplen, const gchar *app_name, merge_progress_callback_t* cb,
-            int *err, gchar **err_info, guint *err_fileno)
+            int *err, gchar **err_info, guint *err_fileno,
+            guint32 *err_framenum)
 {
     merge_in_file_t    *in_files = NULL;
     int                 frame_type = WTAP_ENCAP_PER_PACKET;
@@ -1129,6 +950,7 @@ merge_files(const gchar* out_filename, const int file_type,
     g_assert(err != NULL);
     g_assert(err_info != NULL);
     g_assert(err_fileno != NULL);
+    g_assert(err_framenum != NULL);
 
     /* if a callback was given, it has to have a callback function ptr */
     g_assert((cb != NULL) ? (cb->callback_func != NULL) : TRUE);
@@ -1139,6 +961,7 @@ merge_files(const gchar* out_filename, const int file_type,
     if (!merge_open_in_files(in_file_count, in_filenames, &in_files, cb,
                              err, err_info, err_fileno)) {
         merge_debug("merge_files: merge_open_in_files() failed with err=%d", *err);
+        *err_framenum = 0;
         return MERGE_ERR_CANT_OPEN_INFILE;
     }
 
@@ -1182,15 +1005,16 @@ merge_files(const gchar* out_filename, const int file_type,
         g_free(in_files);
         wtap_block_array_free(shb_hdrs);
         wtap_free_idb_info(idb_inf);
+        *err_framenum = 0;
         return MERGE_ERR_CANT_OPEN_OUTFILE;
     }
 
     if (cb)
         cb->callback_func(MERGE_EVENT_READY_TO_MERGE, 0, in_files, in_file_count, cb->data);
 
-    status = merge_process_packets(out_filename, pdh, file_type, in_files,
-                                   in_file_count, do_append, snaplen, cb,
-                                   err, err_info);
+    status = merge_process_packets(pdh, file_type, in_files, in_file_count,
+                                   do_append, snaplen, cb, err, err_info,
+                                   err_fileno, err_framenum);
 
     g_free(in_files);
     wtap_block_array_free(shb_hdrs);
@@ -1202,8 +1026,7 @@ merge_files(const gchar* out_filename, const int file_type,
 /*
  * Merges the files to a temporary file based on given input, and invokes
  * callback during execution. Returns MERGE_OK on success, or a MERGE_ERR_XXX
- * on failure; note that the passed-in 'err' variable will be more specific
- * to what failed, and err_info will have pretty output.
+ * on failure.
  */
 merge_result
 merge_files_to_tempfile(gchar **out_filenamep, const char *pfx,
@@ -1211,7 +1034,8 @@ merge_files_to_tempfile(gchar **out_filenamep, const char *pfx,
                         const guint in_file_count, const gboolean do_append,
                         const idb_merge_mode mode, guint snaplen,
                         const gchar *app_name, merge_progress_callback_t* cb,
-                        int *err, gchar **err_info, guint *err_fileno)
+                        int *err, gchar **err_info, guint *err_fileno,
+                        guint32 *err_framenum)
 {
     merge_in_file_t    *in_files = NULL;
     int                 frame_type = WTAP_ENCAP_PER_PACKET;
@@ -1226,6 +1050,7 @@ merge_files_to_tempfile(gchar **out_filenamep, const char *pfx,
     g_assert(err != NULL);
     g_assert(err_info != NULL);
     g_assert(err_fileno != NULL);
+    g_assert(err_framenum != NULL);
 
     /* if a callback was given, it has to have a callback function ptr */
     g_assert((cb != NULL) ? (cb->callback_func != NULL) : TRUE);
@@ -1239,6 +1064,7 @@ merge_files_to_tempfile(gchar **out_filenamep, const char *pfx,
     if (!merge_open_in_files(in_file_count, in_filenames, &in_files, cb,
                              err, err_info, err_fileno)) {
         merge_debug("merge_files: merge_open_in_files() failed with err=%d", *err);
+        *err_framenum = 0;
         return MERGE_ERR_CANT_OPEN_INFILE;
     }
 
@@ -1283,15 +1109,16 @@ merge_files_to_tempfile(gchar **out_filenamep, const char *pfx,
         g_free(in_files);
         wtap_block_array_free(shb_hdrs);
         wtap_free_idb_info(idb_inf);
+        *err_framenum = 0;
         return MERGE_ERR_CANT_OPEN_OUTFILE;
     }
 
     if (cb)
         cb->callback_func(MERGE_EVENT_READY_TO_MERGE, 0, in_files, in_file_count, cb->data);
 
-    status = merge_process_packets(*out_filenamep, pdh, file_type, in_files,
-                                   in_file_count, do_append, snaplen, cb,
-                                   err, err_info);
+    status = merge_process_packets(pdh, file_type, in_files, in_file_count,
+                                   do_append, snaplen, cb, err, err_info,
+                                   err_fileno, err_framenum);
 
     g_free(in_files);
     wtap_block_array_free(shb_hdrs);
@@ -1303,15 +1130,15 @@ merge_files_to_tempfile(gchar **out_filenamep, const char *pfx,
 /*
  * Merges the files to the standard output based on given input, and invokes
  * callback during execution. Returns MERGE_OK on success, or a MERGE_ERR_XXX
- * on failure; note that the passed-in 'err' variable will be more specific
- * to what failed, and err_info will have pretty output.
+ * on failure.
  */
 merge_result
 merge_files_to_stdout(const int file_type, const char *const *in_filenames,
                       const guint in_file_count, const gboolean do_append,
                       const idb_merge_mode mode, guint snaplen,
                       const gchar *app_name, merge_progress_callback_t* cb,
-                      int *err, gchar **err_info, guint *err_fileno)
+                      int *err, gchar **err_info, guint *err_fileno,
+                      guint32 *err_framenum)
 {
     merge_in_file_t    *in_files = NULL;
     int                 frame_type = WTAP_ENCAP_PER_PACKET;
@@ -1325,6 +1152,7 @@ merge_files_to_stdout(const int file_type, const char *const *in_filenames,
     g_assert(err != NULL);
     g_assert(err_info != NULL);
     g_assert(err_fileno != NULL);
+    g_assert(err_framenum != NULL);
 
     /* if a callback was given, it has to have a callback function ptr */
     g_assert((cb != NULL) ? (cb->callback_func != NULL) : TRUE);
@@ -1335,6 +1163,7 @@ merge_files_to_stdout(const int file_type, const char *const *in_filenames,
     if (!merge_open_in_files(in_file_count, in_filenames, &in_files, cb,
                              err, err_info, err_fileno)) {
         merge_debug("merge_files: merge_open_in_files() failed with err=%d", *err);
+        *err_framenum = 0;
         return MERGE_ERR_CANT_OPEN_INFILE;
     }
 
@@ -1378,15 +1207,16 @@ merge_files_to_stdout(const int file_type, const char *const *in_filenames,
         g_free(in_files);
         wtap_block_array_free(shb_hdrs);
         wtap_free_idb_info(idb_inf);
+        *err_framenum = 0;
         return MERGE_ERR_CANT_OPEN_OUTFILE;
     }
 
     if (cb)
         cb->callback_func(MERGE_EVENT_READY_TO_MERGE, 0, in_files, in_file_count, cb->data);
 
-    status = merge_process_packets("standard output", pdh, file_type, in_files,
-                                   in_file_count, do_append, snaplen, cb,
-                                   err, err_info);
+    status = merge_process_packets(pdh, file_type, in_files, in_file_count,
+                                   do_append, snaplen, cb, err, err_info,
+                                   err_fileno, err_framenum);
 
     g_free(in_files);
     wtap_block_array_free(shb_hdrs);
index 21d0861cd8595b0ea9c4b99b07566121876c87b4..534fb751e8d41aeceb5c43953da4ec61d7113110 100644 (file)
@@ -135,8 +135,13 @@ typedef struct {
  * @param app_name The application name performing the merge, used in SHB info
  * @param cb The callback information to use during execution
  * @param[out] err Set to the internal WTAP_ERR_XXX error code if it failed
- * @param[out] err_info Set to a descriptive error string, which must be g_free'd
- * @param[out] err_fileno Set to the input file number which failed, if it failed
+ *   with MERGE_ERR_CANT_OPEN_INFILE, MERGE_ERR_CANT_OPEN_OUTFILE,
+ *   MERGE_ERR_CANT_READ_INFILE, MERGE_ERR_CANT_WRITE_OUTFILE, or
+ *   MERGE_ERR_CANT_CLOSE_OUTFILE
+ * @param[out] err_info Additional information for some WTAP_ERR_XXX codes
+ * @param[out] err_fileno Set to the input file number which failed, if it
+ *   failed
+ * @param[out] err_framenum Set to the input frame number if it failed
  * @return the frame type
  */
 WS_DLL_PUBLIC merge_result
@@ -144,7 +149,8 @@ merge_files(const gchar* out_filename, const int file_type,
             const char *const *in_filenames, const guint in_file_count,
             const gboolean do_append, const idb_merge_mode mode,
             guint snaplen, const gchar *app_name, merge_progress_callback_t* cb,
-            int *err, gchar **err_info, guint *err_fileno);
+            int *err, gchar **err_info, guint *err_fileno,
+            guint32 *err_framenum);
 
 /** Merge the given input files to a temporary file
  *
@@ -160,8 +166,13 @@ merge_files(const gchar* out_filename, const int file_type,
  * @param app_name The application name performing the merge, used in SHB info
  * @param cb The callback information to use during execution
  * @param[out] err Set to the internal WTAP_ERR_XXX error code if it failed
- * @param[out] err_info Set to a descriptive error string, which must be g_free'd
- * @param[out] err_fileno Set to the input file number which failed, if it failed
+ *   with MERGE_ERR_CANT_OPEN_INFILE, MERGE_ERR_CANT_OPEN_OUTFILE,
+ *   MERGE_ERR_CANT_READ_INFILE, MERGE_ERR_CANT_WRITE_OUTFILE, or
+ *   MERGE_ERR_CANT_CLOSE_OUTFILE
+ * @param[out] err_info Additional information for some WTAP_ERR_XXX codes
+ * @param[out] err_fileno Set to the input file number which failed, if it
+ *   failed
+ * @param[out] err_framenum Set to the input frame number if it failed
  * @return the frame type
  */
 WS_DLL_PUBLIC merge_result
@@ -170,7 +181,8 @@ merge_files_to_tempfile(gchar **out_filenamep, const char *pfx,
                         const guint in_file_count, const gboolean do_append,
                         const idb_merge_mode mode, guint snaplen,
                         const gchar *app_name, merge_progress_callback_t* cb,
-                        int *err, gchar **err_info, guint *err_fileno);
+                        int *err, gchar **err_info, guint *err_fileno,
+                        guint32 *err_framenum);
 
 /** Merge the given input files to the standard output
  *
@@ -183,8 +195,13 @@ merge_files_to_tempfile(gchar **out_filenamep, const char *pfx,
  * @param app_name The application name performing the merge, used in SHB info
  * @param cb The callback information to use during execution
  * @param[out] err Set to the internal WTAP_ERR_XXX error code if it failed
- * @param[out] err_info Set to a descriptive error string, which must be g_free'd
- * @param[out] err_fileno Set to the input file number which failed, if it failed
+ *   with MERGE_ERR_CANT_OPEN_INFILE, MERGE_ERR_CANT_OPEN_OUTFILE,
+ *   MERGE_ERR_CANT_READ_INFILE, MERGE_ERR_CANT_WRITE_OUTFILE, or
+ *   MERGE_ERR_CANT_CLOSE_OUTFILE
+ * @param[out] err_info Additional information for some WTAP_ERR_XXX codes
+ * @param[out] err_fileno Set to the input file number which failed, if it
+ *   failed
+ * @param[out] err_framenum Set to the input frame number if it failed
  * @return the frame type
  */
 WS_DLL_PUBLIC merge_result
@@ -192,7 +209,8 @@ merge_files_to_stdout(const int file_type, const char *const *in_filenames,
                       const guint in_file_count, const gboolean do_append,
                       const idb_merge_mode mode, guint snaplen,
                       const gchar *app_name, merge_progress_callback_t* cb,
-                      int *err, gchar **err_info, guint *err_fileno);
+                      int *err, gchar **err_info, guint *err_fileno,
+                      guint32 *err_framenum);
 
 #ifdef __cplusplus
 }