packet-smb2: fix getting the dataoffset in dissect_smb2_write_request()
[metze/wireshark/wip.git] / file.c
diff --git a/file.c b/file.c
index 819660cf61b793ea71876a429054d61b14f7b37f..01ed0d4fda124fcae23cb715d8966c1be7f172ff 100644 (file)
--- a/file.c
+++ b/file.c
@@ -20,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>
@@ -33,7 +33,6 @@
 #include <string.h>
 #include <ctype.h>
 #include <errno.h>
-#include <signal.h>
 
 #ifdef HAVE_FCNTL_H
 #include <fcntl.h>
 gboolean auto_scroll_live;
 #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);
 
@@ -197,14 +194,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;
@@ -219,46 +216,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++) {
@@ -346,9 +309,12 @@ cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_temp
      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().)
@@ -439,22 +405,21 @@ 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)
 {
+  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;
@@ -473,8 +438,11 @@ cf_reset_state(capture_file *cf)
   /* 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;
@@ -503,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();
@@ -516,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
@@ -588,7 +546,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. */
@@ -705,9 +663,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"
+                   "More information and 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!");
+                   "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
@@ -771,7 +729,7 @@ cf_read(capture_file *cf, gboolean reloading)
                   "\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;
   }
 
@@ -784,23 +742,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);
+                 err_info != NULL ? err_info : "no information supplied");
       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);
-      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"
@@ -810,14 +755,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",
+                 err_info != NULL ? err_info : "no information supplied");
       g_free(err_info);
       break;
 
@@ -848,7 +793,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. */
@@ -891,9 +836,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"
+                   "More information and 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!");
+                   "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;
@@ -941,10 +886,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;
@@ -971,7 +920,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. */
@@ -1046,10 +995,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;
@@ -1295,7 +1248,7 @@ cf_merge_files(char **out_filenamep, int in_file_count,
   int              out_fd;
   wtap_dumper     *pdh;
   int              open_err, read_err, write_err, close_err;
-  gchar           *err_info;
+  gchar           *err_info, *write_err_info = NULL;
   int              err_fileno;
   int              i;
   gboolean         got_read_error     = FALSE, got_write_error = FALSE;
@@ -1376,7 +1329,7 @@ cf_merge_files(char **out_filenamep, int in_file_count,
                                           /*  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   */
+    shb_hdr->shb_user_appl = g_strdup("Wireshark"); /* NULL if not available, UTF-8 string containing the name   */
                                           /*  of the application used to create this section.          */
 
     /* create fake IDB info */
@@ -1538,7 +1491,7 @@ cf_merge_files(char **out_filenamep, int in_file_count,
       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)) {
+                   wtap_buf_ptr(in_file->wth), &write_err, &write_err_info)) {
       got_write_error = TRUE;
       break;
     }
@@ -1573,19 +1526,6 @@ cf_merge_files(char **out_filenamep, int in_file_count,
         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;
-
         case WTAP_ERR_SHORT_READ:
           simple_error_message_box(
                      "The capture file %s appears to have been cut short"
@@ -1602,7 +1542,8 @@ cf_merge_files(char **out_filenamep, int in_file_count,
         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);
+                     "(%s)", display_basename,
+                     err_info != NULL ? err_info : "no information supplied");
           g_free(err_info);
           break;
 
@@ -1624,7 +1565,7 @@ cf_merge_files(char **out_filenamep, int in_file_count,
       /* Wiretap error. */
       switch (write_err) {
 
-      case WTAP_ERR_UNSUPPORTED_ENCAP:
+      case WTAP_ERR_UNWRITABLE_ENCAP:
         /*
          * This is a problem with the particular frame we're writing and
          * the file type and subtype we're writing; note that, and report
@@ -1652,6 +1593,36 @@ cf_merge_files(char **out_filenamep, int in_file_count,
         g_free(display_basename);
         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.
+         */
+        display_basename = g_filename_display_basename(in_file ? in_file->filename : "UNKNOWN");
+        simple_error_message_box(
+                      "Record %u of \"%s\" has a record type that can't be saved in a \"%s\" file.",
+                      in_file ? in_file->packet_num : 0, display_basename,
+                      wtap_file_type_subtype_string(file_type));
+        g_free(display_basename);
+        break;
+
+      case WTAP_ERR_UNWRITABLE_REC_DATA:
+        /*
+         * This is a problem with the particular record we're writing and
+         * the file type and subtype we're writing; note that, and report
+         * the frame number and file type/subtype.
+         */
+        display_basename = g_filename_display_basename(in_file ? in_file->filename : "UNKNOWN");
+        simple_error_message_box(
+                      "Record %u of \"%s\" has data that can't be saved in a \"%s\" file.\n(%s)",
+                      in_file ? in_file->packet_num : 0, display_basename,
+                      wtap_file_type_subtype_string(file_type),
+                      write_err_info != NULL ? write_err_info : "no information supplied");
+        g_free(write_err_info);
+        g_free(display_basename);
+        break;
+
       default:
         display_basename = g_filename_display_basename(out_filename);
         simple_error_message_box(
@@ -1681,6 +1652,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 */
@@ -1700,12 +1672,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;
     }
@@ -1766,13 +1739,13 @@ cf_read_record_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
@@ -1781,15 +1754,10 @@ cf_read_record_r(capture_file *cf, const frame_data *fdata,
     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;
 
@@ -1853,7 +1821,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. */
@@ -2017,7 +1985,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
@@ -2130,7 +2098,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.");
       }
     }
   }
@@ -2209,7 +2177,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;
@@ -2251,8 +2219,8 @@ process_specified_records(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;
@@ -2337,7 +2305,7 @@ process_specified_records(capture_file *cf, packet_range_t *range,
       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;
@@ -2349,7 +2317,8 @@ process_specified_records(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;
 }
@@ -2554,7 +2523,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). */
@@ -2785,7 +2754,7 @@ write_pdml_packet(capture_file *cf, frame_data *fdata,
   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);
 
@@ -2855,12 +2824,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, 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);
 
@@ -2880,7 +2850,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;
@@ -2941,8 +2911,8 @@ write_csv_packet(capture_file *cf, frame_data *fdata,
   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);
 
@@ -2961,7 +2931,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;
@@ -2997,12 +2967,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);
 
@@ -3010,14 +2974,14 @@ cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
 }
 
 static gboolean
-write_carrays_packet(capture_file *cf, 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, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
-  proto_tree_write_carrays(fdata->num, args->fh, &args->edt);
+  write_carrays_hex_data(fdata->num, args->fh, &args->edt);
   epan_dissect_reset(&args->edt);
 
   return !ferror(args->fh);
@@ -3035,8 +2999,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;
@@ -3050,7 +3012,7 @@ cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
   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);
 
@@ -3067,13 +3029,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;
 }
@@ -3317,7 +3272,7 @@ match_narrow_and_wide(capture_file *cf, frame_data *fdata, void *criterion)
 
   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];
@@ -3365,7 +3320,7 @@ match_narrow(capture_file *cf, frame_data *fdata, void *criterion)
 
   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];
@@ -3412,7 +3367,7 @@ match_wide(capture_file *cf, frame_data *fdata, void *criterion)
 
   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];
@@ -3458,7 +3413,7 @@ match_binary(capture_file *cf, frame_data *fdata, void *criterion)
 
   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]) {
@@ -3494,7 +3449,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
@@ -3723,7 +3678,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 */
@@ -3756,7 +3711,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 */
@@ -4015,6 +3970,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));
@@ -4024,14 +3981,16 @@ cf_get_comment(capture_file *cf, const frame_data *fd)
     struct wtap_pkthdr phdr; /* Packet header */
     Buffer buf; /* Packet data */
 
-    memset(&phdr, 0, sizeof(struct wtap_pkthdr));
+    wtap_phdr_init(&phdr);
+    ws_buffer_init(&buf, 1500);
 
-    buffer_init(&buf, 1500);
     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;
 }
@@ -4095,6 +4054,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;
@@ -4109,13 +4112,14 @@ typedef struct {
  * up a message box for the failure.
  */
 static gboolean
-save_record(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;
 
@@ -4163,12 +4167,12 @@ save_record(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 and
          * the file type and subtype we're writing; note that, and report
@@ -4190,6 +4194,30 @@ save_record(capture_file *cf _U_, frame_data *fdata,
                       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(
@@ -4502,23 +4530,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"
@@ -4528,14 +4543,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;
 
@@ -5030,9 +5046,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;
 
@@ -5044,22 +5061,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:
@@ -5078,7 +5088,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;
 
@@ -5115,7 +5126,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;