From Graeme Hewson:
authorgerald <gerald@f5534014-38df-0310-8fa8-9805f1628bb7>
Sun, 22 Sep 2002 16:17:41 +0000 (16:17 +0000)
committergerald <gerald@f5534014-38df-0310-8fa8-9805f1628bb7>
Sun, 22 Sep 2002 16:17:41 +0000 (16:17 +0000)
  It can sometimes happen that capturing is stopped just after Ethereal
  has switched to a new ring buffer.  The result is that no frames
  are displayed.  The patch to ringbuffer.c displays the previous ring
  buffer if the current buffer is empty on close.

  The patch to capture.c fixes a bug where an error return from
  ringbuf_wtap_dump_close was ignored, and tidies up the code around
  the call.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@6315 f5534014-38df-0310-8fa8-9805f1628bb7

capture.c
ringbuffer.c

index a645d650449e4db744f7380e2ec08e456fc10795..67db8c33bbf8224cc6baa4945af5eb63e939ad0c 100644 (file)
--- a/capture.c
+++ b/capture.c
@@ -1,7 +1,7 @@
 /* capture.c
  * Routines for packet capture windows
  *
- * $Id: capture.c,v 1.190 2002/09/09 20:38:56 guy Exp $
+ * $Id: capture.c,v 1.191 2002/09/22 16:17:41 gerald Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -1367,7 +1367,8 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
   unsigned int i;
   static const char capstart_msg = SP_CAPSTART;
   char        errmsg[4096+1];
-  gboolean    dump_ok;
+  gboolean    write_ok;
+  gboolean    close_ok;
   fd_set      set1;
   struct timeval timeout;
   struct {
@@ -1900,31 +1901,29 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
       popup_errmsg(errmsg);
 #endif
 
-  if (ld.err != 0) {
+  if (ld.err == 0)
+    write_ok = TRUE;
+  else {
     get_capture_file_io_error(errmsg, sizeof(errmsg), cfile.save_file, ld.err,
                              FALSE);
     popup_errmsg(errmsg);
+    write_ok = FALSE;
+  }
 
-    /* A write failed, so we've already told the user there's a problem;
-       if the close fails, there's no point in telling them about that
-       as well. */
-    if (capture_opts.ringbuffer_on) {
-      ringbuf_wtap_dump_close(&cfile, &err);
-    } else {
-      wtap_dump_close(ld.pdh, &err);
-    }
-   } else {
-    if (capture_opts.ringbuffer_on) {
-      dump_ok = ringbuf_wtap_dump_close(&cfile, &err);
-    } else {
-      dump_ok = wtap_dump_close(ld.pdh, &err);
-    }
-    if (!dump_ok) {
-      get_capture_file_io_error(errmsg, sizeof(errmsg), cfile.save_file, err,
-                               TRUE);
-      popup_errmsg(errmsg);
-    }
+  if (capture_opts.ringbuffer_on) {
+    close_ok = ringbuf_wtap_dump_close(&cfile, &err);
+  } else {
+    close_ok = wtap_dump_close(ld.pdh, &err);
+  }
+  /* If we've displayed a message about a write error, there's no point
+     in displaying another message about an error on close. */
+  if (!close_ok && write_ok) {
+    get_capture_file_io_error(errmsg, sizeof(errmsg), cfile.save_file, err,
+               TRUE);
+    popup_errmsg(errmsg);
   }
+  /* Set write_ok to mean the write and the close were successful. */
+  write_ok = (write_ok && close_ok);
 
 #ifndef _WIN32
   /*
@@ -1967,7 +1966,7 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
   gtk_grab_remove(GTK_WIDGET(cap_w));
   gtk_widget_destroy(GTK_WIDGET(cap_w));
 
-  return TRUE;
+  return write_ok;
 
 error:
   if (capture_opts.ringbuffer_on) {
index 922d9b12ae86ea21a9ea6f5418f4f18ac0284c43..cb69c8d805a2f418031ac3cb757e79b50056bc13 100644 (file)
@@ -1,7 +1,7 @@
 /* ringbuffer.c
  * Routines for packet capture windows
  *
- * $Id: ringbuffer.c,v 1.5 2002/08/28 21:00:41 jmayer Exp $
+ * $Id: ringbuffer.c,v 1.6 2002/09/22 16:17:41 gerald Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -292,7 +292,10 @@ gboolean
 ringbuf_wtap_dump_close(capture_file *cf, int *err)
 {
   gboolean     ret_val;
+  gboolean     data_captured = TRUE;
   unsigned int i;
+  long         curr_pos;
+  long         curr_file_curr_pos = 0;  /* Initialise to avoid GCC warning */
   gchar       *new_name;
   char         filenum[5+1];
   char         timestr[14+1];
@@ -304,22 +307,43 @@ ringbuf_wtap_dump_close(capture_file *cf, int *err)
   for (i=0; i<rb_data.num_files; i++) {
     fh = wtap_dump_file(rb_data.files[i].pdh);
     clearerr(fh);
-    /* Flush the file */
-    errno = WTAP_ERR_CANT_CLOSE;
-    if (fflush(fh) == EOF) {
+
+    /* Get the current file position */
+    if ((curr_pos = ftell(fh)) < 0) {
       if (err != NULL) {
         *err = errno;
       }
       ret_val = FALSE;
       /* If the file's not a new one, remove it as it hasn't been truncated
          and thus contains garbage at the end.
-
-         We don't remove it if it's new - it's incomplete, but at least
-         the stuff before the incomplete record is usable. */
+         If the file is a new one, it contains only the dump header, so
+         remove it too. */
       close(rb_data.files[i].fd);
-      if (!rb_data.files[i].is_new) {
-        unlink(rb_data.files[i].name);
+      unlink(rb_data.files[i].name);
+      /* Set name for caller's error message */
+      cf->save_file = rb_data.files[i].name;
+      continue;
+    }
+
+    if (i == rb_data.curr_file_num)
+      curr_file_curr_pos = curr_pos;
+
+    /* If buffer 0 is empty and the ring hasn't wrapped,
+       no data has been captured. */
+    if (i == 0 && curr_pos == rb_data.files[0].start_pos &&
+        rb_data.files[0].number == 0)
+      data_captured = FALSE;
+
+    /* Flush the file */
+    errno = WTAP_ERR_CANT_CLOSE;
+    if (fflush(fh) == EOF) {
+      if (err != NULL) {
+        *err = errno;
       }
+      ret_val = FALSE;
+      close(rb_data.files[i].fd);
+      unlink(rb_data.files[i].name);
+      cf->save_file = rb_data.files[i].name;
       continue;
     }
 
@@ -327,7 +351,7 @@ ringbuf_wtap_dump_close(capture_file *cf, int *err)
        to get rid of the 'garbage' packets at the end of the file from
        previous usage */
     if (!rb_data.files[i].is_new) {
-      if (ftruncate(rb_data.files[i].fd,ftell(fh)) != 0) {
+      if (ftruncate(rb_data.files[i].fd, curr_pos) != 0) {
         /* could not truncate the file */
         if (err != NULL) {
           *err = errno;
@@ -336,17 +360,26 @@ ringbuf_wtap_dump_close(capture_file *cf, int *err)
         /* remove the file since it contains garbage at the end */
         close(rb_data.files[i].fd);
         unlink(rb_data.files[i].name);
+        cf->save_file = rb_data.files[i].name;
         continue;
       }
     }
     /* close the file */
     if (!wtap_dump_close(rb_data.files[i].pdh, err)) {
       /* error only if it is a used file */
-      if (!rb_data.files[i].is_new) {
+      if (curr_pos > rb_data.files[i].start_pos) {
         ret_val = FALSE;
+        /* Don't unlink it; maybe the user can salvage it. */
+        cf->save_file = rb_data.files[i].name;
+        continue;
       }
     }
-    if (!rb_data.files[i].is_new) {
+
+    /* Rename buffers which have data and delete empty buffers --
+       except if no data at all has been captured we need to keep
+       the empty first buffer. */
+    if (curr_pos > rb_data.files[i].start_pos ||
+         (i == 0 && !data_captured)) {
       /* rename the file */
       snprintf(filenum,5+1,"%05d",rb_data.files[i].number);
       strftime(timestr,14+1,"%Y%m%d%H%M%S",
@@ -359,18 +392,32 @@ ringbuf_wtap_dump_close(capture_file *cf, int *err)
           *err = errno;
         }
         ret_val = FALSE;
+        cf->save_file = rb_data.files[i].name;
         g_free(new_name);
       } else {
         g_free(rb_data.files[i].name);
         rb_data.files[i].name = new_name;
       }
     } else {
-      /* this file has never been used - remove it */
+      /* this file is empty - remove it */
       unlink(rb_data.files[i].name);
     }
   }
-  /* make the current file the save file */
-  cf->save_file = rb_data.files[rb_data.curr_file_num].name;
+
+  if (ret_val) {
+    /* Make the current file the save file, or if it's empty apart from
+       the header, make the previous file the save file (assuming data
+       has been captured). */
+    if (curr_file_curr_pos ==
+        rb_data.files[rb_data.curr_file_num].start_pos &&
+        data_captured) {
+      if (rb_data.curr_file_num > 0)
+        rb_data.curr_file_num -= 1;
+      else
+        rb_data.curr_file_num = rb_data.num_files - 1;
+    }
+    cf->save_file = rb_data.files[rb_data.curr_file_num].name;
+  }
   return ret_val;
 }