Fix some copy+pasted tooltip text.
[metze/wireshark/wip.git] / file.c
diff --git a/file.c b/file.c
index 4a936af5ecd2d6fe472999684f1f7844a33c776a..dfe73e9c431bfb057e5484abbf7f0d8f0f4ff945 100644 (file)
--- a/file.c
+++ b/file.c
@@ -1,8 +1,6 @@
 /* file.c
  * File I/O routines
  *
- * $Id$
- *
  * Wireshark - Network traffic analyzer
  * By Gerald Combs <gerald@wireshark.org>
  * Copyright 1998 Gerald Combs
@@ -22,7 +20,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#include "config.h"
+#include <config.h>
 
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
@@ -35,7 +33,6 @@
 #include <string.h>
 #include <ctype.h>
 #include <errno.h>
-#include <signal.h>
 
 #ifdef HAVE_FCNTL_H
 #include <fcntl.h>
 
 #include <wsutil/tempfile.h>
 #include <wsutil/file_util.h>
+#include <wsutil/filesystem.h>
+#include <wsutil/ws_version_info.h>
 
 #include <wiretap/merge.h>
 
+#include <epan/exceptions.h>
 #include <epan/epan-int.h>
 #include <epan/epan.h>
 #include <epan/column.h>
 #include <epan/packet.h>
 #include <epan/column-utils.h>
 #include <epan/expert.h>
-#include <epan/filesystem.h>
 #include <epan/prefs.h>
 #include <epan/dfilter/dfilter.h>
 #include <epan/epan_dissect.h>
 #include <epan/tap.h>
-#include <epan/dissectors/packet-data.h>
 #include <epan/dissectors/packet-ber.h>
 #include <epan/timestamp.h>
 #include <epan/dfilter/dfilter-macro.h>
@@ -77,8 +75,6 @@
 #include "ui/progress_dlg.h"
 #include "ui/ui_util.h"
 
-#include "version_info.h"
-
 /* Needed for addrinfo */
 #ifdef HAVE_SYS_TYPES_H
 # include <sys/types.h>
 #endif
 
 #ifdef HAVE_LIBPCAP
-gboolean auto_scroll_live;
+gboolean auto_scroll_live; /* GTK+ only? */
 #endif
 
-static void cf_reset_state(capture_file *cf);
-
 static int read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
     column_info *cinfo, gint64 offset);
 
@@ -199,14 +193,14 @@ cf_callback_add(cf_callback_t func, gpointer user_data)
 }
 
 void
-cf_callback_remove(cf_callback_t func)
+cf_callback_remove(cf_callback_t func, gpointer user_data)
 {
   cf_callback_data_t *cb;
   GList              *cb_item = cf_callbacks;
 
   while (cb_item != NULL) {
     cb = (cf_callback_data_t *)cb_item->data;
-    if (cb->cb_fct == func) {
+    if (cb->cb_fct == func && cb->user_data == user_data) {
       cf_callbacks = g_list_remove(cf_callbacks, cb);
       g_free(cb);
       return;
@@ -221,46 +215,12 @@ void
 cf_timestamp_auto_precision(capture_file *cf)
 {
   int i;
-  int prec = timestamp_get_precision();
-
 
   /* don't try to get the file's precision if none is opened */
   if (cf->state == FILE_CLOSED) {
     return;
   }
 
-  /* if we are in auto mode, set precision of current file */
-  if (prec == TS_PREC_AUTO ||
-     prec == TS_PREC_AUTO_SEC ||
-     prec == TS_PREC_AUTO_DSEC ||
-     prec == TS_PREC_AUTO_CSEC ||
-     prec == TS_PREC_AUTO_MSEC ||
-     prec == TS_PREC_AUTO_USEC ||
-     prec == TS_PREC_AUTO_NSEC)
-  {
-    switch(wtap_file_tsprecision(cf->wth)) {
-    case(WTAP_FILE_TSPREC_SEC):
-      timestamp_set_precision(TS_PREC_AUTO_SEC);
-      break;
-    case(WTAP_FILE_TSPREC_DSEC):
-      timestamp_set_precision(TS_PREC_AUTO_DSEC);
-      break;
-    case(WTAP_FILE_TSPREC_CSEC):
-      timestamp_set_precision(TS_PREC_AUTO_CSEC);
-      break;
-    case(WTAP_FILE_TSPREC_MSEC):
-      timestamp_set_precision(TS_PREC_AUTO_MSEC);
-      break;
-    case(WTAP_FILE_TSPREC_USEC):
-      timestamp_set_precision(TS_PREC_AUTO_USEC);
-      break;
-    case(WTAP_FILE_TSPREC_NSEC):
-      timestamp_set_precision(TS_PREC_AUTO_NSEC);
-      break;
-    default:
-      g_assert_not_reached();
-    }
-  }
   /* Set the column widths of those columns that show the time in
      "command-line-specified" format. */
   for (i = 0; i < cf->cinfo.num_cols; i++) {
@@ -335,12 +295,12 @@ ws_epan_new(capture_file *cf)
 }
 
 cf_status_t
-cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
+cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err)
 {
   wtap  *wth;
   gchar *err_info;
 
-  wth = wtap_open_offline(fname, err, &err_info, TRUE);
+  wth = wtap_open_offline(fname, type, err, &err_info, TRUE);
   if (wth == NULL)
     goto fail;
 
@@ -348,9 +308,12 @@ cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
      and fill in the information for this file. */
   cf_close(cf);
 
+  /* Initialize the packet header. */
+  wtap_phdr_init(&cf->phdr);
+
   /* XXX - we really want to initialize this after we've read all
      the packets, so we know how much we'll ultimately need. */
-  buffer_init(&cf->buf, 1500);
+  ws_buffer_init(&cf->buf, 1500);
 
   /* Create new epan session for dissection.
    * (The old one was freed in cf_close().)
@@ -377,6 +340,7 @@ cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
   cf->computed_elapsed = 0;
 
   cf->cd_t        = wtap_file_type_subtype(cf->wth);
+  cf->open_type   = type;
   cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
   cf->count     = 0;
   cf->packet_comment_count = 0;
@@ -440,22 +404,22 @@ cf_add_encapsulation_type(capture_file *cf, int encap)
   g_array_append_val(cf->linktypes, encap);
 }
 
-/*
- * Reset the state for the currently closed file, but don't do the
- * UI callbacks; this is for use in "cf_open()", where we don't
- * want the UI to go from "file open" to "file closed" back to
- * "file open", we want it to go from "old file open" to "new file
- * open and being read".
- *
- * XXX - currently, cf_open() calls cf_close(), rather than
- * cf_reset_state().
- */
-static void
-cf_reset_state(capture_file *cf)
+/* Reset everything to a pristine state */
+void
+cf_close(capture_file *cf)
 {
+  cf->stop_flag = FALSE;
+  if (cf->state == FILE_CLOSED)
+    return; /* Nothing to do */
+
   /* Die if we're in the middle of reading a file. */
   g_assert(cf->state != FILE_READ_IN_PROGRESS);
 
+  cf_callback_invoke(cf_cb_file_closing, cf);
+
+  /* close things, if not already closed before */
+  color_filters_cleanup();
+
   if (cf->wth) {
     wtap_close(cf->wth);
     cf->wth = NULL;
@@ -471,8 +435,14 @@ cf_reset_state(capture_file *cf)
   /* ...which means we have no changes to that file to save. */
   cf->unsaved_changes = FALSE;
 
+  /* no open_routine type */
+  cf->open_type = WTAP_TYPE_AUTO;
+
+  /* Clean up the packet header. */
+  wtap_phdr_cleanup(&cf->phdr);
+
   /* Free up the packet buffer. */
-  buffer_free(&cf->buf);
+  ws_buffer_free(&cf->buf);
 
   dfilter_free(cf->rfcode);
   cf->rfcode = NULL;
@@ -501,8 +471,10 @@ cf_reset_state(capture_file *cf)
   cf->finfo_selected = NULL;
 
   /* No frame link-layer types, either. */
-  g_array_free(cf->linktypes, TRUE);
-  cf->linktypes = NULL;
+  if (cf->linktypes != NULL) {
+    g_array_free(cf->linktypes, TRUE);
+    cf->linktypes = NULL;
+  }
 
   /* Clear the packet list. */
   packet_list_freeze();
@@ -514,25 +486,13 @@ cf_reset_state(capture_file *cf)
 
   reset_tap_listeners();
 
+  epan_free(cf->epan);
+  cf->epan = NULL;
+
   /* We have no file open. */
   cf->state = FILE_CLOSED;
-}
-
-/* Reset everything to a pristine state */
-void
-cf_close(capture_file *cf)
-{
-  if (cf->state != FILE_CLOSED) {
-    cf_callback_invoke(cf_cb_file_closing, cf);
-
-  /* close things, if not already closed before */
-    color_filters_cleanup();
-    cf_reset_state(cf);
-    epan_free(cf->epan);
-    cf->epan = NULL;
 
-    cf_callback_invoke(cf_cb_file_closed, cf);
-  }
+  cf_callback_invoke(cf_cb_file_closed, cf);
 }
 
 static float
@@ -574,7 +534,6 @@ cf_read(capture_file *cf, gboolean reloading)
   gchar               *err_info;
   gchar               *name_ptr;
   progdlg_t           *progbar        = NULL;
-  gboolean             stop_flag;
   GTimeVal             start_time;
   epan_dissect_t       edt;
   dfilter_t           *dfcode;
@@ -586,7 +545,7 @@ cf_read(capture_file *cf, gboolean reloading)
    * We assume this will not fail since cf->dfilter is only set in
    * cf_filter IFF the filter was valid.
    */
-  compiled = dfilter_compile(cf->dfilter, &dfcode);
+  compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
   g_assert(!cf->dfilter || (compiled && dfcode));
 
   /* Get the union of the flags for all tap listeners. */
@@ -610,7 +569,7 @@ cf_read(capture_file *cf, gboolean reloading)
   /* The packet list window will be empty until the file is completly loaded */
   packet_list_freeze();
 
-  stop_flag = FALSE;
+  cf->stop_flag = FALSE;
   g_get_current_time(&start_time);
 
   epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
@@ -660,10 +619,10 @@ cf_read(capture_file *cf, gboolean reloading)
           progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
           if (reloading)
             progbar = delayed_create_progress_dlg(cf->window, "Reloading", name_ptr,
-                TRUE, &stop_flag, &start_time, progbar_val);
+                TRUE, &cf->stop_flag, &start_time, progbar_val);
           else
             progbar = delayed_create_progress_dlg(cf->window, "Loading", name_ptr,
-                TRUE, &stop_flag, &start_time, progbar_val);
+                TRUE, &cf->stop_flag, &start_time, progbar_val);
         }
 
         /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
@@ -689,7 +648,7 @@ cf_read(capture_file *cf, gboolean reloading)
         }
       }
 
-      if (stop_flag) {
+      if (cf->stop_flag) {
         /* Well, the user decided to abort the read. He/She will be warned and
            it might be enough for him/her to work with the already loaded
            packets.
@@ -703,9 +662,9 @@ cf_read(capture_file *cf, gboolean reloading)
   }
   CATCH(OutOfMemoryError) {
     simple_message_box(ESD_TYPE_ERROR, NULL,
-                   "Some infos / workarounds can be found at:\n"
-                   "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
-                   "Sorry, but Wireshark has run out of memory and has to terminate now!");
+                   "More information and workarounds can be found at\n"
+                   "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
+                   "Sorry, but Wireshark has run out of memory and has to terminate now.");
 #if 0
     /* Could we close the current capture and free up memory from that? */
 #else
@@ -763,13 +722,13 @@ cf_read(capture_file *cf, gboolean reloading)
     packet_list_select_first_row();
   }
 
-  if (stop_flag) {
+  if (cf->stop_flag) {
     simple_message_box(ESD_TYPE_WARN, NULL,
                   "The remaining packets in the file were discarded.\n"
                   "\n"
                   "As a lot of packets from the original file will be missing,\n"
                   "remember to be careful when saving the current content to a file.\n",
-                  "File loading was cancelled!");
+                  "File loading was cancelled.");
     return CF_READ_ERROR;
   }
 
@@ -782,23 +741,10 @@ cf_read(capture_file *cf, gboolean reloading)
     case WTAP_ERR_UNSUPPORTED:
       simple_error_message_box(
                  "The capture file contains record data that Wireshark doesn't support.\n(%s)",
-                 err_info);
-      g_free(err_info);
-      break;
-
-    case WTAP_ERR_UNSUPPORTED_ENCAP:
-      simple_error_message_box(
-                 "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
-                 err_info);
+                 err_info != NULL ? err_info : "no information supplied");
       g_free(err_info);
       break;
 
-    case WTAP_ERR_CANT_READ:
-      simple_error_message_box(
-                 "An attempt to read from the capture file failed for"
-                 " some unknown reason.");
-      break;
-
     case WTAP_ERR_SHORT_READ:
       simple_error_message_box(
                  "The capture file appears to have been cut short"
@@ -808,14 +754,14 @@ cf_read(capture_file *cf, gboolean reloading)
     case WTAP_ERR_BAD_FILE:
       simple_error_message_box(
                  "The capture file appears to be damaged or corrupt.\n(%s)",
-                 err_info);
+                 err_info != NULL ? err_info : "no information supplied");
       g_free(err_info);
       break;
 
     case WTAP_ERR_DECOMPRESS:
       simple_error_message_box(
-                 "The compressed capture file appears to be damaged or corrupt.\n"
-                 "(%s)", err_info);
+                 "The compressed capture file appears to be damaged or corrupt.\n(%s)",
+                 err_info != NULL ? err_info : "no information supplied");
       g_free(err_info);
       break;
 
