Improve the alert boxes put up for file open/read/write errors. (Some
authorGuy Harris <guy@alum.mit.edu>
Sat, 12 Jun 1999 09:10:20 +0000 (09:10 -0000)
committerGuy Harris <guy@alum.mit.edu>
Sat, 12 Jun 1999 09:10:20 +0000 (09:10 -0000)
influence came from

http://developer.apple.com/techpubs/mac/HIGuidelines/HIGuidelines-232.html

which has a section on dialog box and alert box messages.  However,
we're largely dealing with technoids, not with The Rest Of Us, so I
didn't go as far as one perhaps should.)

Unfortunately, it looks like it's a bit more work to arrange that, if
you give a bad file name to the "-r" flag, the dialog box pop up only
*after* the main window pops up - it has the annoying habit of popping
up *before* the main window pops up, and sometimes getting *obscured* by
it, when I do that.  The removal of the dialog box stuff from
"load_cap_file()" was intended to facilitate that work.  (It might also
be nice if, when an open from the "File/Open" menu item fails, we keep
the file selection box open, and give the user a chance to correct
typos, choose another file name, etc.)

svn path=/trunk/; revision=310

capture.c
ethereal.c
file.c
file.h
util.c
util.h

index 73c226b663eff1ae22d624d701a9ca3cecb586a8..58af109b1cb4d883b51d9f5bf14ffc5ab246e100 100644 (file)
--- a/capture.c
+++ b/capture.c
@@ -1,7 +1,7 @@
 /* capture.c
  * Routines for packet capture windows
  *
- * $Id: capture.c,v 1.25 1999/06/11 15:30:34 gram Exp $
+ * $Id: capture.c,v 1.26 1999/06/12 09:10:19 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -368,6 +368,7 @@ capture_prep_ok_cb(GtkWidget *w, gpointer data) {
     int  fork_child;
     char ssnap[24];
     char scount[24];   /* need a constant for len of numbers */
+    int err;
 
     sprintf(ssnap,"%d",cf.snap); /* in liu of itoa */
     sprintf(scount,"%d",cf.count);
@@ -412,8 +413,13 @@ capture_prep_ok_cb(GtkWidget *w, gpointer data) {
           if (kill(fork_child, 0) == -1 && errno == ESRCH) 
             break;
         }
-        if (sigusr2_received) 
-          tail_cap_file(cf.save_file, &cf);
+        if (sigusr2_received) {
+          err = tail_cap_file(cf.save_file, &cf);
+          if (err != 0) {
+            simple_dialog(ESD_TYPE_WARN, NULL,
+                       file_open_error_message(err, FALSE), cf.save_file);
+          }
+        }
         sigusr2_received = FALSE;
        }
     }
@@ -441,6 +447,7 @@ capture(void) {
   loop_data   ld;
   bpf_u_int32 netnum, netmask;
   time_t      upd_time, cur_time;
+  int         err;
   
   ld.go           = TRUE;
   ld.counts.total = 0;
@@ -586,13 +593,19 @@ capture(void) {
     gtk_exit(0);
   }
 
-  if (cf.save_file) load_cap_file(cf.save_file, &cf);
+  if (cf.save_file) {
+    err = load_cap_file(cf.save_file, &cf);
+    if (err != 0) {
+      simple_dialog(ESD_TYPE_WARN, NULL,
+                       file_open_error_message(err, FALSE), cf.save_file);
+    }
+  }
 #ifdef USE_ITEM
-    set_menu_sensitivity("/File/Save", TRUE);
-    set_menu_sensitivity("/File/Save as", FALSE);
+  set_menu_sensitivity("/File/Save", TRUE);
+  set_menu_sensitivity("/File/Save as", FALSE);
 #else
-    set_menu_sensitivity("<Main>/File/Save", TRUE);
-    set_menu_sensitivity("<Main>/File/Save as", FALSE);
+  set_menu_sensitivity("<Main>/File/Save", TRUE);
+  set_menu_sensitivity("<Main>/File/Save as", FALSE);
 #endif
 }
 
index db13a53acfc3c88f56c44f4da3909c1b9b701f84..ca0d282da757e8e675120c45b1344f1c27146a69 100644 (file)
@@ -1,6 +1,6 @@
 /* ethereal.c
  *
- * $Id: ethereal.c,v 1.37 1999/06/12 07:04:34 guy Exp $
+ * $Id: ethereal.c,v 1.38 1999/06/12 09:10:20 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -155,6 +155,10 @@ file_sel_ok_cb(GtkWidget *w, GtkFileSelection *fs) {
    * cf_name, leaving only the path to the directory. */
   if ((err = load_cap_file(cf_name, &cf)) == 0)
     chdir(cf_name);
+  else {
+    simple_dialog(ESD_TYPE_WARN, NULL, file_open_error_message(err, FALSE),
+               cf_name);
+  }
   g_free(cf_name);
 #ifdef USE_ITEM
     set_menu_sensitivity("/File/Save", FALSE);
@@ -179,6 +183,7 @@ follow_stream_cb( GtkWidget *w, gpointer data ) {
   char filename1[128];
   GtkWidget *streamwindow, *box, *text, *vscrollbar, *table;
   GtkWidget *filter_te = NULL;
+  int err;
 
   if (w)
        filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);
@@ -204,7 +209,11 @@ follow_stream_cb( GtkWidget *w, gpointer data ) {
       fprintf( stderr, "Could not open tmp file %s\n", filename1 );
     }
     reset_tcp_reassembly();
-    load_cap_file( cf.filename, &cf );
+    err = load_cap_file( cf.filename, &cf );
+    if (err != 0) {
+      simple_dialog(ESD_TYPE_WARN, NULL, file_open_error_message(err, FALSE),
+               cf.filename);
+    }
     /* the data_out_file should now be full of the streams information */
     fclose( data_out_file );
     /* the filename1 file now has all the text that was in the session */
@@ -357,6 +366,7 @@ file_save_as_cmd_cb(GtkWidget *w, gpointer data) {
 static void
 file_save_ok_cb(GtkWidget *w, GtkFileSelection *fs) {
        gchar   *cf_name;
+       int     err;
 
        cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
        gtk_widget_hide(GTK_WIDGET (fs));
@@ -367,7 +377,11 @@ file_save_ok_cb(GtkWidget *w, GtkFileSelection *fs) {
        g_free(cf.save_file);
        cf.save_file = g_strdup(cf_name);
        cf.user_saved = 1;
-       load_cap_file(cf_name, &cf);
+       err = load_cap_file(cf_name, &cf);
+       if (err != 0) {
+               simple_dialog(ESD_TYPE_WARN, NULL,
+                   file_open_error_message(err, FALSE), cf_name);
+       }
 
 #ifdef USE_ITEM
        set_menu_sensitivity("/File/Save", FALSE);
@@ -381,6 +395,7 @@ file_save_ok_cb(GtkWidget *w, GtkFileSelection *fs) {
 static void
 file_save_as_ok_cb(GtkWidget *w, GtkFileSelection *fs) {
        gchar   *cf_name;
+       int     err;
 
        cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
        gtk_widget_hide(GTK_WIDGET (fs));
@@ -391,7 +406,11 @@ file_save_as_ok_cb(GtkWidget *w, GtkFileSelection *fs) {
        g_free(cf.save_file);
        cf.save_file = g_strdup(cf_name);
        cf.user_saved = 1;
-       load_cap_file(cf_name, &cf);
+       err = load_cap_file(cf_name, &cf);
+       if (err != 0) {
+               simple_dialog(ESD_TYPE_WARN, NULL,
+                   file_open_error_message(err, FALSE), cf_name);
+       }
 
 #ifdef USE_ITEM
        set_menu_sensitivity("/File/Save", FALSE);
@@ -407,12 +426,17 @@ void
 file_reload_cmd_cb(GtkWidget *w, gpointer data) {
   /*GtkWidget *filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);*/
   GtkWidget *filter_te;
+  int err;
 
   filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);
 
   if (cf.dfilter) g_free(cf.dfilter);
   cf.dfilter = g_strdup(gtk_entry_get_text(GTK_ENTRY(filter_te)));
-  load_cap_file(cf.filename, &cf);
+  err = load_cap_file(cf.filename, &cf);
+  if (err != 0) {
+    simple_dialog(ESD_TYPE_WARN, NULL, file_open_error_message(err, FALSE),
+               cf.filename);
+  }
 }
 
 /* Print a packet */
@@ -495,7 +519,7 @@ void blank_packetinfo() {
   pi.destport = 0;
 }
 
-/* Things to do when the OK button is pressed */
+/* Things to do when the main window is realized */
 void
 main_realize_cb(GtkWidget *w, gpointer data) {
   gchar  *cf_name = (gchar *) data;
@@ -503,6 +527,10 @@ main_realize_cb(GtkWidget *w, gpointer data) {
   
   if (cf_name) {
     err = load_cap_file(cf_name, &cf);
+    if (err != 0) {
+      simple_dialog(ESD_TYPE_WARN, NULL, file_open_error_message(err, FALSE),
+               cf_name);
+    }
     cf_name[0] = '\0';
 #ifdef USE_ITEM
     set_menu_sensitivity("/File/Save as", TRUE);
@@ -529,7 +557,7 @@ ethereal_proto_init(void) {
 
 }
 
-void 
+static void 
 print_usage(void) {
 
   fprintf(stderr, "This is GNU %s %s, compiled with %s\n", PACKAGE,
diff --git a/file.c b/file.c
index 87f56166ea8971f7c5593f0f8207c049bec88fa8..e41599e518b00c947caca3924af1c2ad4993e756 100644 (file)
--- a/file.c
+++ b/file.c
@@ -1,7 +1,7 @@
 /* file.c
  * File I/O routines
  *
- * $Id: file.c,v 1.25 1999/05/11 20:07:47 gram Exp $
+ * $Id: file.c,v 1.26 1999/06/12 09:10:19 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -96,14 +96,10 @@ open_cap_file(char *fname, capture_file *cf) {
   struct stat cf_stat;
 
   /* First, make sure the file is valid */
-  if (stat(fname, &cf_stat)) {
-    simple_dialog(ESD_TYPE_WARN, NULL, "File does not exist.");
-    return 1;
-  }
-  if (! S_ISREG(cf_stat.st_mode) && ! S_ISFIFO(cf_stat.st_mode)) {
-    simple_dialog(ESD_TYPE_WARN, NULL, "The file you have chosen is invalid.");
-    return 1;
-  }
+  if (stat(fname, &cf_stat))
+    return (errno);
+  if (! S_ISREG(cf_stat.st_mode) && ! S_ISFIFO(cf_stat.st_mode))
+    return (OPEN_CAP_FILE_NOT_REGULAR);
 
   /* Next, try to open the file */
   cf->fh = fopen(fname, "r");
@@ -156,8 +152,10 @@ open_cap_file(char *fname, capture_file *cf) {
        if (cf->wth == NULL) {
 #endif
 
-      simple_dialog(ESD_TYPE_WARN, NULL, "Could not open file.");
-      return 1;
+      /* XXX - we assume that, because we were able to open it above,
+         this must have failed because it's not a capture file in
+        a format we can read. */
+      return (OPEN_CAP_FILE_UNKNOWN_FORMAT);
     }
 
 #ifndef WITH_WIRETAP
@@ -184,14 +182,11 @@ open_cap_file(char *fname, capture_file *cf) {
     cf->snap  = pcap_snapshot(cf->pfh);
     cf->lnk_t = pcap_datalink(cf->pfh);
   } else if (ntohl(magic[0]) == SNOOP_MAGIC_1 && ntohl(magic[1]) == SNOOP_MAGIC_2) {
-    simple_dialog(ESD_TYPE_WARN, NULL, "The snoop format is not yet supported.");
-    return 1;
+    return (OPEN_CAP_FILE_UNKNOWN_FORMAT);
   }
   
-  if (cf->cd_t == CD_UNKNOWN) {
-    simple_dialog(ESD_TYPE_WARN, NULL, "Can't determine file type.");
-    return 1;
-  }
+  if (cf->cd_t == CD_UNKNOWN)
+    return (OPEN_CAP_FILE_UNKNOWN_FORMAT);
 #else
     if (cf->dfilter) {
       if (wtap_offline_filter(cf->wth, cf->dfilter) < 0) {
@@ -204,7 +199,7 @@ open_cap_file(char *fname, capture_file *cf) {
   cf->snap = wtap_snapshot_length(cf->wth);
 #endif
 
-  return 0;
+  return (0);
 }
 
 /* Reset everything to a pristine state */
@@ -250,7 +245,7 @@ load_cap_file(char *fname, capture_file *cf) {
 
   close_cap_file(cf, info_bar, file_ctx);
 
-  /* Initialize protocol-speficic variables */
+  /* Initialize protocol-specific variables */
   ncp_init_protocol();
 
   if ((name_ptr = (gchar *) strrchr(fname, '/')) == NULL)
@@ -562,3 +557,162 @@ pcap_dispatch_cb(u_char *user, const struct pcap_pkthdr *phdr,
   cf->plist = cf->plist->next;
 
 }
+
+/* Tries to mv a file. If unsuccessful, tries to cp the file.
+ * Returns 0 on failure to do either, 1 on success of either
+ */
+int
+file_mv(char *from, char *to)
+{
+
+#define COPY_BUFFER_SIZE       8192
+
+       int retval;
+
+       /* try a hard link */
+       retval = link(from, to);
+
+       /* or try a copy */
+       if (retval < 0) {
+               retval = file_cp(from, to);
+               if (!retval) {
+                       return 0;
+               }
+       }
+
+       unlink(from);
+       return 1;
+}
+
+/* Copies a file.
+ * Returns 0 on failure to do either, 1 on success of either
+ */
+int
+file_cp(char *from, char *to)
+{
+
+#define COPY_BUFFER_SIZE       8192
+
+       int from_fd, to_fd, nread, nwritten;
+       char *buffer;
+       gint dialogue_button = ESD_BTN_OK;
+
+       buffer = g_malloc(COPY_BUFFER_SIZE);
+
+       from_fd = open(from, O_RDONLY);
+       if (from_fd < 0) {
+               simple_dialog(ESD_TYPE_WARN, &dialogue_button,
+                       file_open_error_message(errno, TRUE), from);
+               return 0;
+       }
+
+       to_fd = creat(to, 0644);
+       if (to_fd < 0) {
+               simple_dialog(ESD_TYPE_WARN, &dialogue_button,
+                       file_open_error_message(errno, TRUE), to);
+               close(from_fd);
+               return 0;
+       }
+
+       while( (nread = read(from_fd, buffer, COPY_BUFFER_SIZE)) > 0) {
+               nwritten = write(to_fd, buffer, nread);
+               if (nwritten < nread) {
+                       if (nwritten < 0) {
+                               simple_dialog(ESD_TYPE_WARN, &dialogue_button,
+                                       file_write_error_message(errno), to);
+                       } else {
+                               simple_dialog(ESD_TYPE_WARN, &dialogue_button,
+"The file \"%s\" could not be saved: tried writing %d, wrote %d.\n",
+                                       to, nread, nwritten);
+                       }
+                       close(from_fd);
+                       close(to_fd);
+                       return 0;
+               }
+       }
+       if (nread < 0) {
+               simple_dialog(ESD_TYPE_WARN, &dialogue_button,
+                       file_read_error_message(errno), from);
+               close(from_fd);
+               close(to_fd);
+               return 0;
+       }
+       close(from_fd);
+       close(to_fd);
+
+       return 1;
+}
+
+char *
+file_open_error_message(int err, int for_writing)
+{
+  char *errmsg;
+  static char errmsg_errno[1024+1];
+
+  switch (err) {
+
+  case OPEN_CAP_FILE_NOT_REGULAR:
+    errmsg = "The file \"%s\" is invalid.";
+    break;
+
+  case OPEN_CAP_FILE_UNKNOWN_FORMAT:
+    errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
+    break;
+
+  case ENOENT:
+    if (for_writing)
+      errmsg = "The path to the file \"%s\" does not exist.";
+    else
+      errmsg = "The file \"%s\" does not exist.";
+    break;
+
+  case EACCES:
+    if (for_writing)
+      errmsg = "You do not have permission to create or write to the file \"%s\".";
+    else
+      errmsg = "You do not have permission to open the file \"%s\".";
+    break;
+
+  default:
+    sprintf(errmsg_errno, "The file \"%%s\" could not be opened: %s.", strerror(err));
+    errmsg = errmsg_errno;
+    break;
+  }
+  return errmsg;
+}
+
+char *
+file_read_error_message(int err)
+{
+  static char errmsg_errno[1024+1];
+
+  sprintf(errmsg_errno, "An error occurred while reading from the file \"%%s\": %s.", strerror(err));
+  return errmsg_errno;
+}
+
+char *
+file_write_error_message(int err)
+{
+  char *errmsg;
+  static char errmsg_errno[1024+1];
+
+  switch (err) {
+
+  case ENOSPC:
+    errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
+    break;
+
+#ifdef EDQUOT
+  case EDQUOT:
+    errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
+    break;
+#endif
+
+  default:
+    sprintf(errmsg_errno, "An error occurred while writing to the file \"%%s\": %s.", strerror(err));
+    errmsg = errmsg_errno;
+    break;
+  }
+  return errmsg;
+}
+
diff --git a/file.h b/file.h
index 3480347c3d9747567c76ebd4a3386d57ab8b378e..0b96caa3e0b29c5bce5868d0a27cb382b8cec7c9 100644 (file)
--- a/file.h
+++ b/file.h
@@ -1,7 +1,7 @@
 /* file.h
  * Definitions for file structures and routines
  *
- * $Id: file.h,v 1.13 1999/05/11 18:51:10 deniel Exp $
+ * $Id: file.h,v 1.14 1999/06/12 09:10:19 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -118,10 +118,32 @@ typedef struct _snoop_frame_hdr {
 } snoop_frame_hdr;
 #endif
 
+/*
+ * "open_cap_file()" can return:
+ *
+ * 0 on success;
+ *
+ * a positive "errno" value on an open failure;
+ *
+ * a negative number, indicating the type of error, on other failures.
+ */
+#define        OPEN_CAP_FILE_NOT_REGULAR       -1      /* not a plain file */
+#define        OPEN_CAP_FILE_UNKNOWN_FORMAT    -2      /* not a capture file in a known format */
+
 int  open_cap_file(char *, capture_file *);
 void close_cap_file(capture_file *, void *, guint);
 int  load_cap_file(char *, capture_file *);
 int  tail_cap_file(char *, capture_file *);
 /* size_t read_frame_header(capture_file *); */
 
+/* Moves or copies a file. Returns 0 on failure, 1 on success */
+int file_mv(char *from, char *to);
+
+/* Copies a file. Returns 0 on failure, 1 on success */
+int file_cp(char *from, char *to);
+
+char *file_open_error_message(int, int);
+char *file_read_error_message(int);
+char *file_write_error_message(int);
+
 #endif /* file.h */
diff --git a/util.c b/util.c
index 4c8277db3c93ed18c4b8da8354922801770d59d7..7a84868b08c26cc519a8b673fe12ad0e6be4a98d 100644 (file)
--- a/util.c
+++ b/util.c
@@ -1,7 +1,7 @@
 /* util.c
  * Utility routines
  *
- * $Id: util.c,v 1.14 1999/04/06 16:24:49 gram Exp $
+ * $Id: util.c,v 1.15 1999/06/12 09:10:18 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -174,72 +174,3 @@ simple_dialog_cancel_cb(GtkWidget *w, gpointer win) {
     *btn_mask = ESD_BTN_CANCEL;
   gtk_widget_destroy(GTK_WIDGET(win));
 }
-
-/* Tries to mv a file. If unsuccessful, tries to cp the file.
- * Returns 0 on failure to do either, 1 on success of either
- */
-int
-file_mv(char *from, char *to)
-{
-
-#define COPY_BUFFER_SIZE       8192
-
-       int retval;
-
-       /* try a hard link */
-       retval = link(from, to);
-
-       /* or try a copy */
-       if (retval < 0) {
-               retval = file_cp(from, to);
-               if (!retval) {
-                       return 0;
-               }
-       }
-
-       unlink(from);
-       return 1;
-}
-
-/* Copies a file.
- * Returns 0 on failure to do either, 1 on success of either
- */
-int
-file_cp(char *from, char *to)
-{
-
-#define COPY_BUFFER_SIZE       8192
-
-       int from_fd, to_fd, nread;
-       char *buffer;
-       gint dialogue_button = ESD_BTN_OK;
-
-       buffer = g_malloc(COPY_BUFFER_SIZE);
-
-       from_fd = open(from, O_RDONLY);
-       if (from_fd < 0) {
-               simple_dialog(ESD_TYPE_WARN, &dialogue_button,
-                       "Cannot open from-file for copying.");
-               return 0;
-       }
-
-       to_fd = creat(to, 0644);
-       if (to_fd < 0) {
-               simple_dialog(ESD_TYPE_WARN, &dialogue_button,
-                       "Cannot open to-file for copying.");
-               close(from_fd);
-               return 0;
-       }
-
-       while( (nread = read(from_fd, buffer, COPY_BUFFER_SIZE)) > 0) {
-               if (write(to_fd, buffer, nread) < nread) {
-                       close(from_fd);
-                       close(to_fd);
-                       return 0;
-               }
-       }
-       close(from_fd);
-       close(to_fd);
-
-       return 1;
-}
diff --git a/util.h b/util.h
index 69dffb82666330b8b5b4f267ff693f9e517046b1..88f1ab9d44cf0c35126d719ba574544310b41cee 100644 (file)
--- a/util.h
+++ b/util.h
@@ -1,7 +1,7 @@
 /* util.h
  * Utility definitions
  *
- * $Id: util.h,v 1.9 1999/04/06 16:24:50 gram Exp $
+ * $Id: util.h,v 1.10 1999/06/12 09:10:20 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -46,12 +46,6 @@ void simple_dialog(gint, gint *, gchar *, ...)
 void simple_dialog(gint, gint *, gchar *, ...);
 #endif
 
-/* Moves or copies a file. Returns 0 on failure, 1 on success */
-int file_mv(char *from, char *to);
-
-/* Copies a file. Returns 0 on failure, 1 on success */
-int file_cp(char *from, char *to);
-
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */