Try to fix some of the build problems, it still bumms out on:
[obnox/wireshark/wip.git] / file.c
diff --git a/file.c b/file.c
index 50c499e126d6e50d6827becfeba70cd22b844ef5..68e7336985eb3589f15fb834edf5e048a83b3d93 100644 (file)
--- a/file.c
+++ b/file.c
 #include "fileset.h"
 #include "tempfile.h"
 #include "merge.h"
-#include "alert_box.h"
-#include "simple_dialog.h"
-#include "main_statusbar.h"
-#include "progress_dlg.h"
-#include "ui_util.h"
+
 #include <epan/prefs.h>
 #include <epan/dfilter/dfilter.h>
 #include <epan/epan_dissect.h>
 #include <epan/strutil.h>
 #include <epan/addr_resolv.h>
 
+#include "ui/alert_box.h"
+#include "ui/simple_dialog.h"
+#include "ui/main_statusbar.h"
+#include "ui/progress_dlg.h"
+#include "ui/ui_util.h"
+
 #ifdef HAVE_LIBPCAP
 gboolean auto_scroll_live;
 #endif
@@ -126,7 +128,6 @@ static void cf_open_failure_alert_box(const char *filename, int err,
                       gchar *err_info, gboolean for_writing,
                       int file_type);
 static const char *file_rename_error_message(int err);
-static void cf_write_failure_alert_box(const char *filename, int err);
 static void cf_close_failure_alert_box(const char *filename, int err);
 static void ref_time_packets(capture_file *cf);
 /* Update the progress bar this many times when reading a file. */
@@ -135,11 +136,6 @@ static void ref_time_packets(capture_file *cf);
 #define MIN_QUANTUM         200000
 #define MIN_NUMBER_OF_PACKET 1500
 
-/* Number of "frame_data" structures per memory chunk.
-   XXX - is this the right number? */
-#define FRAME_DATA_CHUNK_SIZE   1024
-
-
 /*
  * We could probably use g_signal_...() instead of the callbacks below but that
  * would require linking our CLI programs to libgobject and creating an object
@@ -289,7 +285,7 @@ cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
 
   /* The open succeeded.  Close whatever capture file we had open,
      and fill in the information for this file. */
-  cf_reset_state(cf);
+  cf_close(cf);
 
   /* Cleanup all data structures used for dissection. */
   cleanup_dissection();
@@ -331,24 +327,15 @@ cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
   } else
     cf->has_snap = TRUE;
 
+  /* Allocate a frame_data_sequence for the frames in this file */
+  cf->frames = new_frame_data_sequence();
+
   nstime_set_zero(&cf->elapsed_time);
   nstime_set_unset(&first_ts);
   nstime_set_unset(&prev_dis_ts);
   nstime_set_unset(&prev_cap_ts);
   cum_bytes = 0;
 
-#if GLIB_CHECK_VERSION(2,10,0)
-#else
-  /* memory chunks have been deprecated in favor of the slice allocator,
-   * which has been added in 2.10
-   */
-  cf->plist_chunk = g_mem_chunk_new("frame_data_chunk",
-    sizeof(frame_data),
-    FRAME_DATA_CHUNK_SIZE * sizeof(frame_data),
-    G_ALLOC_AND_FREE);
-  g_assert(cf->plist_chunk);
-#endif
-
   /* Adjust timestamp precision if auto is selected, col width will be adjusted */
   cf_timestamp_auto_precision(cf);
   /* XXX needed ? */
@@ -399,28 +386,25 @@ cf_reset_state(capture_file *cf)
   /* ...which means we have nothing to save. */
   cf->user_saved = FALSE;
 
-#if GLIB_CHECK_VERSION(2,10,0)
-  if (cf->plist_start != NULL)
-    g_slice_free_chain(frame_data, cf->plist_start, next);
-#else
-  /* memory chunks have been deprecated in favor of the slice allocator,
-   * which has been added in 2.10
-   */
-  if (cf->plist_chunk != NULL) {
-    g_mem_chunk_destroy(cf->plist_chunk);
-    cf->plist_chunk = NULL;
-  }
-#endif
   dfilter_free(cf->rfcode);
   cf->rfcode = NULL;
-  cf->plist_start = NULL;
-  cf->plist_end = NULL;
+  if (cf->frames != NULL) {
+    free_frame_data_sequence(cf->frames);
+    cf->frames = NULL;
+  }
+#ifdef WANT_PACKET_EDITOR
+  if (cf->edited_frames) {
+    g_tree_destroy(cf->edited_frames);
+    cf->edited_frames = NULL;
+  }
+#endif
   cf_unselect_packet(cf);   /* nothing to select */
-  cf->first_displayed = NULL;
-  cf->last_displayed = NULL;
+  cf->first_displayed = 0;
+  cf->last_displayed = 0;
 
-  /* No frame selected, no field in that frame selected. */
-  cf->current_frame = NULL;
+  /* No frames, no frame selected, no field in that frame selected. */
+  cf->count = 0;
+  cf->current_frame = 0;
   cf->current_row = 0;
   cf->finfo_selected = NULL;
 
@@ -430,7 +414,6 @@ cf_reset_state(capture_file *cf)
   new_packet_list_thaw();
 
   cf->f_datalen = 0;
-  cf->count = 0;
   nstime_set_zero(&cf->elapsed_time);
 
   reset_tap_listeners();
@@ -478,17 +461,6 @@ calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_s
      */
     size = wtap_file_size(cf->wth, NULL);
 
-    /*  Another possibility is that we're reading a compressed file and we've
-     *  read more (uncompressed) data from the file than exists in the
-     *  (compressed) file.  So check how much data we've actually read.
-     *
-     *  This is inside this "if val > 1.0" check to avoid the lseek() when
-     *  reading uncompressed files.  Testing has (thus far) shown no progress
-     *  bar weirdness resulting from switching from the data offset (when
-     *  reading the first part of the file) to the real file position.
-     */
-    file_pos = wtap_read_so_far(cf->wth, NULL);
-
     if (size >= 0)
       progbar_val = (gfloat) file_pos / (gfloat) size;
 
@@ -502,8 +474,8 @@ calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_s
   }
 
   g_snprintf(status_str, status_size,
-            "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
-            file_pos / 1024, size / 1024);
+             "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
+             file_pos / 1024, size / 1024);
 
   return progbar_val;
 }
@@ -517,6 +489,7 @@ cf_read(capture_file *cf, gboolean from_save)
   const char  *errmsg;
   char         errmsg_errno[1024+1];
   gint64       data_offset;
+  gint64       file_pos;
   progdlg_t *volatile progbar = NULL;
   gboolean     stop_flag;
   volatile gint64 size;
@@ -572,6 +545,7 @@ cf_read(capture_file *cf, gboolean from_save)
   /* Progress so far. */
   progbar_val = 0.0f;
 
+  /* The packet list window will be empty untill the file is completly loaded */
   new_packet_list_freeze();
 
   stop_flag = FALSE;
@@ -580,11 +554,13 @@ cf_read(capture_file *cf, gboolean from_save)
   while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
     if (size >= 0) {
       count++;
+      file_pos = 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, data_offset, status_str, sizeof(status_str));
+        progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
         if (from_save == FALSE)
           progbar = delayed_create_progress_dlg("Loading", name_ptr,
                                                 TRUE, &stop_flag, &start_time, progbar_val);
@@ -598,19 +574,15 @@ cf_read(capture_file *cf, gboolean from_save)
          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) {
+      if (file_pos >= progbar_nextstep) {
         if (progbar != NULL) {
-          progbar_val = calc_progbar_val(cf, size, data_offset, status_str, sizeof(status_str));
-          /* update the packet lists content on the first run or frequently on very large files */
-          /* (on smaller files the display update takes longer than reading the file) */
+          progbar_val = calc_progbar_val(cf, size, file_pos, 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) {
-            if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->plist_end != NULL) {
+            if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->count != 0) {
               displayed_once = 1;
-              new_packet_list_thaw();
-              if (auto_scroll_live)
-                new_packet_list_moveto_end();
-              new_packet_list_freeze();
+              packets_bar_update();
             }
           }
 #endif /* HAVE_LIBPCAP */
@@ -683,7 +655,7 @@ cf_read(capture_file *cf, gboolean from_save)
      WTAP_ENCAP_PER_PACKET). */
   cf->lnk_t = wtap_file_encap(cf->wth);
 
-  cf->current_frame = cf->first_displayed;
+  cf->current_frame = frame_data_sequence_find(cf->frames, cf->first_displayed);
   cf->current_row = 0;
 
   new_packet_list_thaw();
@@ -694,7 +666,7 @@ cf_read(capture_file *cf, gboolean from_save)
 
   /* If we have any displayed packets to select, select the first of those
      packets by making the first row the selected row. */
-  if (cf->first_displayed != NULL){
+  if (cf->first_displayed != 0){
     new_packet_list_select_first_row();
   }
 
@@ -734,7 +706,7 @@ cf_read(capture_file *cf, gboolean from_save)
         " in the middle of a packet.";
       break;
 
-    case WTAP_ERR_BAD_RECORD:
+    case WTAP_ERR_BAD_FILE:
       g_snprintf(errmsg_errno, sizeof(errmsg_errno),
                  "The capture file appears to be damaged or corrupt.\n(%s)",
                  err_info);
@@ -869,7 +841,7 @@ cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
 
   /* moving to the end of the packet list - if the user requested so and
      we have some new packets. */
-  if (newly_displayed_packets && auto_scroll_live && cf->plist_end != NULL)
+  if (newly_displayed_packets && auto_scroll_live && cf->count != 0)
       new_packet_list_moveto_end();
 
   if (cf->state == FILE_READ_ABORTED) {
@@ -955,7 +927,7 @@ cf_finish_tail(capture_file *cf, int *err)
     return CF_READ_ABORTED;
   }
 
-  if (auto_scroll_live && cf->plist_end != NULL)
+  if (auto_scroll_live && cf->count != 0)
     new_packet_list_moveto_end();
 
   /* We're done reading sequentially through the file. */
@@ -1163,27 +1135,17 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
        We thus need to leave behind bread crumbs so that
        "cf_select_packet()" can find this frame.  See the comment
        in "cf_select_packet()". */
-    if (cf->first_displayed == NULL)
-      cf->first_displayed = fdata;
+    if (cf->first_displayed == 0)
+      cf->first_displayed = fdata->num;
 
     /* This is the last frame we've seen so far. */
-    cf->last_displayed = fdata;
+    cf->last_displayed = fdata->num;
   }
 
   epan_dissect_cleanup(&edt);
   return row;
 }
 
-/*
- * Initialize the col_text and col_text_len arrays.
- */
-static void
-init_col_text(frame_data *fdata, gint num_cols)
-{
-  fdata->col_text_len = se_alloc0(sizeof(*fdata->col_text_len) * num_cols);
-  fdata->col_text = se_alloc0(sizeof(*fdata->col_text) * num_cols);
-}
-
 /* read in a new packet */
 /* returns the row of the new packet in the packet list or -1 if not displayed */
 static int
@@ -1193,65 +1155,40 @@ read_packet(capture_file *cf, dfilter_t *dfcode,
   const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
   union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
   const guchar *buf = wtap_buf_ptr(cf->wth);
+  frame_data    fdlocal;
+  guint32       framenum;
   frame_data   *fdata;
   int           passed;
   int           row = -1;
 
-  cf->count++;
-
-  /* Allocate the next list entry, and add it to the list.
-   * memory chunks have been deprecated in favor of the slice allocator,
-   * which has been added in 2.10
-   */
-#if GLIB_CHECK_VERSION(2,10,0)
-  fdata = g_slice_new(frame_data);
-#else
-  fdata = g_mem_chunk_alloc(cf->plist_chunk);
-#endif
+  /* The frame number of this packet is one more than the count of
+     frames in this packet. */
+  framenum = cf->count + 1;
 
-  frame_data_init(fdata, cf->count, phdr, offset, cum_bytes);
-  init_col_text(fdata, cf->cinfo.num_cols);
+  frame_data_init(&fdlocal, framenum, phdr, offset, cum_bytes);
 
   passed = TRUE;
   if (cf->rfcode) {
     epan_dissect_t edt;
     epan_dissect_init(&edt, TRUE, FALSE);
     epan_dissect_prime_dfilter(&edt, cf->rfcode);
-    epan_dissect_run(&edt, pseudo_header, buf, fdata, NULL);
+    epan_dissect_run(&edt, pseudo_header, buf, &fdlocal, NULL);
     passed = dfilter_apply_edt(cf->rfcode, &edt);
     epan_dissect_cleanup(&edt);
   }
 
   if (passed) {
-    cap_file_add_fdata(cf, fdata);
+    /* This does a shallow copy of fdlocal, which is good enough. */
+    fdata = frame_data_sequence_add(cf->frames, &fdlocal);
 
-    cf->f_datalen = offset + fdata->cap_len;
+    cf->count++;
+    cf->f_datalen = offset + fdlocal.cap_len;
 
     if (!cf->redissecting) {
       row = add_packet_to_packet_list(fdata, cf, dfcode,
                                       filtering_tap_listeners, tap_flags,
                                       pseudo_header, buf, TRUE, TRUE);
     }
-  } else {
-    /* We didn't pass read filter so roll back count */
-    cf->count--;
-
-    /* XXX - if we didn't have read filters, or if we could avoid
-       allocating the "frame_data" structure until we knew whether
-       the frame passed the read filter, we could use a G_ALLOC_ONLY
-       memory chunk...
-
-       ...but, at least in one test I did, where I just made the chunk
-       a G_ALLOC_ONLY chunk and read in a huge capture file, it didn't
-       seem to save a noticeable amount of time or space. */
-#if GLIB_CHECK_VERSION(2,10,0)
-  /* memory chunks have been deprecated in favor of the slice allocator,
-   * which has been added in 2.10
-   */
-    g_slice_free(frame_data,fdata);
-#else
-    g_mem_chunk_free(cf->plist_chunk, fdata);
-#endif
   }
 
   return row;
@@ -1261,8 +1198,7 @@ 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;
-  wtap             *wth;
+  merge_in_file_t  *in_files, *in_file;
   char             *out_filename;
   char             *tmpname;
   int               out_fd;
@@ -1345,14 +1281,19 @@ cf_merge_files(char **out_filenamep, int in_file_count,
   /* do the merge (or append) */
   for (;;) {
     if (do_append)
-      wth = merge_append_read_packet(in_file_count, in_files, &read_err,
-                                     &err_info);
+      in_file = merge_append_read_packet(in_file_count, in_files, &read_err,
+                                         &err_info);
     else
-      wth = merge_read_packet(in_file_count, in_files, &read_err,
-                              &err_info);
-    if (wth == NULL) {
-      if (read_err != 0)
-        got_read_error = TRUE;
+      in_file = merge_read_packet(in_file_count, in_files, &read_err,
+                                  &err_info);
+    if (in_file == NULL) {
+      /* EOF */
+      break;
+    }
+
+    if (read_err != 0) {
+      /* I/O error reading from in_file */
+      got_read_error = TRUE;
       break;
     }
 
@@ -1380,7 +1321,7 @@ cf_merge_files(char **out_filenamep, int in_file_count,
         /* Get the sum of the seek positions in all of the files. */
         file_pos = 0;
         for (i = 0; i < in_file_count; i++)
-          file_pos += wtap_read_so_far(in_files[i].wth, NULL);
+          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.
@@ -1402,8 +1343,8 @@ cf_merge_files(char **out_filenamep, int in_file_count,
       break;
     }
 
-    if (!wtap_dump(pdh, wtap_phdr(wth), wtap_pseudoheader(wth),
-         wtap_buf_ptr(wth), &write_err)) {
+    if (!wtap_dump(pdh, wtap_phdr(in_file->wth), wtap_pseudoheader(in_file->wth),
+         wtap_buf_ptr(in_file->wth), &write_err)) {
       got_write_error = TRUE;
       break;
     }
@@ -1426,51 +1367,51 @@ cf_merge_files(char **out_filenamep, int in_file_count,
      */
     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. */
-    switch (read_err) {
-
-    case WTAP_ERR_UNSUPPORTED_ENCAP:
-      g_snprintf(errmsg_errno, sizeof(errmsg_errno),
-           "The capture file %%s has a packet with a network type that Wireshark doesn't support.\n(%s)",
-           err_info);
-      g_free(err_info);
-      errmsg = errmsg_errno;
-      break;
+        /* Put up a message box noting that a read failed somewhere along
+           the line. */
+        switch (read_err) {
+
+        case WTAP_ERR_UNSUPPORTED_ENCAP:
+          g_snprintf(errmsg_errno, sizeof(errmsg_errno),
+                     "The capture file %%s has a packet with a network type that Wireshark doesn't support.\n(%s)",
+                     err_info);
+          g_free(err_info);
+          errmsg = errmsg_errno;
+          break;
 
-    case WTAP_ERR_CANT_READ:
-      errmsg = "An attempt to read from the capture file %s failed for"
-           " some unknown reason.";
-      break;
+        case WTAP_ERR_CANT_READ:
+          errmsg = "An attempt to read from the capture file %s failed for"
+                   " some unknown reason.";
+          break;
 
-    case WTAP_ERR_SHORT_READ:
-      errmsg = "The capture file %s appears to have been cut short"
-           " in the middle of a packet.";
-      break;
+        case WTAP_ERR_SHORT_READ:
+          errmsg = "The capture file %s appears to have been cut short"
+                   " in the middle of a packet.";
+          break;
 
-    case WTAP_ERR_BAD_RECORD:
-      g_snprintf(errmsg_errno, sizeof(errmsg_errno),
-           "The capture file %%s appears to be damaged or corrupt.\n(%s)",
-           err_info);
-      g_free(err_info);
-      errmsg = errmsg_errno;
-      break;
+        case WTAP_ERR_BAD_FILE:
+          g_snprintf(errmsg_errno, sizeof(errmsg_errno),
+                     "The capture file %%s appears to be damaged or corrupt.\n(%s)",
+                     err_info);
+          g_free(err_info);
+          errmsg = errmsg_errno;
+          break;
 
-    case WTAP_ERR_DECOMPRESS:
-      g_snprintf(errmsg_errno, sizeof(errmsg_errno),
-                 "The compressed capture file %%s appears to be damaged or corrupt.\n"
-                 "(%s)", err_info);
-      g_free(err_info);
-      errmsg = errmsg_errno;
-      break;
+        case WTAP_ERR_DECOMPRESS:
+          g_snprintf(errmsg_errno, sizeof(errmsg_errno),
+                     "The compressed capture file %%s appears to be damaged or corrupt.\n"
+                     "(%s)", err_info);
+          g_free(err_info);
+          errmsg = errmsg_errno;
+          break;
 
-    default:
-      g_snprintf(errmsg_errno, sizeof(errmsg_errno),
-           "An error occurred while reading the"
-           " capture file %%s: %s.", wtap_strerror(read_err));
-      errmsg = errmsg_errno;
-      break;
-    }
+        default:
+          g_snprintf(errmsg_errno, sizeof(errmsg_errno),
+                     "An error occurred while reading the"
+                     " capture file %%s: %s.", wtap_strerror(read_err));
+          errmsg = errmsg_errno;
+          break;
+        }
         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, errmsg, in_files[i].filename);
       }
     }
@@ -1478,7 +1419,31 @@ cf_merge_files(char **out_filenamep, int in_file_count,
 
   if (got_write_error) {
     /* Put up an alert box for the write error. */
-    cf_write_failure_alert_box(out_filename, write_err);
+    if (write_err < 0) {
+      /* Wiretap error. */
+      switch (write_err) {
+
+      case WTAP_ERR_UNSUPPORTED_ENCAP:
+        /*
+         * This is a problem with the particular frame we're writing;
+         * note that, and give the frame number.
+         */
+        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+                      "Frame %u of \"%s\" has a network type that can't be saved in a \"%s\" file.",
+                      in_file->packet_num, in_file->filename,
+                      wtap_file_type_string(file_type));
+        break;
+
+      default:
+        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+                      "An error occurred while writing to the file \"%s\": %s.",
+                      out_filename, wtap_strerror(write_err));
+        break;
+      }
+    } else {
+      /* OS error. */
+      write_failure_alert_box(out_filename, write_err);
+    }
   }
 
   if (got_read_error || got_write_error || stop_flag) {
@@ -1582,6 +1547,22 @@ cf_read_frame_r(capture_file *cf, frame_data *fdata,
   gchar *err_info;
   char errmsg_errno[1024+1];
 
+#ifdef WANT_PACKET_EDITOR
+  /* if fdata->file_off == -1 it means packet was edited, and we must find data inside edited_frames tree */
+  if (G_UNLIKELY(fdata->file_off == -1)) {
+    const modified_frame_data *frame = (const modified_frame_data *) g_tree_lookup(cf->edited_frames, GINT_TO_POINTER(fdata->num));
+
+    if (!frame) {
+      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "fdata->file_off == -1, but can't find modified frame!");
+      return FALSE;
+    }
+
+    *pseudo_header = frame->ph;
+    memcpy(pd, frame->pd, fdata->cap_len);
+    return TRUE;
+  }
+#endif
+
   if (!wtap_seek_read(cf->wth, fdata->file_off, pseudo_header, pd,
                       fdata->cap_len, &err, &err_info)) {
     switch (err) {
@@ -1593,7 +1574,7 @@ cf_read_frame_r(capture_file *cf, frame_data *fdata,
       g_free(err_info);
       break;
 
-    case WTAP_ERR_BAD_RECORD:
+    case WTAP_ERR_BAD_FILE:
       g_snprintf(errmsg_errno, sizeof(errmsg_errno),
                  "An error occurred while reading from the file \"%%s\": %s.\n(%s)",
                  wtap_strerror(err), err_info);
@@ -1636,7 +1617,8 @@ static void
 rescan_packets(capture_file *cf, const char *action, const char *action_item,
         gboolean refilter, gboolean redissect)
 {
-    /* Rescan packets new packet list */
+  /* Rescan packets new packet list */
+  guint32     framenum;
   frame_data *fdata;
   progdlg_t  *progbar = NULL;
   gboolean    stop_flag;
@@ -1704,8 +1686,8 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
   }
 
   /* We don't yet know which will be the first and last frames displayed. */
-  cf->first_displayed = NULL;
-  cf->last_displayed = NULL;
+  cf->first_displayed = 0;
+  cf->last_displayed = 0;
 
   /* We currently don't display any packets */
   cf->displayed_count = 0;
@@ -1742,7 +1724,9 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
 
   selected_frame_seen = FALSE;
 
-  for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
+  for (framenum = 1; framenum <= cf->count; framenum++) {
+    fdata = frame_data_sequence_find(cf->frames, framenum);
+
     /* 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
@@ -1799,12 +1783,6 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
        * "init_dissection()"), and null out the GSList pointer. */
       fdata->flags.visited = 0;
       frame_data_cleanup(fdata);
-
-      /* cleanup_dissection() calls se_free_all();
-       * And after that fdata->col_text (which is allocated using se_alloc0())
-       * no longer points to valid memory.
-       */
-      init_col_text(fdata, cf->cinfo.num_cols);
     }
 
     if (!cf_read_frame(cf, fdata))
@@ -1855,7 +1833,8 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
        even though the user requested that the scan stop, and that
        would leave the user stuck with an Wireshark grinding on
        until it finishes.  Should we just stick them with that? */
-    for (; fdata != NULL; fdata = fdata->next) {
+    for (; framenum <= cf->count; framenum++) {
+      fdata = frame_data_sequence_find(cf->frames, framenum);
       fdata->flags.visited = 0;
       frame_data_cleanup(fdata);
     }
@@ -1948,13 +1927,16 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
 static void
 ref_time_packets(capture_file *cf)
 {
+  guint32 framenum;
   frame_data *fdata;
 
   nstime_set_unset(&first_ts);
   nstime_set_unset(&prev_dis_ts);
   cum_bytes = 0;
 
-  for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
+  for (framenum = 1; framenum <= cf->count; framenum++) {
+    fdata = frame_data_sequence_find(cf->frames, framenum);
+
     /* just add some value here until we know if it is being displayed or not */
     fdata->cum_bytes = cum_bytes + fdata->pkt_len;
 
@@ -1993,11 +1975,12 @@ ref_time_packets(capture_file *cf)
         cf->elapsed_time = fdata->rel_ts;
     }
 
-    /* Get the time elapsed between the previous displayed packet and
-     this packet. */
-    nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts);
-
-    prev_dis_ts = fdata->abs_ts;
+    /* If this frame is displayed, get the time elapsed between the 
+     previous displayed packet and this packet. */ 
+    if( fdata->flags.passed_dfilter ) {
+        nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts);
+        prev_dis_ts = fdata->abs_ts;
+    }
 
     /*
      * Byte counts
@@ -2031,6 +2014,7 @@ process_specified_packets(capture_file *cf, packet_range_t *range,
                          union wtap_pseudo_header *, const guint8 *, void *),
     void *callback_args)
 {
+  guint32 framenum;
   frame_data *fdata;
   union wtap_pseudo_header pseudo_header;
   guint8      pd[WTAP_MAX_PACKET_SIZE+1];
@@ -2061,9 +2045,11 @@ process_specified_packets(capture_file *cf, packet_range_t *range,
 
   packet_range_process_init(range);
 
-  /* Iterate through the list of packets, printing the packets that
+  /* Iterate through all the packets, printing the packets that
      were selected by the current display filter.  */
-  for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
+  for (framenum = 1; framenum <= cf->count; framenum++) {
+    fdata = frame_data_sequence_find(cf->frames, framenum);
+
     /* 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
@@ -2528,7 +2514,7 @@ cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
   if (fh == NULL)
     return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
 
-  write_pdml_preamble(fh);
+  write_pdml_preamble(fh, cf->filename);
   if (ferror(fh)) {
     fclose(fh);
     return CF_PRINT_WRITE_ERROR;
@@ -2720,12 +2706,17 @@ cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
 
 static gboolean
 write_carrays_packet(capture_file *cf _U_, frame_data *fdata,
-             union wtap_pseudo_header *pseudo_header _U_,
+             union wtap_pseudo_header *pseudo_header,
              const guint8 *pd, void *argsp)
 {
   FILE *fh = argsp;
+  epan_dissect_t edt;
+
+  epan_dissect_init(&edt, TRUE, TRUE);
+  epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
+  proto_tree_write_carrays(fdata->num, fh, &edt);
+  epan_dissect_cleanup(&edt);
 
-  proto_tree_write_carrays(pd, fdata->cap_len, fdata->num, fh);
   return !ferror(fh);
 }
 
@@ -2797,7 +2788,7 @@ cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree,  match_data *md
   mdata->cf = cf;
   /* Iterate through all the nodes looking for matching text */
   proto_tree_children_foreach(tree, match_subtree_text, mdata);
-  return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED; 
+  return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
 }
 
 static match_result
@@ -3002,22 +2993,28 @@ match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
 
   result = MR_NOTMATCHED;
   buf_len = fdata->pkt_len;
-  for (i = 0; i < buf_len; i++) {
+  i = 0;
+  while (i < buf_len) {
     c_char = cf->pd[i];
     if (cf->case_type)
       c_char = toupper(c_char);
-    if (c_char != 0) {
+    if (c_char != '\0') {
       if (c_char == ascii_text[c_match]) {
-        c_match++;
+        c_match += 1;
         if (c_match == textlen) {
           result = MR_MATCHED;
           cf->search_pos = i; /* Save the position of the last character
                                  for highlighting the field. */
           break;
         }
-      } else
+      }
+      else {
+        g_assert(i>=c_match);
+        i -= (guint32)c_match;
         c_match = 0;
+      }
     }
+    i += 1;
   }
   return result;
 }
@@ -3042,21 +3039,28 @@ match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
 
   result = MR_NOTMATCHED;
   buf_len = fdata->pkt_len;
-  for (i = 0; i < buf_len; i++) {
+  i = 0;
+  while (i < buf_len) {
     c_char = cf->pd[i];
     if (cf->case_type)
       c_char = toupper(c_char);
     if (c_char == ascii_text[c_match]) {
-      c_match++;
+      c_match += 1;
       if (c_match == textlen) {
         result = MR_MATCHED;
         cf->search_pos = i; /* Save the position of the last character
                                for highlighting the field. */
         break;
       }
-    } else
+    }
+    else {
+      g_assert(i>=c_match);
+      i -= (guint32)c_match;
       c_match = 0;
+    }
+    i += 1;
   }
+
   return result;
 }
 
@@ -3080,21 +3084,27 @@ match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
 
   result = MR_NOTMATCHED;
   buf_len = fdata->pkt_len;
-  for (i = 0; i < buf_len; i++) {
+  i = 0;
+  while (i < buf_len) {
     c_char = cf->pd[i];
     if (cf->case_type)
       c_char = toupper(c_char);
     if (c_char == ascii_text[c_match]) {
-      c_match++;
-      i++;
+      c_match += 1;
       if (c_match == textlen) {
         result = MR_MATCHED;
         cf->search_pos = i; /* Save the position of the last character
                                for highlighting the field. */
         break;
       }
-    } else
+      i += 1;
+    }
+    else {
+      g_assert(i>=(c_match*2));
+      i -= (guint32)c_match*2;
       c_match = 0;
+    }
+    i += 1;
   }
   return result;
 }
@@ -3118,17 +3128,23 @@ match_binary(capture_file *cf, frame_data *fdata, void *criterion)
 
   result = MR_NOTMATCHED;
   buf_len = fdata->pkt_len;
-  for (i = 0; i < buf_len; i++) {
+  i = 0;
+  while (i < buf_len) {
     if (cf->pd[i] == binary_data[c_match]) {
-      c_match++;
+      c_match += 1;
       if (c_match == datalen) {
         result = MR_MATCHED;
         cf->search_pos = i; /* Save the position of the last character
                                for highlighting the field. */
         break;
       }
-    } else
+    }
+    else {
+      g_assert(i>=c_match);
+      i -= (guint32)c_match;
       c_match = 0;
+    }
+    i += 1;
   }
   return result;
 }
@@ -3217,6 +3233,7 @@ find_packet(capture_file *cf,
             void *criterion, search_direction dir)
 {
   frame_data  *start_fd;
+  guint32      framenum;
   frame_data  *fdata;
   frame_data  *new_fd = NULL;
   progdlg_t   *progbar = NULL;
@@ -3237,7 +3254,7 @@ find_packet(capture_file *cf,
        picked, calling a routine to run the filter on the packet, see if
        it matches, and stop if so.  */
     count = 0;
-    fdata = start_fd;
+    framenum = start_fd->num;
 
     /* Update the progress bar when it gets to this value. */
     progbar_nextstep = 0;
@@ -3293,8 +3310,7 @@ find_packet(capture_file *cf,
       /* Go past the current frame. */
       if (dir == SD_BACKWARD) {
         /* Go on to the previous frame. */
-        fdata = fdata->prev;
-        if (fdata == NULL) {
+        if (framenum == 1) {
           /*
            * XXX - other apps have a bit more of a detailed message
            * for this, and instead of offering "OK" and "Cancel",
@@ -3306,30 +3322,32 @@ find_packet(capture_file *cf,
           if (prefs.gui_find_wrap)
           {
               statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
-              fdata = cf->plist_end;    /* wrap around */
+              framenum = cf->count;     /* wrap around */
           }
           else
           {
               statusbar_push_temporary_msg("Search reached the beginning.");
-              fdata = start_fd;        /* stay on previous packet */
+              framenum = start_fd->num; /* stay on previous packet */
           }
-        }
+        } else
+          framenum--;
       } else {
         /* Go on to the next frame. */
-        fdata = fdata->next;
-        if (fdata == NULL) {
+        if (framenum == cf->count) {
           if (prefs.gui_find_wrap)
           {
               statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
-              fdata = cf->plist_start;    /* wrap around */
+              framenum = 1;             /* wrap around */
           }
           else
           {
               statusbar_push_temporary_msg("Search reached the end.");
-              fdata = start_fd;     /* stay on previous packet */
+              framenum = start_fd->num; /* stay on previous packet */
           }
-        }
+        } else
+          framenum++;
       }
+      fdata = frame_data_sequence_find(cf->frames, framenum);
 
       count++;
 
@@ -3388,8 +3406,7 @@ cf_goto_frame(capture_file *cf, guint fnumber)
 {
   frame_data *fdata;
 
-  for (fdata = cf->plist_start; fdata != NULL && fdata->num < fnumber; fdata = fdata->next)
-    ;
+  fdata = frame_data_sequence_find(cf->frames, fnumber);
 
   if (fdata == NULL) {
     /* we didn't find a packet with that packet number */
@@ -3417,7 +3434,7 @@ cf_goto_frame(capture_file *cf, guint fnumber)
 }
 
 gboolean
-cf_goto_top_frame()
+cf_goto_top_frame(void)
 {
   /* Find and select */
   new_packet_list_select_first_row();
@@ -3425,7 +3442,7 @@ cf_goto_top_frame()
 }
 
 gboolean
-cf_goto_bottom_frame()
+cf_goto_bottom_frame(void)
 {
   /* Find and select */
   new_packet_list_select_last_row();
@@ -3466,7 +3483,7 @@ cf_select_packet(capture_file *cf, int row)
   if (fdata == NULL) {
     /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
        the first entry is added to it by "real_insert_row()", that row
-       is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
+       is selected (see "real_insert_row()", in "ui/gtk/gtkclist.c", in both
        our version and the vanilla GTK+ version).
 
        This means that a "select-row" signal is emitted; this causes
@@ -3491,7 +3508,7 @@ cf_select_packet(capture_file *cf, int row)
        GtkCList; see the comment in "add_packet_to_packet_list()". */
 
        if (row == 0 && cf->first_displayed == cf->last_displayed)
-         fdata = cf->first_displayed;
+         fdata = frame_data_sequence_find(cf->frames, cf->first_displayed);
   }
 
   /* If fdata _still_ isn't set simply give up. */
@@ -3608,6 +3625,7 @@ cf_unignore_frame(capture_file *cf, frame_data *frame)
 typedef struct {
   wtap_dumper *pdh;
   const char  *fname;
+  int          file_type;
 } save_callback_args_t;
 
 /*
@@ -3635,7 +3653,30 @@ save_packet(capture_file *cf _U_, frame_data *fdata,
 
   /* and save the packet */
   if (!wtap_dump(args->pdh, &hdr, pseudo_header, pd, &err)) {
-    cf_write_failure_alert_box(args->fname, err);
+    if (err < 0) {
+      /* Wiretap error. */
+      switch (err) {
+
+      case WTAP_ERR_UNSUPPORTED_ENCAP:
+        /*
+         * This is a problem with the particular frame we're writing;
+         * note that, and give the frame number.
+         */
+        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+                      "Frame %u has a network type that can't be saved in a \"%s\" file.",
+                      fdata->num, wtap_file_type_string(args->file_type));
+        break;
+
+      default:
+        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+                      "An error occurred while writing to the file \"%s\": %s.",
+                      args->fname, wtap_strerror(err));
+        break;
+      }
+    } else {
+      /* OS error. */
+      write_failure_alert_box(args->fname, err);
+    }
     return FALSE;
   }
   return TRUE;
@@ -3732,7 +3773,7 @@ cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_f
     if (do_copy) {
       /* Copy the file, if we haven't moved it. */
       if (!copy_file_binary_mode(from_filename, fname))
-    goto fail;
+        goto fail;
     }
   } else {
     /* Either we're filtering packets, or we're saving in a different
@@ -3760,6 +3801,7 @@ cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_f
        "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, "Saving", "selected packets",
                                       TRUE, save_packet, &callback_args)) {
 
@@ -3904,7 +3946,7 @@ cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
       }
       break;
 
-    case WTAP_ERR_BAD_RECORD:
+    case WTAP_ERR_BAD_FILE:
       /* Seen only when opening a capture file for reading. */
       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
             "The file \"%s\" appears to be damaged or corrupt.\n"
@@ -3990,20 +4032,6 @@ file_rename_error_message(int err)
   return errmsg;
 }
 
-static void
-cf_write_failure_alert_box(const char *filename, int err)
-{
-  if (err < 0) {
-    /* Wiretap error. */
-    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-          "An error occurred while writing to the file \"%s\": %s.",
-          filename, wtap_strerror(err));
-  } else {
-    /* OS error. */
-    write_failure_alert_box(filename, err);
-  }
-}
-
 /* Check for write errors - if the file is being written to an NFS server,
    a write error may not show up until the file is closed, as NFS clients
    might not send writes to the server until the "write()" call finishes,
@@ -4101,6 +4129,6 @@ cf_reload(capture_file *cf) {
  * indent-tabs-mode: nil
  * End:
  *
- * ex: set shiftwidth=2 tabstop=8 expandtab
+ * ex: set shiftwidth=2 tabstop=8 expandtab:
  * :indentSize=2:tabSize=8:noTabs=true:
  */