@@ -835,10 +781,10 @@ cf_read_status_t
 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
 {
   gchar            *err_info;
-  int               newly_displayed_packets = 0;
+  volatile int      newly_displayed_packets = 0;
   dfilter_t        *dfcode;
-  epan_dissect_t       edt;
-  gboolean create_proto_tree;
+  epan_dissect_t    edt;
+  gboolean          create_proto_tree;
   guint             tap_flags;
   gboolean          compiled;
 
@@ -846,7 +792,7 @@ cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
    * We assume this will not fail since cf->dfilter is only set in
    * cf_filter IFF the filter was valid.
    */
-  compiled = dfilter_compile(cf->dfilter, &dfcode);
+  compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
   g_assert(!cf->dfilter || (compiled && dfcode));
 
   /* Get the union of the flags for all tap listeners. */
@@ -889,9 +835,9 @@ cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
   }
   CATCH(OutOfMemoryError) {
     simple_message_box(ESD_TYPE_ERROR, NULL,
-                   "Some infos / workarounds can be found at:\n"
-                   "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
-                   "Sorry, but Wireshark has run out of memory and has to terminate now!");
+                   "More information and workarounds can be found at\n"
+                   "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
+                   "Sorry, but Wireshark has run out of memory and has to terminate now.");
 #if 0
     /* Could we close the current capture and free up memory from that? */
     return CF_READ_ABORTED;
@@ -939,10 +885,14 @@ cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
   } else if (*err != 0) {
     /* We got an error reading the capture file.
        XXX - pop up a dialog box instead? */
-    g_warning("Error \"%s\" while reading: \"%s\" (\"%s\")",
-        wtap_strerror(*err), err_info, cf->filename);
-    g_free(err_info);
-
+    if (err_info != NULL) {
+      g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
+                wtap_strerror(*err), cf->filename, err_info);
+      g_free(err_info);
+    } else {
+      g_warning("Error \"%s\" while reading \"%s\"",
+                wtap_strerror(*err), cf->filename);
+    }
     return CF_READ_ERROR;
   } else
     return CF_READ_OK;
@@ -969,7 +919,7 @@ cf_finish_tail(capture_file *cf, int *err)
    * We assume this will not fail since cf->dfilter is only set in
    * cf_filter IFF the filter was valid.
    */
-  compiled = dfilter_compile(cf->dfilter, &dfcode);
+  compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
   g_assert(!cf->dfilter || (compiled && dfcode));
 
   /* Get the union of the flags for all tap listeners. */
@@ -1044,10 +994,14 @@ cf_finish_tail(capture_file *cf, int *err)
   if (*err != 0) {
     /* We got an error reading the capture file.
        XXX - pop up a dialog box? */
-
-    g_warning("Error \"%s\" while reading: \"%s\" (\"%s\")",
-        wtap_strerror(*err), err_info, cf->filename);
-    g_free(err_info);
+    if (err_info != NULL) {
+      g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
+                wtap_strerror(*err), cf->filename, err_info);
+      g_free(err_info);
+    } else {
+      g_warning("Error \"%s\" while reading \"%s\"",
+                wtap_strerror(*err), cf->filename);
+    }
     return CF_READ_ERROR;
   } else {
     return CF_READ_OK;
@@ -1108,13 +1062,6 @@ cf_get_packet_count(capture_file *cf)
   return cf->count;
 }
 
-/* XXX - use a macro instead? */
-void
-cf_set_packet_count(capture_file *cf, int packet_count)
-{
-  cf->count = packet_count;
-}
-
 /* XXX - use a macro instead? */
 gboolean
 cf_is_tempfile(capture_file *cf)
@@ -1173,7 +1120,7 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
   }
 
   /* Dissect the frame. */
-  epan_dissect_run_with_taps(edt, phdr, frame_tvbuff_new(fdata, buf), fdata, cinfo);
+  epan_dissect_run_with_taps(edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, buf), fdata, cinfo);
 
   /* If we don't have a display filter, set "passed_dfilter" to 1. */
   if (dfcode != NULL) {
@@ -1194,7 +1141,7 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
 
   if (add_to_packet_list) {
     /* We fill the needed columns from new_packet_list */
-      row = packet_list_append(cinfo, fdata, &edt->pi);
+      row = packet_list_append(cinfo, fdata);
   }
 
   if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
@@ -1237,7 +1184,7 @@ read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
   frame_data    fdlocal;
   guint32       framenum;
   frame_data   *fdata;
-  int           passed;
+  gboolean      passed;
   int           row = -1;
 
   /* Add this packet's link-layer encapsulation type to cf->linktypes, if
@@ -1260,7 +1207,7 @@ read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
 
     epan_dissect_init(&rf_edt, cf->epan, TRUE, FALSE);
     epan_dissect_prime_dfilter(&rf_edt, cf->rfcode);
-    epan_dissect_run(&rf_edt, phdr, frame_tvbuff_new(&fdlocal, buf), &fdlocal, NULL);
+    epan_dissect_run(&rf_edt, cf->cd_t, phdr, frame_tvbuff_new(&fdlocal, buf), &fdlocal, NULL);
     passed = dfilter_apply_edt(cf->rfcode, &rf_edt);
     epan_dissect_cleanup(&rf_edt);
   }
@@ -1283,366 +1230,186 @@ read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
   return row;
 }
 
-cf_status_t
-cf_merge_files(char **out_filenamep, int in_file_count,
-               char *const *in_filenames, int file_type, gboolean do_append)
-{
-  merge_in_file_t *in_files, *in_file;
-  char            *out_filename;
-  char            *tmpname;
-  int              out_fd;
-  wtap_dumper     *pdh;
-  int              open_err, read_err, write_err, close_err;
-  gchar           *err_info;
-  int              err_fileno;
-  int              i;
-  gboolean         got_read_error     = FALSE, got_write_error = FALSE;
-  gint64           data_offset;
-  progdlg_t       *progbar            = NULL;
-  gboolean         stop_flag;
-  gint64           f_len, file_pos;
-  float            progbar_val;
-  GTimeVal         start_time;
-  gchar            status_str[100];
+
+typedef struct _callback_data_t {
+  gint64           f_len;
   gint64           progbar_nextstep;
   gint64           progbar_quantum;
-  gchar           *display_basename;
-  int              selected_frame_type;
-  gboolean         fake_interface_ids = FALSE;
-
-  /* open the input files */
-  if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
-                           &open_err, &err_info, &err_fileno)) {
-    g_free(in_files);
-    cf_open_failure_alert_box(in_filenames[err_fileno], open_err, err_info,
-                              FALSE, 0);
-    return CF_ERROR;
-  }
-
-  if (*out_filenamep != NULL) {
-    out_filename = *out_filenamep;
-    out_fd = ws_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
-    if (out_fd == -1)
-      open_err = errno;
-  } else {
-    out_fd = create_tempfile(&tmpname, "wireshark");
-    if (out_fd == -1)
-      open_err = errno;
-    out_filename = g_strdup(tmpname);
-    *out_filenamep = out_filename;
-  }
-  if (out_fd == -1) {
-    err_info = NULL;
-    merge_close_in_files(in_file_count, in_files);
-    g_free(in_files);
-    cf_open_failure_alert_box(out_filename, open_err, NULL, TRUE, file_type);
-    return CF_ERROR;
-  }
-
-  selected_frame_type = merge_select_frame_type(in_file_count, in_files);
-
-  /* If we are trying to merge a number of libpcap files with different encapsulation types
-   * change the output file type to pcapng and create SHB and IDB:s for the new file use the
-   * interface index stored in in_files per file to change the phdr before writing the datablock.
-   * XXX should it be an option to convert to pcapng?
-   *
-   * We need something similar when merging pcapng files possibly with an option to say
-   * the same interface(s) used in all in files. SHBs comments should be merged together.
-   */
-  if ((selected_frame_type == WTAP_ENCAP_PER_PACKET)&&(file_type == WTAP_FILE_TYPE_SUBTYPE_PCAP)) {
-    /* Write output in pcapng format */
-    wtapng_section_t            *shb_hdr;
-    wtapng_iface_descriptions_t *idb_inf, *idb_inf_merge_file;
-    wtapng_if_descr_t            int_data, *file_int_data;
-    GString                     *comment_gstr;
-
-    fake_interface_ids = TRUE;
-    /* Create SHB info */
-    shb_hdr      = wtap_file_get_shb_info(in_files[0].wth);
-    comment_gstr = g_string_new("");
-    g_string_append_printf(comment_gstr, "%s \n",shb_hdr->opt_comment);
-    g_string_append_printf(comment_gstr, "File created by merging: \n");
-    file_type = WTAP_FILE_TYPE_SUBTYPE_PCAPNG;
-
-    for (i = 0; i < in_file_count; i++) {
-        g_string_append_printf(comment_gstr, "File%d: %s \n",i+1,in_files[i].filename);
-    }
-    shb_hdr->section_length = -1;
-    /* options */
-    shb_hdr->opt_comment   = g_string_free(comment_gstr, FALSE);  /* NULL if not available */
-    shb_hdr->shb_hardware  = NULL;        /* NULL if not available, UTF-8 string containing the        */
-                                          /*  description of the hardware used to create this section. */
-    shb_hdr->shb_os        = NULL;        /* NULL if not available, UTF-8 string containing the name   */
-                                          /*  of the operating system used to create this section.     */
-    shb_hdr->shb_user_appl = "Wireshark"; /* NULL if not available, UTF-8 string containing the name   */
-                                          /*  of the application used to create this section.          */
-
-    /* create fake IDB info */
-    idb_inf = g_new(wtapng_iface_descriptions_t,1);
-    idb_inf->number_of_interfaces = in_file_count; /* TODO make this the number of DIFFERENT encapsulation types
-                                                    * check that snaplength is the same too?
-                                                    */
-    idb_inf->interface_data = g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
-
-    for (i = 0; i < in_file_count; i++) {
-      idb_inf_merge_file               = wtap_file_get_idb_info(in_files[i].wth);
-      /* read the interface data from the in file to our combined interfca data */
-      file_int_data = &g_array_index (idb_inf_merge_file->interface_data, wtapng_if_descr_t, 0);
-      int_data.wtap_encap            = file_int_data->wtap_encap;
-      int_data.time_units_per_second = file_int_data->time_units_per_second;
-      int_data.link_type             = file_int_data->link_type;
-      int_data.snap_len              = file_int_data->snap_len;
-      int_data.if_name               = g_strdup(file_int_data->if_name);
-      int_data.opt_comment           = NULL;
-      int_data.if_description        = NULL;
-      int_data.if_speed              = 0;
-      int_data.if_tsresol            = 6;
-      int_data.if_filter_str         = NULL;
-      int_data.bpf_filter_len        = 0;
-      int_data.if_filter_bpf_bytes   = NULL;
-      int_data.if_os                 = NULL;
-      int_data.if_fcslen             = -1;
-      int_data.num_stat_entries      = 0;          /* Number of ISB:s */
-      int_data.interface_statistics  = NULL;
-
-      g_array_append_val(idb_inf->interface_data, int_data);
-      g_free(idb_inf_merge_file);
-
-      /* Set fake interface Id in per file data */
-      in_files[i].interface_id = i;
-    }
+  GTimeVal         start_time;
+  progdlg_t       *progbar;
+  gboolean         stop_flag;
+} callback_data_t;
 
-    pdh = wtap_dump_fdopen_ng(out_fd, file_type,
-                              selected_frame_type,
-                              merge_max_snapshot_length(in_file_count, in_files),
-                              FALSE /* compressed */, shb_hdr, idb_inf /* wtapng_iface_descriptions_t *idb_inf */, &open_err);
 
-    if (pdh == NULL) {
-      ws_close(out_fd);
-      merge_close_in_files(in_file_count, in_files);
-      g_free(in_files);
-      cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
-                                file_type);
-      return CF_ERROR;
-    }
+static gboolean
+merge_callback(merge_event event, int num _U_,
+               const merge_in_file_t in_files[], const guint in_file_count,
+               void *data)
+{
+  guint i;
+  callback_data_t *cb_data = (callback_data_t*) data;
 
-  } else {
+  g_assert(cb_data != NULL);
 
-    pdh = wtap_dump_fdopen(out_fd, file_type,
-                           selected_frame_type,
-                           merge_max_snapshot_length(in_file_count, in_files),
-                           FALSE /* compressed */, &open_err);
-    if (pdh == NULL) {
-      ws_close(out_fd);
-      merge_close_in_files(in_file_count, in_files);
-      g_free(in_files);
-      cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
-                                file_type);
-      return CF_ERROR;
-    }
-  }
+  switch (event) {
 
-  /* Get the sum of the sizes of all the files. */
-  f_len = 0;
-  for (i = 0; i < in_file_count; i++)
-    f_len += in_files[i].size;
+    case MERGE_EVENT_INPUT_FILES_OPENED:
+      /* do nothing */
+      break;
 
-  /* Update the progress bar when it gets to this value. */
-  progbar_nextstep = 0;
-  /* When we reach the value that triggers a progress bar update,
-     bump that value by this amount. */
-  progbar_quantum = f_len/N_PROGBAR_UPDATES;
-  /* Progress so far. */
-  progbar_val = 0.0f;
+    case MERGE_EVENT_FRAME_TYPE_SELECTED:
+      /* do nothing */
+      break;
 
-  stop_flag = FALSE;
-  g_get_current_time(&start_time);
+    case MERGE_EVENT_READY_TO_MERGE:
+      /* Get the sum of the sizes of all the files. */
+      for (i = 0; i < in_file_count; i++)
+        cb_data->f_len += in_files[i].size;
 
-  /* do the merge (or append) */
-  for (;;) {
-    if (do_append)
-      in_file = merge_append_read_packet(in_file_count, in_files, &read_err,
-                                         &err_info);
-    else
-      in_file = merge_read_packet(in_file_count, in_files, &read_err,
-                                  &err_info);
-    if (in_file == NULL) {
-      /* EOF */
-      break;
-    }
+      /* When we reach the value that triggers a progress bar update,
+         bump that value by this amount. */
+      cb_data->progbar_quantum = cb_data->f_len / N_PROGBAR_UPDATES;
 
-    if (read_err != 0) {
-      /* I/O error reading from in_file */
-      got_read_error = TRUE;
+      g_get_current_time(&cb_data->start_time);
       break;
-    }
-
-    /* Get the sum of the data offsets in all of the files. */
-    data_offset = 0;
-    for (i = 0; i < in_file_count; i++)
-      data_offset += in_files[i].data_offset;
 
-    /* Create the progress bar if necessary.
-       We check on every iteration of the loop, so that it takes no
-       longer than the standard time to create it (otherwise, for a
-       large file, we might take considerably longer than that standard
-       time in order to get to the next progress bar step). */
-    if (progbar == NULL) {
-      progbar = delayed_create_progress_dlg(NULL, "Merging", "files",
-        FALSE, &stop_flag, &start_time, progbar_val);
-    }
+    case MERGE_EVENT_PACKET_WAS_READ:
+      {
+        gint64 data_offset = 0;
 
-    /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
-       when we update it, we have to run the GTK+ main loop to get it
-       to repaint what's pending, and doing so may involve an "ioctl()"
-       to see if there's any pending input from an X server, and doing
-       that for every packet can be costly, especially on a big file. */
-    if (data_offset >= progbar_nextstep) {
-        /* Get the sum of the seek positions in all of the files. */
-        file_pos = 0;
+        /* Get the sum of the data offsets in all of the files. */
+        data_offset = 0;
         for (i = 0; i < in_file_count; i++)
-          file_pos += wtap_read_so_far(in_files[i].wth);
-        progbar_val = (gfloat) file_pos / (gfloat) f_len;
-        if (progbar_val > 1.0f) {
-          /* Some file probably grew while we were reading it.
-             That "shouldn't happen", so we'll just clip the progress
-             value at 1.0. */
-          progbar_val = 1.0f;
-        }
-        if (progbar != NULL) {
-          g_snprintf(status_str, sizeof(status_str),
-                     "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
-                     file_pos / 1024, f_len / 1024);
-          update_progress_dlg(progbar, progbar_val, status_str);
+          data_offset += in_files[i].data_offset;
+
+        /* Create the progress bar if necessary.
+           We check on every iteration of the loop, so that it takes no
+           longer than the standard time to create it (otherwise, for a
+           large file, we might take considerably longer than that standard
+           time in order to get to the next progress bar step). */
+        if (cb_data->progbar == NULL) {
+          cb_data->progbar = delayed_create_progress_dlg(NULL, "Merging", "files",
+            FALSE, &cb_data->stop_flag, &cb_data->start_time, 0.0f);
         }
-        progbar_nextstep += progbar_quantum;
-    }
 
-    if (stop_flag) {
-      /* Well, the user decided to abort the merge. */
-      break;
-    }
+        /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
+           when we update it, we have to run the GTK+ main loop to get it
+           to repaint what's pending, and doing so may involve an "ioctl()"
+           to see if there's any pending input from an X server, and doing
+           that for every packet can be costly, especially on a big file. */
+        if (data_offset >= cb_data->progbar_nextstep) {
+            float  progbar_val;
+            gint64 file_pos = 0;
+            /* Get the sum of the seek positions in all of the files. */
+            for (i = 0; i < in_file_count; i++)
+              file_pos += wtap_read_so_far(in_files[i].wth);
+
+            progbar_val = (gfloat) file_pos / (gfloat) cb_data->f_len;
+            if (progbar_val > 1.0f) {
+              /* Some file probably grew while we were reading it.
+                 That "shouldn't happen", so we'll just clip the progress
+                 value at 1.0. */
+              progbar_val = 1.0f;
+            }
 
-    /* If we have WTAP_ENCAP_PER_PACKET and the infiles are of type
-     * WTAP_FILE_TYPE_SUBTYPE_PCAP, we need to set the interface id
-     * in the paket header = the interface index we used in the IDBs
-     * interface description for this file(encapsulation type).
-     */
-    if (fake_interface_ids) {
-      struct wtap_pkthdr *phdr;
+            if (cb_data->progbar != NULL) {
+              gchar status_str[100];
+              g_snprintf(status_str, sizeof(status_str),
+                         "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
+                         file_pos / 1024, cb_data->f_len / 1024);
+              update_progress_dlg(cb_data->progbar, progbar_val, status_str);
+            }
+            cb_data->progbar_nextstep += cb_data->progbar_quantum;
+        }
+      }
+      break;
 
-      phdr = wtap_phdr(in_file->wth);
-      phdr->interface_id = in_file->interface_id;
-      phdr->presence_flags = phdr->presence_flags | WTAP_HAS_INTERFACE_ID;
-    }
-    if (!wtap_dump(pdh, wtap_phdr(in_file->wth),
-                   wtap_buf_ptr(in_file->wth), &write_err)) {
-      got_write_error = TRUE;
+    case MERGE_EVENT_DONE:
+      /* We're done merging the files; destroy the progress bar if it was created. */
+      if (cb_data->progbar != NULL)
+        destroy_progress_dlg(cb_data->progbar);
       break;
-    }
   }
 
-  /* We're done merging the files; destroy the progress bar if it was created. */
-  if (progbar != NULL)
-    destroy_progress_dlg(progbar);
+  return cb_data->stop_flag;
+}
 
-  merge_close_in_files(in_file_count, in_files);
-  if (!got_read_error && !got_write_error) {
-    if (!wtap_dump_close(pdh, &write_err))
-      got_write_error = TRUE;
-  } else
-    wtap_dump_close(pdh, &close_err);
 
-  if (got_read_error) {
-    /*
-     * 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) {
-        /* Put up a message box noting that a read failed somewhere along
-           the line. */
-        display_basename = g_filename_display_basename(in_files[i].filename);
-        switch (read_err) {
-
-        case WTAP_ERR_UNSUPPORTED_ENCAP:
-          simple_error_message_box(
-                     "The capture file %s has a packet with a network type that Wireshark doesn't support.\n(%s)",
-                     display_basename, err_info);
-          g_free(err_info);
-          break;
 
-        case WTAP_ERR_CANT_READ:
-          simple_error_message_box(
-                     "An attempt to read from the capture file %s failed for"
-                     " some unknown reason.", display_basename);
-          break;
+cf_status_t
+cf_merge_files(char **out_filenamep, int in_file_count,
+               char *const *in_filenames, int file_type, gboolean do_append)
+{
+  char                      *out_filename;
+  char                      *tmpname;
+  int                        out_fd;
+  int                        err      = 0;
+  gchar                     *err_info = NULL;
+  int                        err_fileno;
+  merge_result               status;
+  merge_progress_callback_t  cb;
 
-        case WTAP_ERR_SHORT_READ:
-          simple_error_message_box(
-                     "The capture file %s appears to have been cut short"
-                      " in the middle of a packet.", display_basename);
-          break;
 
-        case WTAP_ERR_BAD_FILE:
-          simple_error_message_box(
-                     "The capture file %s appears to be damaged or corrupt.\n(%s)",
-                     display_basename, err_info);
-          g_free(err_info);
-          break;
+  if (*out_filenamep != NULL) {
+    out_filename = *out_filenamep;
+    out_fd = ws_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
+    if (out_fd == -1)
+      err = errno;
+  } else {
+    out_fd = create_tempfile(&tmpname, "wireshark");
+    if (out_fd == -1)
+      err = errno;
+    out_filename = g_strdup(tmpname);
+    *out_filenamep = out_filename;
+  }
+  if (out_fd == -1) {
+    cf_open_failure_alert_box(out_filename, err, NULL, TRUE, file_type);
+    return CF_ERROR;
+  }
 
-        case WTAP_ERR_DECOMPRESS:
-          simple_error_message_box(
-                     "The compressed capture file %s appears to be damaged or corrupt.\n"
-                     "(%s)", display_basename, err_info);
-          g_free(err_info);
-          break;
+  /* prepare our callback routine */
+  cb.callback_func = merge_callback;
+  cb.data = g_malloc0(sizeof(callback_data_t));
 
-        default:
-          simple_error_message_box(
-                     "An error occurred while reading the"
-                     " capture file %s: %s.",
-                     display_basename,  wtap_strerror(read_err));
-          break;
-        }
-        g_free(display_basename);
-      }
-    }
-  }
+  /* merge the files */
+  status = merge_files(out_fd, out_filename, file_type,
+                       (const char *const *) in_filenames, in_file_count,
+                       do_append, IDB_MERGE_MODE_ALL_SAME, 0 /* snaplen */,
+                       "Wireshark", &cb, &err, &err_info, &err_fileno);
 
-  if (got_write_error) {
-    /* Put up an alert box for the write error. */
-    if (write_err < 0) {
-      /* Wiretap error. */
-      switch (write_err) {
+  g_free(cb.data);
 
-      case WTAP_ERR_UNSUPPORTED_ENCAP:
-        /*
-         * This is a problem with the particular frame we're writing;
-         * note that, and give the frame number.
-         */
-        display_basename = g_filename_display_basename(in_file->filename);
-        simple_error_message_box(
-                      "Frame %u of \"%s\" has a network type that can't be saved in a \"%s\" file.",
-                      in_file->packet_num, display_basename,
-                      wtap_file_type_subtype_string(file_type));
-        g_free(display_basename);
-        break;
+  switch (status) {
+    case MERGE_OK:
+      break;
 
-      default:
-        display_basename = g_filename_display_basename(out_filename);
-        simple_error_message_box(
-                      "An error occurred while writing to the file \"%s\": %s.",
-                      out_filename, wtap_strerror(write_err));
-        g_free(display_basename);
-        break;
-      }
-    } else {
-      /* OS error. */
-      write_failure_alert_box(out_filename, write_err);
-    }
+    case MERGE_USER_ABORTED:
+      /* this isn't really an error, though we will return CF_ERROR later */
+      break;
+
+    case MERGE_ERR_CANT_OPEN_INFILE:
+      cf_open_failure_alert_box(in_filenames[err_fileno], err, err_info,
+                                FALSE, 0);
+      break;
+
+    case MERGE_ERR_CANT_OPEN_OUTFILE:
+      cf_open_failure_alert_box(out_filename, err, err_info, TRUE,
+                                file_type);
+      break;
+
+    case MERGE_ERR_CANT_READ_INFILE:      /* fall through */
+    case MERGE_ERR_BAD_PHDR_INTERFACE_ID:
+    case MERGE_ERR_CANT_WRITE_OUTFILE:
+    case MERGE_ERR_CANT_CLOSE_OUTFILE:
+    default:
+      simple_error_message_box("%s", err_info ? err_info : "unknown error");
+      break;
   }
 
-  if (got_read_error || got_write_error || stop_flag) {
+  g_free(err_info);
+  ws_close(out_fd);
+
+  if (status != MERGE_OK) {
     /* Callers aren't expected to treat an error or an explicit abort
        differently - we put up error dialogs ourselves, so they don't
        have to. */
@@ -1657,6 +1424,7 @@ cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
   const char *filter_new = dftext ? dftext : "";
   const char *filter_old = cf->dfilter ? cf->dfilter : "";
   dfilter_t  *dfcode;
+  gchar      *err_msg;
   GTimeVal    start_time;
 
   /* if new filter equals old one, do nothing unless told to do so */
@@ -1676,12 +1444,13 @@ cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
      * and try to compile it.
      */
     dftext = g_strdup(dftext);
-    if (!dfilter_compile(dftext, &dfcode)) {
+    if (!dfilter_compile(dftext, &dfcode, &err_msg)) {
       /* The attempt failed; report an error. */
       simple_message_box(ESD_TYPE_ERROR, NULL,
           "See the help for a description of the display filter syntax.",
           "\"%s\" isn't a valid display filter: %s",
-          dftext, dfilter_error_msg);
+          dftext, err_msg);
+      g_free(err_msg);
       g_free(dftext);
       return CF_ERROR;
     }
@@ -1702,10 +1471,12 @@ cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
 
   /* Now rescan the packet list, applying the new filter, but not
      throwing away information constructed on a previous pass. */
-  if (dftext == NULL) {
-    rescan_packets(cf, "Resetting", "Filter", FALSE);
-  } else {
-    rescan_packets(cf, "Filtering", dftext, FALSE);
+  if (cf->state != FILE_CLOSED) {
+    if (dftext == NULL) {
+      rescan_packets(cf, "Resetting", "Filter", FALSE);
+    } else {
+      rescan_packets(cf, "Filtering", dftext, FALSE);
+    }
   }
 
   /* Cleanup and release all dfilter resources */
@@ -1729,8 +1500,8 @@ cf_redissect_packets(capture_file *cf)
 }
 
 gboolean
-cf_read_frame_r(capture_file *cf, const frame_data *fdata,
-                struct wtap_pkthdr *phdr, Buffer *buf)
+cf_read_record_r(capture_file *cf, const frame_data *fdata,
+                 struct wtap_pkthdr *phdr, Buffer *buf)
 {
   int    err;
   gchar *err_info;
@@ -1742,31 +1513,25 @@ cf_read_frame_r(capture_file *cf, const frame_data *fdata,
     const modified_frame_data *frame = (const modified_frame_data *) g_tree_lookup(cf->edited_frames, GINT_TO_POINTER(fdata->num));
 
     if (!frame) {
-      simple_error_message_box("fdata->file_off == -1, but can't find modified frame!");
+      simple_error_message_box("fdata->file_off == -1, but can't find modified frame.");
       return FALSE;
     }
 
     *phdr = frame->phdr;
-    buffer_assure_space(buf, frame->phdr.caplen);
-    memcpy(buffer_start_ptr(buf), frame->pd, frame->phdr.caplen);
+    ws_buffer_assure_space(buf, frame->phdr.caplen);
+    memcpy(ws_buffer_start_ptr(buf), frame->pd, frame->phdr.caplen);
     return TRUE;
   }
 #endif
 
-  if (!wtap_seek_read(cf->wth, fdata->file_off, phdr, buf,
-                      fdata->cap_len, &err, &err_info)) {
+  if (!wtap_seek_read(cf->wth, fdata->file_off, phdr, buf, &err, &err_info)) {
     display_basename = g_filename_display_basename(cf->filename);
     switch (err) {
 
-    case WTAP_ERR_UNSUPPORTED_ENCAP:
-      simple_error_message_box("The file \"%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)",
-                 display_basename, err_info);
-      g_free(err_info);
-      break;
-
     case WTAP_ERR_BAD_FILE:
       simple_error_message_box("An error occurred while reading from the file \"%s\": %s.\n(%s)",
-                 display_basename, wtap_strerror(err), err_info);
+                 display_basename, wtap_strerror(err),
+                 err_info != NULL ? err_info : "no information supplied");
       g_free(err_info);
       break;
 
@@ -1783,9 +1548,9 @@ cf_read_frame_r(capture_file *cf, const frame_data *fdata,
 }
 
 gboolean
-cf_read_frame(capture_file *cf, frame_data *fdata)
+cf_read_record(capture_file *cf, frame_data *fdata)
 {
-  return cf_read_frame_r(cf, fdata, &cf->phdr, &cf->buf);
+  return cf_read_record_r(cf, fdata, &cf->phdr, &cf->buf);
 }
 
 /* Rescan the list of packets, reconstructing the CList.
@@ -1807,7 +1572,6 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
   guint32     framenum;
   frame_data *fdata;
   progdlg_t  *progbar = NULL;
-  gboolean    stop_flag;
   int         count;
   frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
   int         selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
@@ -1830,7 +1594,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
    * We assume this will not fail since cf->dfilter is only set in
    * cf_filter IFF the filter was valid.
    */
-  compiled = dfilter_compile(cf->dfilter, &dfcode);
+  compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
   g_assert(!cf->dfilter || (compiled && dfcode));
 
   /* Get the union of the flags for all tap listeners. */
@@ -1866,6 +1630,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
     /* 'reset' dissection session */
     epan_free(cf->epan);
     cf->epan = ws_epan_new(cf);
+    cf->cinfo.epan = cf->epan;
 
     /* We need to redissect the packets so we have to discard our old
      * packet list store. */
@@ -1888,6 +1653,8 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
   cf->prev_cap = NULL;
   cf->cum_bytes = 0;
 
+  cf_callback_invoke(cf_cb_file_rescan_started, cf);
+
   /* Update the progress bar when it gets to this value. */
   progbar_nextstep = 0;
   /* When we reach the value that triggers a progress bar update,
@@ -1898,7 +1665,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
   /* Progress so far. */
   progbar_val = 0.0f;
 
-  stop_flag = FALSE;
+  cf->stop_flag = FALSE;
   g_get_current_time(&start_time);
 
   /* no previous row yet */
@@ -1926,7 +1693,8 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
        time in order to get to the next progress bar step). */
     if (progbar == NULL)
       progbar = delayed_create_progress_dlg(cf->window, action, action_item, TRUE,
-                                            &stop_flag, &start_time,
+                                            &cf->stop_flag,
+                                            &start_time,
                                             progbar_val);
 
     /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
@@ -1950,7 +1718,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
       progbar_nextstep += progbar_quantum;
     }
 
-    if (stop_flag) {
+    if (cf->stop_flag) {
       /* Well, the user decided to abort the filtering.  Just stop.
 
          XXX - go back to the previous filter?  Users probably just
@@ -1980,7 +1748,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
     /* Frame dependencies from the previous dissection/filtering are no longer valid. */
     fdata->flags.dependent_of_displayed = 0;
 
-    if (!cf_read_frame(cf, fdata))
+    if (!cf_read_record(cf, fdata))
       break; /* error reading the frame */
 
     /* If the previous frame is displayed, and we haven't yet seen the
@@ -1993,7 +1761,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
 
     add_packet_to_packet_list(fdata, cf, &edt, dfcode,
                                     cinfo, &cf->phdr,
-                                    buffer_start_ptr(&cf->buf),
+                                    ws_buffer_start_ptr(&cf->buf),
                                     add_to_packet_list);
 
     /* If this frame is displayed, and this is the first frame we've
@@ -2052,6 +1820,8 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
 
   packet_list_thaw();
 
+  cf_callback_invoke(cf_cb_file_rescan_finished, cf);
+
   if (selected_frame_num == -1) {
     /* The selected frame didn't pass the filter. */
     if (selected_frame == NULL) {
@@ -2106,7 +1876,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
            so we can't select it. */
         simple_message_box(ESD_TYPE_INFO, NULL,
                            "The capture file is probably not fully dissected.",
-                           "End of capture exceeded!");
+                           "End of capture exceeded.");
       }
     }
   }
@@ -2185,7 +1955,7 @@ ref_time_packets(capture_file *cf)
     if ( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ) {
         /* This frame either passed the display filter list or is marked as
         a time reference frame.  All time reference frames are displayed
-        even if they dont pass the display filter */
+        even if they don't pass the display filter */
         if (fdata->flags.ref_time) {
             /* if this was a TIME REF frame we should reset the cum_bytes field */
             cf->cum_bytes = fdata->pkt_len;
@@ -2205,7 +1975,7 @@ typedef enum {
 } psp_return_t;
 
 static psp_return_t
-process_specified_packets(capture_file *cf, packet_range_t *range,
+process_specified_records(capture_file *cf, packet_range_t *range,
     const char *string1, const char *string2, gboolean terminate_is_stop,
     gboolean (*callback)(capture_file *, frame_data *,
                          struct wtap_pkthdr *, const guint8 *, void *),
@@ -2219,7 +1989,6 @@ process_specified_packets(capture_file *cf, packet_range_t *range,
   progdlg_t       *progbar = NULL;
   int              progbar_count;
   float            progbar_val;
-  gboolean         progbar_stop_flag;
   GTimeVal         progbar_start_time;
   gchar            progbar_status_str[100];
   int              progbar_nextstep;
@@ -2227,8 +1996,8 @@ process_specified_packets(capture_file *cf, packet_range_t *range,
   range_process_e  process_this;
   struct wtap_pkthdr phdr;
 
-  memset(&phdr, 0, sizeof(struct wtap_pkthdr));
-  buffer_init(&buf, 1500);
+  wtap_phdr_init(&phdr);
+  ws_buffer_init(&buf, 1500);
 
   /* Update the progress bar when it gets to this value. */
   progbar_nextstep = 0;
@@ -2240,7 +2009,7 @@ process_specified_packets(capture_file *cf, packet_range_t *range,
   /* Progress so far. */
   progbar_val = 0.0f;
 
-  progbar_stop_flag = FALSE;
+  cf->stop_flag = FALSE;
   g_get_current_time(&progbar_start_time);
 
   if (range != NULL)
@@ -2259,7 +2028,7 @@ process_specified_packets(capture_file *cf, packet_range_t *range,
     if (progbar == NULL)
       progbar = delayed_create_progress_dlg(cf->window, string1, string2,
                                             terminate_is_stop,
-                                            &progbar_stop_flag,
+                                            &cf->stop_flag,
                                             &progbar_start_time,
                                             progbar_val);
 
@@ -2284,7 +2053,7 @@ process_specified_packets(capture_file *cf, packet_range_t *range,
       progbar_nextstep += progbar_quantum;
     }
 
-    if (progbar_stop_flag) {
+    if (cf->stop_flag) {
       /* Well, the user decided to abort the operation.  Just stop,
          and arrange to return PSP_STOPPED to our caller, so they know
          it was stopped explicitly. */
@@ -2307,13 +2076,13 @@ process_specified_packets(capture_file *cf, packet_range_t *range,
     }
 
     /* Get the packet */
-    if (!cf_read_frame_r(cf, fdata, &phdr, &buf)) {
+    if (!cf_read_record_r(cf, fdata, &phdr, &buf)) {
       /* Attempt to get the packet failed. */
       ret = PSP_FAILED;
       break;
     }
     /* Process the packet */
-    if (!callback(cf, fdata, &phdr, buffer_start_ptr(&buf), callback_args)) {
+    if (!callback(cf, fdata, &phdr, ws_buffer_start_ptr(&buf), callback_args)) {
       /* Callback failed.  We assume it reported the error appropriately. */
       ret = PSP_FAILED;
       break;
@@ -2325,7 +2094,8 @@ process_specified_packets(capture_file *cf, packet_range_t *range,
   if (progbar != NULL)
     destroy_progress_dlg(progbar);
 
-  buffer_free(&buf);
+  wtap_phdr_cleanup(&phdr);
+  ws_buffer_free(&buf);
 
   return ret;
 }
@@ -2336,13 +2106,13 @@ typedef struct {
 } retap_callback_args_t;
 
 static gboolean
-retap_packet(capture_file *cf _U_, frame_data *fdata,
+retap_packet(capture_file *cf, frame_data *fdata,
              struct wtap_pkthdr *phdr, const guint8 *pd,
              void *argsp)
 {
   retap_callback_args_t *args = (retap_callback_args_t *)argsp;
 
-  epan_dissect_run_with_taps(&args->edt, phdr, frame_tvbuff_new(fdata, pd), fdata, args->cinfo);
+  epan_dissect_run_with_taps(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, args->cinfo);
   epan_dissect_reset(&args->edt);
 
   return TRUE;
@@ -2358,6 +2128,13 @@ cf_retap_packets(capture_file *cf)
   guint                 tap_flags;
   psp_return_t          ret;
 
+  /* Presumably the user closed the capture file. */
+  if (cf == NULL) {
+    return CF_READ_ABORTED;
+  }
+
+  cf_callback_invoke(cf_cb_file_retap_started, cf);
+
   /* Do we have any tap listeners with filters? */
   filtering_tap_listeners = have_filtering_tap_listeners();
 
@@ -2381,12 +2158,14 @@ cf_retap_packets(capture_file *cf)
   packet_range_init(&range, cf);
   packet_range_process_init(&range);
 
-  ret = process_specified_packets(cf, &range, "Recalculating statistics on",
+  ret = process_specified_records(cf, &range, "Recalculating statistics on",
                                   "all packets", TRUE, retap_packet,
                                   &callback_args);
 
   epan_dissect_cleanup(&callback_args.edt);
 
+  cf_callback_invoke(cf_cb_file_retap_finished, cf);
+
   switch (ret) {
   case PSP_FINISHED:
     /* Completed successfully. */
@@ -2434,15 +2213,16 @@ print_packet(capture_file *cf, frame_data *fdata,
   int             cp_off;
   char            bookmark_name[9+10+1];  /* "__frameNNNNNNNNNN__\0" */
   char            bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0"  */
+  col_item_t*     col_item;
 
   /* Fill in the column information if we're printing the summary
      information. */
   if (args->print_args->print_summary) {
     col_custom_prime_edt(&args->edt, &cf->cinfo);
-    epan_dissect_run(&args->edt, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
+    epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
     epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
   } else
-    epan_dissect_run(&args->edt, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
+    epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
 
   if (args->print_formfeed) {
     if (!new_page(args->print_args->stream))
@@ -2471,8 +2251,9 @@ print_packet(capture_file *cf, frame_data *fdata,
     cp = &args->line_buf[0];
     line_len = 0;
     for (i = 0; i < args->num_visible_cols; i++) {
+      col_item = &cf->cinfo.columns[args->visible_cols[i]];
       /* Find the length of the string for this column. */
-      column_len = (int) strlen(cf->cinfo.col_data[args->visible_cols[i]]);
+      column_len = (int) strlen(col_item->col_data);
       if (args->col_widths[i] > column_len)
          column_len = args->col_widths[i];
 
@@ -2487,10 +2268,10 @@ print_packet(capture_file *cf, frame_data *fdata,
       }
 
       /* Right-justify the packet number column. */
-      if (cf->cinfo.col_fmt[args->visible_cols[i]] == COL_NUMBER)
-        g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], cf->cinfo.col_data[args->visible_cols[i]]);
+      if (col_item->col_fmt == COL_NUMBER)
+        g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], col_item->col_data);
       else
-        g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], cf->cinfo.col_data[args->visible_cols[i]]);
+        g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], col_item->col_data);
       cp += column_len;
       if (i != args->num_visible_cols - 1)
         *cp++ = ' ';
@@ -2525,7 +2306,7 @@ print_packet(capture_file *cf, frame_data *fdata,
     }
 
     /* Print the information in that tree. */
-    if (!proto_tree_print(args->print_args, &args->edt, args->print_args->stream))
+    if (!proto_tree_print(args->print_args, &args->edt, NULL, args->print_args->stream))
       goto fail;
 
     /* Print a blank line if we print anything after this (aka more than one packet). */
@@ -2592,7 +2373,7 @@ cf_print_packets(capture_file *cf, print_args_t *print_args)
   callback_args.num_visible_cols = 0;
   callback_args.visible_cols = NULL;
 
-  if (!print_preamble(print_args->stream, cf->filename, wireshark_svnversion)) {
+  if (!print_preamble(print_args->stream, cf->filename, get_ws_vcs_version_info())) {
     destroy_print_stream(print_args->stream);
     return CF_PRINT_WRITE_ERROR;
   }
@@ -2642,14 +2423,14 @@ cf_print_packets(capture_file *cf, print_args_t *print_args)
       if (i == last_visible_col)
         callback_args.col_widths[visible_col_count] = 0;
       else {
-        callback_args.col_widths[visible_col_count] = (gint) strlen(cf->cinfo.col_title[i]);
+        callback_args.col_widths[visible_col_count] = (gint) strlen(cf->cinfo.columns[i].col_title);
         data_width = get_column_char_width(get_column_format(i));
         if (data_width > callback_args.col_widths[visible_col_count])
           callback_args.col_widths[visible_col_count] = data_width;
       }
 
       /* Find the length of the string for this column. */
-      column_len = (int) strlen(cf->cinfo.col_title[i]);
+      column_len = (int) strlen(cf->cinfo.columns[i].col_title);
       if (callback_args.col_widths[i] > column_len)
         column_len = callback_args.col_widths[visible_col_count];
 
@@ -2666,9 +2447,9 @@ cf_print_packets(capture_file *cf, print_args_t *print_args)
 
       /* Right-justify the packet number column. */
 /*      if (cf->cinfo.col_fmt[i] == COL_NUMBER)
-        g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.col_title[i]);
+        g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
       else*/
-      g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[visible_col_count], cf->cinfo.col_title[i]);
+      g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
       cp += column_len;
       if (i != cf->cinfo.num_cols - 1)
         *cp++ = ' ';
@@ -2694,7 +2475,7 @@ cf_print_packets(capture_file *cf, print_args_t *print_args)
 
   /* Iterate through the list of packets, printing the packets we were
      told to print. */
-  ret = process_specified_packets(cf, &print_args->range, "Printing",
+  ret = process_specified_records(cf, &print_args->range, "Printing",
                                   "selected packets", TRUE, print_packet,
                                   &callback_args);
   epan_dissect_cleanup(&callback_args.edt);
@@ -2746,17 +2527,17 @@ typedef struct {
 } write_packet_callback_args_t;
 
 static gboolean
-write_pdml_packet(capture_file *cf _U_, frame_data *fdata,
+write_pdml_packet(capture_file *cf, frame_data *fdata,
                   struct wtap_pkthdr *phdr, const guint8 *pd,
           void *argsp)
 {
   write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
 
   /* Create the protocol tree, but don't fill in the column information. */
-  epan_dissect_run(&args->edt, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
+  epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
 
   /* Write out the information in that tree. */
-  proto_tree_write_pdml(&args->edt, args->fh);
+  write_pdml_proto_tree(&args->edt, args->fh);
 
   epan_dissect_reset(&args->edt);
 
@@ -2785,7 +2566,7 @@ cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
 
   /* Iterate through the list of packets, printing the packets we were
      told to print. */
-  ret = process_specified_packets(cf, &print_args->range, "Writing PDML",
+  ret = process_specified_records(cf, &print_args->range, "Writing PDML",
                                   "selected packets", TRUE,
                                   write_pdml_packet, &callback_args);
 
@@ -2826,12 +2607,13 @@ write_psml_packet(capture_file *cf, frame_data *fdata,
 {
   write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
 
+  /* Fill in the column information */
   col_custom_prime_edt(&args->edt, &cf->cinfo);
-  epan_dissect_run(&args->edt, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
+  epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
   epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
 
-  /* Write out the information in that tree. */
-  proto_tree_write_psml(&args->edt, args->fh);
+  /* Write out the column information. */
+  write_psml_columns(&args->edt, args->fh);
 
   epan_dissect_reset(&args->edt);
 
@@ -2851,7 +2633,7 @@ cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
   if (fh == NULL)
     return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
 
-  write_psml_preamble(fh);
+  write_psml_preamble(&cf->cinfo, fh);
   if (ferror(fh)) {
     fclose(fh);
     return CF_PRINT_WRITE_ERROR;
@@ -2866,7 +2648,7 @@ cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
 
   /* Iterate through the list of packets, printing the packets we were
      told to print. */
-  ret = process_specified_packets(cf, &print_args->range, "Writing PSML",
+  ret = process_specified_records(cf, &print_args->range, "Writing PSML",
                                   "selected packets", TRUE,
                                   write_psml_packet, &callback_args);
 
@@ -2909,11 +2691,11 @@ write_csv_packet(capture_file *cf, frame_data *fdata,
 
   /* Fill in the column information */
   col_custom_prime_edt(&args->edt, &cf->cinfo);
-  epan_dissect_run(&args->edt, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
+  epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
   epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
 
-  /* Write out the information in that tree. */
-  proto_tree_write_csv(&args->edt, args->fh);
+  /* Write out the column information. */
+  write_csv_columns(&args->edt, args->fh);
 
   epan_dissect_reset(&args->edt);
 
@@ -2932,7 +2714,7 @@ cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
   if (fh == NULL)
     return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
 
-  write_csv_preamble(fh);
+  write_csv_column_titles(&cf->cinfo, fh);
   if (ferror(fh)) {
     fclose(fh);
     return CF_PRINT_WRITE_ERROR;
@@ -2946,9 +2728,9 @@ cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
 
   /* Iterate through the list of packets, printing the packets we were
      told to print. */
-  ret = process_specified_packets(cf, &print_args->range, "Writing CSV",
+  ret = process_specified_records(cf, &print_args->range, "Writing CSV",
                                   "selected packets", TRUE,
-                                  write_csv_packet, fh);
+                                  write_csv_packet, &callback_args);
 
   epan_dissect_cleanup(&callback_args.edt);
 
@@ -2968,12 +2750,6 @@ cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
     return CF_PRINT_WRITE_ERROR;
   }
 
-  write_csv_finale(fh);
-  if (ferror(fh)) {
-    fclose(fh);
-    return CF_PRINT_WRITE_ERROR;
-  }
-
   /* XXX - check for an error */
   fclose(fh);
 
@@ -2981,14 +2757,14 @@ cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
 }
 
 static gboolean
-write_carrays_packet(capture_file *cf _U_, frame_data *fdata,
+carrays_write_packet(capture_file *cf, frame_data *fdata,
              struct wtap_pkthdr *phdr,
              const guint8 *pd, void *argsp)
 {
   write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
 
-  epan_dissect_run(&args->edt, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
-  proto_tree_write_carrays(fdata->num, args->fh, &args->edt);
+  epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
+  write_carrays_hex_data(fdata->num, args->fh, &args->edt);
   epan_dissect_reset(&args->edt);
 
   return !ferror(args->fh);
@@ -3006,8 +2782,6 @@ cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
   if (fh == NULL)
     return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
 
-  write_carrays_preamble(fh);
-
   if (ferror(fh)) {
     fclose(fh);
     return CF_PRINT_WRITE_ERROR;
@@ -3018,10 +2792,10 @@ cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
 
   /* Iterate through the list of packets, printing the packets we were
      told to print. */
-  ret = process_specified_packets(cf, &print_args->range,
+  ret = process_specified_records(cf, &print_args->range,
                   "Writing C Arrays",
                   "selected packets", TRUE,
-                                  write_carrays_packet, &callback_args);
+                                  carrays_write_packet, &callback_args);
 
   epan_dissect_cleanup(&callback_args.edt);
 
@@ -3038,13 +2812,6 @@ cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
     return CF_PRINT_WRITE_ERROR;
   }
 
-  write_carrays_finale(fh);
-
-  if (ferror(fh)) {
-    fclose(fh);
-    return CF_PRINT_WRITE_ERROR;
-  }
-
   fclose(fh);
   return CF_PRINT_OK;
 }
@@ -3079,7 +2846,7 @@ match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
   epan_dissect_t  edt;
 
   /* Load the frame's data. */
-  if (!cf_read_frame(cf, fdata)) {
+  if (!cf_read_record(cf, fdata)) {
     /* Attempt to get the packet failed. */
     return MR_ERROR;
   }
@@ -3087,7 +2854,7 @@ match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
   /* Construct the protocol tree, including the displayed text */
   epan_dissect_init(&edt, cf->epan, TRUE, TRUE);
   /* We don't need the column information */
-  epan_dissect_run(&edt, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
+  epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
 
   /* Iterate through all the nodes, seeing if they have text that matches. */
   mdata->cf = cf;
@@ -3138,7 +2905,7 @@ match_subtree_text(proto_node *node, gpointer data)
   for (i = 0; i < label_len; i++) {
     c_char = label_ptr[i];
     if (cf->case_type)
-      c_char = toupper(c_char);
+      c_char = g_ascii_toupper(c_char);
     if (c_char == string[c_match]) {
       c_match++;
       if (c_match == string_len) {
@@ -3183,7 +2950,7 @@ match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
   size_t          c_match    = 0;
 
   /* Load the frame's data. */
-  if (!cf_read_frame(cf, fdata)) {
+  if (!cf_read_record(cf, fdata)) {
     /* Attempt to get the packet failed. */
     return MR_ERROR;
   }
@@ -3191,19 +2958,19 @@ match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
   /* Don't bother constructing the protocol tree */
   epan_dissect_init(&edt, cf->epan, FALSE, FALSE);
   /* Get the column information */
-  epan_dissect_run(&edt, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata,
+  epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata,
                    &cf->cinfo);
 
   /* Find the Info column */
   for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
-    if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
+    if (cf->cinfo.columns[colx].fmt_matx[COL_INFO]) {
       /* Found it.  See if we match. */
-      info_column = edt.pi.cinfo->col_data[colx];
+      info_column = edt.pi.cinfo->columns[colx].col_data;
       info_column_len = strlen(info_column);
       for (i = 0; i < info_column_len; i++) {
         c_char = info_column[i];
         if (cf->case_type)
-          c_char = toupper(c_char);
+          c_char = g_ascii_toupper(c_char);
         if (c_char == string[c_match]) {
           c_match++;
           if (c_match == string_len) {
@@ -3281,19 +3048,19 @@ match_narrow_and_wide(capture_file *cf, frame_data *fdata, void *criterion)
   size_t        c_match    = 0;
 
   /* Load the frame's data. */
-  if (!cf_read_frame(cf, fdata)) {
+  if (!cf_read_record(cf, fdata)) {
     /* Attempt to get the packet failed. */
     return MR_ERROR;
   }
 
   result = MR_NOTMATCHED;
   buf_len = fdata->cap_len;
-  pd = buffer_start_ptr(&cf->buf);
+  pd = ws_buffer_start_ptr(&cf->buf);
   i = 0;
   while (i < buf_len) {
     c_char = pd[i];
     if (cf->case_type)
-      c_char = toupper(c_char);
+      c_char = g_ascii_toupper(c_char);
     if (c_char != '\0') {
       if (c_char == ascii_text[c_match]) {
         c_match += 1;
@@ -3329,19 +3096,19 @@ match_narrow(capture_file *cf, frame_data *fdata, void *criterion)
   size_t        c_match    = 0;
 
   /* Load the frame's data. */
-  if (!cf_read_frame(cf, fdata)) {
+  if (!cf_read_record(cf, fdata)) {
     /* Attempt to get the packet failed. */
     return MR_ERROR;
   }
 
   result = MR_NOTMATCHED;
   buf_len = fdata->cap_len;
-  pd = buffer_start_ptr(&cf->buf);
+  pd = ws_buffer_start_ptr(&cf->buf);
   i = 0;
   while (i < buf_len) {
     c_char = pd[i];
     if (cf->case_type)
-      c_char = toupper(c_char);
+      c_char = g_ascii_toupper(c_char);
     if (c_char == ascii_text[c_match]) {
       c_match += 1;
       if (c_match == textlen) {
@@ -3376,19 +3143,19 @@ match_wide(capture_file *cf, frame_data *fdata, void *criterion)
   size_t        c_match    = 0;
 
   /* Load the frame's data. */
-  if (!cf_read_frame(cf, fdata)) {
+  if (!cf_read_record(cf, fdata)) {
     /* Attempt to get the packet failed. */
     return MR_ERROR;
   }
 
   result = MR_NOTMATCHED;
   buf_len = fdata->cap_len;
-  pd = buffer_start_ptr(&cf->buf);
+  pd = ws_buffer_start_ptr(&cf->buf);
   i = 0;
   while (i < buf_len) {
     c_char = pd[i];
     if (cf->case_type)
-      c_char = toupper(c_char);
+      c_char = g_ascii_toupper(c_char);
     if (c_char == ascii_text[c_match]) {
       c_match += 1;
       if (c_match == textlen) {
@@ -3422,14 +3189,14 @@ match_binary(capture_file *cf, frame_data *fdata, void *criterion)
   size_t        c_match     = 0;
 
   /* Load the frame's data. */
-  if (!cf_read_frame(cf, fdata)) {
+  if (!cf_read_record(cf, fdata)) {
     /* Attempt to get the packet failed. */
     return MR_ERROR;
   }
 
   result = MR_NOTMATCHED;
   buf_len = fdata->cap_len;
-  pd = buffer_start_ptr(&cf->buf);
+  pd = ws_buffer_start_ptr(&cf->buf);
   i = 0;
   while (i < buf_len) {
     if (pd[i] == binary_data[c_match]) {
@@ -3465,7 +3232,7 @@ cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
   dfilter_t *sfcode;
   gboolean   result;
 
-  if (!dfilter_compile(filter, &sfcode)) {
+  if (!dfilter_compile(filter, &sfcode, NULL)) {
      /*
       * XXX - this shouldn't happen, as the filter string is machine
       * generated
@@ -3492,14 +3259,14 @@ match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
   match_result    result;
 
   /* Load the frame's data. */
-  if (!cf_read_frame(cf, fdata)) {
+  if (!cf_read_record(cf, fdata)) {
     /* Attempt to get the packet failed. */
     return MR_ERROR;
   }
 
   epan_dissect_init(&edt, cf->epan, TRUE, FALSE);
   epan_dissect_prime_dfilter(&edt, sfcode);
-  epan_dissect_run(&edt, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
+  epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
   result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
   epan_dissect_cleanup(&edt);
   return result;
@@ -3539,7 +3306,6 @@ find_packet(capture_file *cf,
   frame_data  *fdata;
   frame_data  *new_fd = NULL;
   progdlg_t   *progbar = NULL;
-  gboolean     stop_flag;
   int          count;
   gboolean     found;
   float        progbar_val;
@@ -3566,7 +3332,7 @@ find_packet(capture_file *cf,
     /* Progress so far. */
     progbar_val = 0.0f;
 
-    stop_flag = FALSE;
+    cf->stop_flag = FALSE;
     g_get_current_time(&start_time);
 
     title = cf->sfilter?cf->sfilter:"";
@@ -3578,7 +3344,7 @@ find_packet(capture_file *cf,
          time in order to get to the next progress bar step). */
       if (progbar == NULL)
          progbar = delayed_create_progress_dlg(cf->window, "Searching", title,
-           FALSE, &stop_flag, &start_time, progbar_val);
+           FALSE, &cf->stop_flag, &start_time, progbar_val);
 
       /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
          when we update it, we have to run the GTK+ main loop to get it
@@ -3602,7 +3368,7 @@ find_packet(capture_file *cf,
         progbar_nextstep += progbar_quantum;
       }
 
-      if (stop_flag) {
+      if (cf->stop_flag) {
         /* Well, the user decided to abort the search.  Go back to the
            frame where we started. */
         new_fd = start_fd;
@@ -3694,7 +3460,7 @@ find_packet(capture_file *cf,
          so we can't select it. */
       simple_message_box(ESD_TYPE_INFO, NULL,
                          "The capture file is probably not fully dissected.",
-                         "End of capture exceeded!");
+                         "End of capture exceeded.");
       return FALSE;
     }
     return TRUE;    /* success */
@@ -3727,7 +3493,7 @@ cf_goto_frame(capture_file *cf, guint fnumber)
        so we can't select it. */
     simple_message_box(ESD_TYPE_INFO, NULL,
                        "The capture file is probably not fully dissected.",
-                       "End of capture exceeded!");
+                       "End of capture exceeded.");
     return FALSE;
   }
   return TRUE;  /* we got to that packet */
@@ -3818,7 +3584,7 @@ cf_select_packet(capture_file *cf, int row)
   }
 
   /* Get the data in that frame. */
-  if (!cf_read_frame (cf, fdata)) {
+  if (!cf_read_record (cf, fdata)) {
     return;
   }
 
@@ -3832,7 +3598,7 @@ cf_select_packet(capture_file *cf, int row)
   cf->edt = epan_dissect_new(cf->epan, TRUE, TRUE);
 
   tap_build_interesting(cf->edt);
-  epan_dissect_run(cf->edt, &cf->phdr, frame_tvbuff_new_buffer(cf->current_frame, &cf->buf),
+  epan_dissect_run(cf->edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(cf->current_frame, &cf->buf),
                    cf->current_frame, NULL);
 
   dfilter_macro_build_ftv_cache(cf->edt->tree);
@@ -3934,39 +3700,26 @@ cf_unignore_frame(capture_file *cf, frame_data *frame)
 const gchar *
 cf_read_shb_comment(capture_file *cf)
 {
-  wtapng_section_t *shb_inf;
-  const gchar      *temp_str;
-
   /* Get info from SHB */
-  shb_inf = wtap_file_get_shb_info(cf->wth);
-  if (shb_inf == NULL)
-        return NULL;
-  temp_str = shb_inf->opt_comment;
-  g_free(shb_inf);
-
-  return temp_str;
-
+  return wtap_file_get_shb_comment(cf->wth);
 }
 
 void
 cf_update_capture_comment(capture_file *cf, gchar *comment)
 {
-  wtapng_section_t *shb_inf;
+  const gchar *shb_comment;
 
   /* Get info from SHB */
-  shb_inf = wtap_file_get_shb_info(cf->wth);
+  shb_comment = wtap_file_get_shb_comment(cf->wth);
 
   /* See if the comment has changed or not */
-  if (shb_inf && shb_inf->opt_comment) {
-    if (strcmp(shb_inf->opt_comment, comment) == 0) {
+  if (shb_comment) {
+    if (strcmp(shb_comment, comment) == 0) {
       g_free(comment);
-      g_free(shb_inf);
       return;
     }
   }
 
-  g_free(shb_inf);
-
   /* The comment has changed, let's update it */
   wtap_write_shb_comment(cf->wth, comment);
   /* Mark the file as having unsaved changes */
@@ -3986,6 +3739,8 @@ cf_get_user_packet_comment(capture_file *cf, const frame_data *fd)
 char *
 cf_get_comment(capture_file *cf, const frame_data *fd)
 {
+  char *comment;
+
   /* fetch user comment */
   if (fd->flags.has_user_comment)
     return g_strdup(cf_get_user_packet_comment(cf, fd));
@@ -3995,14 +3750,16 @@ cf_get_comment(capture_file *cf, const frame_data *fd)
     struct wtap_pkthdr phdr; /* Packet header */
     Buffer buf; /* Packet data */
 
-    phdr.opt_comment = NULL;
+    wtap_phdr_init(&phdr);
+    ws_buffer_init(&buf, 1500);
 
-    buffer_init(&buf, 1500);
-    if (!cf_read_frame_r(cf, fd, &phdr, &buf))
+    if (!cf_read_record_r(cf, fd, &phdr, &buf))
       { /* XXX, what we can do here? */ }
 
-    buffer_free(&buf);
-    return phdr.opt_comment;
+    comment = phdr.opt_comment;
+    wtap_phdr_cleanup(&phdr);
+    ws_buffer_free(&buf);
+    return comment;
   }
   return NULL;
 }
@@ -4066,6 +3823,50 @@ cf_comment_types(capture_file *cf)
   return comment_types;
 }
 
+#ifdef WANT_PACKET_EDITOR
+static gint
+g_direct_compare_func(gconstpointer a, gconstpointer b, gpointer user_data _U_)
+{
+  if (a > b)
+    return 1;
+  else if (a < b)
+    return -1;
+  else
+    return 0;
+}
+
+static void
+modified_frame_data_free(gpointer data)
+{
+  modified_frame_data *mfd = (modified_frame_data *)data;
+
+  g_free(mfd->pd);
+  g_free(mfd);
+}
+
+/*
+ * Give a frame new, edited data.
+ */
+void
+cf_set_frame_edited(capture_file *cf, frame_data *fd,
+                    struct wtap_pkthdr *phdr, guint8 *pd)
+{
+  modified_frame_data *mfd = (modified_frame_data *)g_malloc(sizeof(modified_frame_data));
+
+  mfd->phdr = *phdr;
+  mfd->pd = pd;
+
+  if (cf->edited_frames == NULL)
+    cf->edited_frames = g_tree_new_full(g_direct_compare_func, NULL, NULL,
+                                        modified_frame_data_free);
+  g_tree_insert(cf->edited_frames, GINT_TO_POINTER(fd->num), mfd);
+  fd->file_off = -1;
+
+  /* Mark the file as having unsaved changes */
+  cf->unsaved_changes = TRUE;
+}
+#endif
+
 typedef struct {
   wtap_dumper *pdh;
   const char  *fname;
@@ -4080,13 +3881,14 @@ typedef struct {
  * up a message box for the failure.
  */
 static gboolean
-save_packet(capture_file *cf _U_, frame_data *fdata,
+save_record(capture_file *cf, frame_data *fdata,
             struct wtap_pkthdr *phdr, const guint8 *pd,
             void *argsp)
 {
   save_callback_args_t *args = (save_callback_args_t *)argsp;
   struct wtap_pkthdr    hdr;
   int           err;
+  gchar        *err_info;
   gchar        *display_basename;
   const char   *pkt_comment;
 
@@ -4108,6 +3910,7 @@ save_packet(capture_file *cf _U_, frame_data *fdata,
 
      For WTAP_HAS_PACK_FLAGS, we currently don't save the FCS length
      from the packet flags. */
+  hdr.rec_type = phdr->rec_type;
   hdr.presence_flags = 0;
   if (fdata->flags.has_ts)
     hdr.presence_flags |= WTAP_HAS_TS;
@@ -4117,8 +3920,8 @@ save_packet(capture_file *cf _U_, frame_data *fdata,
     hdr.presence_flags |= WTAP_HAS_PACK_FLAGS;
   hdr.ts.secs      = fdata->abs_ts.secs;
   hdr.ts.nsecs     = fdata->abs_ts.nsecs;
-  hdr.caplen       = fdata->cap_len;
-  hdr.len          = fdata->pkt_len;
+  hdr.caplen       = phdr->caplen;
+  hdr.len          = phdr->len;
   hdr.pkt_encap    = fdata->lnk_t;
   /* pcapng */
   hdr.interface_id = phdr->interface_id;   /* identifier of the interface. */
@@ -4133,21 +3936,57 @@ save_packet(capture_file *cf _U_, frame_data *fdata,
   hdr.pack_flags   =     /* XXX - 0 for now (any value for "we don't have it"?) */
 #endif
   /* and save the packet */
-  if (!wtap_dump(args->pdh, &hdr, pd, &err)) {
+  if (!wtap_dump(args->pdh, &hdr, pd, &err, &err_info)) {
     if (err < 0) {
       /* Wiretap error. */
       switch (err) {
 
-      case WTAP_ERR_UNSUPPORTED_ENCAP:
+      case WTAP_ERR_UNWRITABLE_ENCAP:
         /*
-         * This is a problem with the particular frame we're writing;
-         * note that, and give the frame number.
+         * 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.
          */
         simple_error_message_box(
                       "Frame %u has a network type that can't be saved in a \"%s\" file.",
                       fdata->num, wtap_file_type_subtype_string(args->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.
+         */
+        simple_error_message_box(
+                      "Frame %u is larger than Wireshark supports in a \"%s\" file.",
+                      fdata->num, wtap_file_type_subtype_string(args->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.
+         */
+        simple_error_message_box(
+                      "Record %u has a record type that can't be saved in a \"%s\" file.",
+                      fdata->num, wtap_file_type_subtype_string(args->file_type));
+        break;
+
+      case WTAP_ERR_UNWRITABLE_REC_DATA:
+        /*
+         * 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.
+         */
+        simple_error_message_box(
+                      "Record %u has data that can't be saved in a \"%s\" file.\n(%s)",
+                      fdata->num, wtap_file_type_subtype_string(args->file_type),
+                      err_info != NULL ? err_info : "no information supplied");
+        g_free(err_info);
+        break;
+
       default:
         display_basename = g_filename_display_basename(args->fname);
         simple_error_message_box(
@@ -4269,7 +4108,7 @@ cf_has_unsaved_data(capture_file *cf)
    * If this is a temporary file, or a file with unsaved changes, it
    * has unsaved data.
    */
-  return cf->is_tempfile || cf->unsaved_changes;
+  return (cf->is_tempfile && cf->count>0) || cf->unsaved_changes;
 }
 
 /*
@@ -4282,9 +4121,7 @@ rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
   gchar               *err_info;
   gchar               *name_ptr;
   gint64               data_offset;
-  gint64               file_pos;
   progdlg_t           *progbar        = NULL;
-  gboolean             stop_flag;
   gint64               size;
   float                progbar_val;
   GTimeVal             start_time;
@@ -4302,7 +4139,12 @@ rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
   wtap_close(cf->wth);
 
   /* Open the new file. */
-  cf->wth = wtap_open_offline(fname, err, &err_info, TRUE);
+  /* XXX: this will go through all open_routines for a matching one. But right
+     now rescan_file() is only used when a file is being saved to a different
+     format than the original, and the user is not given a choice of which
+     reader to use (only which format to save it in), so doing this makes
+     sense for now. */
+  cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, err, &err_info, TRUE);
   if (cf->wth == NULL) {
     cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
     return CF_READ_ERROR;
@@ -4356,7 +4198,7 @@ rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
   }else
     progbar_quantum = 0;
 
-  stop_flag = FALSE;
+  cf->stop_flag = FALSE;
   g_get_current_time(&start_time);
 
   framenum = 0;
@@ -4367,15 +4209,15 @@ rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
     fdata->file_off = data_offset;
     if (size >= 0) {
       count++;
-      file_pos = wtap_read_so_far(cf->wth);
+      cf->f_datalen = wtap_read_so_far(cf->wth);
 
       /* Create the progress bar if necessary.
        * Check whether it should be created or not every MIN_NUMBER_OF_PACKET
        */
       if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)) {
-        progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
+        progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
         progbar = delayed_create_progress_dlg(cf->window, "Rescanning", name_ptr,
-                                              TRUE, &stop_flag, &start_time, progbar_val);
+                                              TRUE, &cf->stop_flag, &start_time, progbar_val);
       }
 
       /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
@@ -4383,9 +4225,9 @@ rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
          to repaint what's pending, and doing so may involve an "ioctl()"
          to see if there's any pending input from an X server, and doing
          that for every packet can be costly, especially on a big file. */
-      if (file_pos >= progbar_nextstep) {
+      if (cf->f_datalen >= progbar_nextstep) {
         if (progbar != NULL) {
-          progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
+          progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
           /* update the packet bar content on the first run or frequently on very large files */
 #ifdef HAVE_LIBPCAP
           if (progbar_quantum > 500000 || displayed_once == 0) {
@@ -4401,7 +4243,7 @@ rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
       }
     }
 
-    if (stop_flag) {
+    if (cf->stop_flag) {
       /* Well, the user decided to abort the rescan.  Sadly, as this
          isn't a reread, recovering is difficult, so we'll just
          close the current capture. */
@@ -4441,7 +4283,7 @@ rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
 
   cf_callback_invoke(cf_cb_file_rescan_finished, cf);
 
-  if (stop_flag) {
+  if (cf->stop_flag) {
     /* Our caller will give up at this point. */
     return CF_READ_ABORTED;
   }
@@ -4455,23 +4297,10 @@ rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
     case WTAP_ERR_UNSUPPORTED:
       simple_error_message_box(
                  "The capture file contains record data that Wireshark doesn't support.\n(%s)",
-                 err_info);
-      g_free(err_info);
-      break;
-
-    case WTAP_ERR_UNSUPPORTED_ENCAP:
-      simple_error_message_box(
-                 "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
-                 err_info);
+                 err_info != NULL ? err_info : "no information supplied");
       g_free(err_info);
       break;
 
-    case WTAP_ERR_CANT_READ:
-      simple_error_message_box(
-                 "An attempt to read from the capture file failed for"
-                 " some unknown reason.");
-      break;
-
     case WTAP_ERR_SHORT_READ:
       simple_error_message_box(
                  "The capture file appears to have been cut short"
@@ -4481,14 +4310,15 @@ rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
     case WTAP_ERR_BAD_FILE:
       simple_error_message_box(
                  "The capture file appears to be damaged or corrupt.\n(%s)",
-                 err_info);
+                 err_info != NULL ? err_info : "no information supplied");
       g_free(err_info);
       break;
 
     case WTAP_ERR_DECOMPRESS:
       simple_error_message_box(
                  "The compressed capture file appears to be damaged or corrupt.\n"
-                 "(%s)", err_info);
+                 "(%s)",
+                 err_info != NULL ? err_info : "no information supplied");
       g_free(err_info);
       break;
 
@@ -4504,7 +4334,7 @@ rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
 }
 
 cf_write_status_t
-cf_save_packets(capture_file *cf, const char *fname, guint save_format,
+cf_save_records(capture_file *cf, const char *fname, guint save_format,
                 gboolean compressed, gboolean discard_comments,
                 gboolean dont_reopen)
 {
@@ -4611,12 +4441,15 @@ cf_save_packets(capture_file *cf, const char *fname, guint save_format,
        or moving the capture file, we have to do it by writing the packets
        out in Wiretap. */
 
-    wtapng_section_t *shb_hdr = NULL;
+    wtapng_section_t            *shb_hdr = NULL;
     wtapng_iface_descriptions_t *idb_inf = NULL;
+    wtapng_name_res_t           *nrb_hdr = NULL;
     int encap;
 
-    shb_hdr = wtap_file_get_shb_info(cf->wth);
+    /* XXX: what free's this shb_hdr? */
+    shb_hdr = wtap_file_get_shb_for_new_file(cf->wth);
     idb_inf = wtap_file_get_idb_info(cf->wth);
+    nrb_hdr = wtap_file_get_nrb_for_new_file(cf->wth);
 
     /* Determine what file encapsulation type we should use. */
     encap = wtap_dump_file_encap_type(cf->linktypes);
@@ -4631,10 +4464,10 @@ cf_save_packets(capture_file *cf, const char *fname, guint save_format,
          from which we're reading the packets that we're writing!) */
       fname_new = g_strdup_printf("%s~", fname);
       pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
-                              compressed, shb_hdr, idb_inf, &err);
+                              compressed, shb_hdr, idb_inf, nrb_hdr, &err);
     } else {
       pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
-                              compressed, shb_hdr, idb_inf, &err);
+                              compressed, shb_hdr, idb_inf, nrb_hdr, &err);
     }
     g_free(idb_inf);
     idb_inf = NULL;
@@ -4651,8 +4484,8 @@ cf_save_packets(capture_file *cf, const char *fname, guint save_format,
     callback_args.pdh = pdh;
     callback_args.fname = fname;
     callback_args.file_type = save_format;
-    switch (process_specified_packets(cf, NULL, "Saving", "packets",
-                                      TRUE, save_packet, &callback_args)) {
+    switch (process_specified_records(cf, NULL, "Saving", "packets",
+                                      TRUE, save_record, &callback_args)) {
 
     case PSP_FINISHED:
       /* Completed successfully. */
@@ -4736,7 +4569,11 @@ cf_save_packets(capture_file *cf, const char *fname, guint save_format,
          the wtap structure, the filename, and the "is temporary"
          status applies to the new file; just update that. */
       wtap_close(cf->wth);
-      cf->wth = wtap_open_offline(fname, &err, &err_info, TRUE);
+      /* Although we're just "copying" and then opening the copy, it will
+         try all open_routine readers to open the copy, so we need to
+         reset the cfile's open_type. */
+      cf->open_type = WTAP_TYPE_AUTO;
+      cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
       if (cf->wth == NULL) {
         cf_open_failure_alert_box(fname, err, err_info, FALSE, 0);
         cf_close(cf);
@@ -4767,6 +4604,9 @@ cf_save_packets(capture_file *cf, const char *fname, guint save_format,
          ...as long as, for gzipped files, the process of writing
          out the file *also* generates the information needed to
          support fast random access to the compressed file. */
+      /* rescan_file will cause us to try all open_routines, so
+         reset cfile's open_type */
+      cf->open_type = WTAP_TYPE_AUTO;
       if (rescan_file(cf, fname, FALSE, &err) != CF_READ_OK) {
         /* The rescan failed; just close the file.  Either
            a dialog was popped up for the failure, so the
@@ -4824,8 +4664,9 @@ cf_export_specified_packets(capture_file *cf, const char *fname,
   int                          err;
   wtap_dumper                 *pdh;
   save_callback_args_t         callback_args;
-  wtapng_section_t            *shb_hdr;
-  wtapng_iface_descriptions_t *idb_inf;
+  wtapng_section_t            *shb_hdr = NULL;
+  wtapng_iface_descriptions_t *idb_inf = NULL;
+  wtapng_name_res_t           *nrb_hdr = NULL;
   int                          encap;
 
   cf_callback_invoke(cf_cb_file_export_specified_packets_started, (gpointer)fname);
@@ -4837,8 +4678,10 @@ cf_export_specified_packets(capture_file *cf, const char *fname,
      written, don't special-case the operation - read each packet
      and then write it out if it's one of the specified ones. */
 
-  shb_hdr = wtap_file_get_shb_info(cf->wth);
+  /* XXX: what free's this shb_hdr? */
+  shb_hdr = wtap_file_get_shb_for_new_file(cf->wth);
   idb_inf = wtap_file_get_idb_info(cf->wth);
+  nrb_hdr = wtap_file_get_nrb_for_new_file(cf->wth);
 
   /* Determine what file encapsulation type we should use. */
   encap = wtap_dump_file_encap_type(cf->linktypes);
@@ -4853,10 +4696,10 @@ cf_export_specified_packets(capture_file *cf, const char *fname,
        from which we're reading the packets that we're writing!) */
     fname_new = g_strdup_printf("%s~", fname);
     pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
-                            compressed, shb_hdr, idb_inf, &err);
+                            compressed, shb_hdr, idb_inf, nrb_hdr, &err);
   } else {
     pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
-                            compressed, shb_hdr, idb_inf, &err);
+                            compressed, shb_hdr, idb_inf, nrb_hdr, &err);
   }
   g_free(idb_inf);
   idb_inf = NULL;
@@ -4873,14 +4716,14 @@ cf_export_specified_packets(capture_file *cf, const char *fname,
      told to process.
 
      XXX - we've already called "packet_range_process_init(range)", but
-     "process_specified_packets()" will do it again.  Fortunately,
+     "process_specified_records()" will do it again.  Fortunately,
      that's harmless in this case, as we haven't done anything to
      "range" since we initialized it. */
   callback_args.pdh = pdh;
   callback_args.fname = fname;
   callback_args.file_type = save_format;
-  switch (process_specified_packets(cf, range, "Writing", "specified packets",
-                                    TRUE, save_packet, &callback_args)) {
+  switch (process_specified_records(cf, range, "Writing", "specified records",
+                                    TRUE, save_record, &callback_args)) {
 
   case PSP_FINISHED:
     /* Completed successfully. */
@@ -4976,9 +4819,10 @@ cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
     case WTAP_ERR_UNSUPPORTED:
       /* Seen only when opening a capture file for reading. */
       simple_error_message_box(
-            "The file \"%s\" isn't a capture file in a format Wireshark understands.\n"
+            "The file \"%s\" contains record data that Wireshark doesn't support.\n"
             "(%s)",
-            display_basename, err_info);
+            display_basename,
+            err_info != NULL ? err_info : "no information supplied");
       g_free(err_info);
       break;
 
@@ -4990,22 +4834,15 @@ cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
             display_basename, wtap_file_type_subtype_string(file_type));
       break;
 
-    case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
+    case WTAP_ERR_UNWRITABLE_FILE_TYPE:
       /* Seen only when opening a capture file for writing. */
       simple_error_message_box(
             "Wireshark doesn't support writing capture files in that format.");
       break;
 
-    case WTAP_ERR_UNSUPPORTED_ENCAP:
-      if (for_writing) {
-        simple_error_message_box("Wireshark can't save this capture in that format.");
-      } else {
-        simple_error_message_box(
-              "The file \"%s\" is a capture for a network type that Wireshark doesn't support.\n"
-              "(%s)",
-              display_basename, err_info);
-        g_free(err_info);
-      }
+    case WTAP_ERR_UNWRITABLE_ENCAP:
+      /* Seen only when opening a capture file for writing. */
+      simple_error_message_box("Wireshark can't save this capture in that format.");
       break;
 
     case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
@@ -5024,7 +4861,8 @@ cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
       simple_error_message_box(
             "The file \"%s\" appears to be damaged or corrupt.\n"
             "(%s)",
-            display_basename, err_info);
+            display_basename,
+            err_info != NULL ? err_info : "no information supplied");
       g_free(err_info);
       break;
 
@@ -5061,7 +4899,8 @@ cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
     case WTAP_ERR_DECOMPRESS:
       simple_error_message_box(
             "The compressed file \"%s\" appears to be damaged or corrupt.\n"
-            "(%s)", display_basename, err_info);
+            "(%s)", display_basename,
+            err_info != NULL ? err_info : "no information supplied");
       g_free(err_info);
       break;
 
@@ -5178,7 +5017,7 @@ cf_reload(capture_file *cf) {
   filename = g_strdup(cf->filename);
   is_tempfile = cf->is_tempfile;
   cf->is_tempfile = FALSE;
-  if (cf_open(cf, filename, is_tempfile, &err) == CF_OK) {
+  if (cf_open(cf, filename, cf->open_type, is_tempfile, &err) == CF_OK) {
     switch (cf_read(cf, TRUE)) {
 
     case CF_READ_OK: