v7 gzip dump restore patches

David Bremner david at tethera.net
Sat Apr 5 08:43:50 PDT 2014


Supercedes 

  id:1396554083-3892-2-git-send-email-david at tethera.net

- adds new analogues of strerror
  - util_error_string
  - gz_error_string

Interdiff:

diff --git a/configure b/configure
index 1d624f7..83b4af7 100755
--- a/configure
+++ b/configure
@@ -509,7 +509,7 @@ EOF
 	echo "	http://xapian.org/"
     fi
     if [ $have_zlib -eq 0 ]; then
-	echo "	zlib library (including development files such as headers)"
+	echo "	zlib library (>= version 1.2.5.2, including development files such as headers)"
 	echo "	http://zlib.net/"
 	echo
     fi
diff --git a/notmuch-dump.c b/notmuch-dump.c
index 2a7252a..2849eab 100644
--- a/notmuch-dump.c
+++ b/notmuch-dump.c
@@ -127,7 +127,7 @@ notmuch_database_dump (notmuch_database_t *notmuch,
 		       dump_format_t output_format,
 		       notmuch_bool_t gzip_output)
 {
-    gzFile output;
+    gzFile output = NULL;
     const char *mode = gzip_output ? "w9" : "wT";
     const char *name_for_error = output_file_name ? output_file_name : "stdout";
 
@@ -178,7 +178,10 @@ notmuch_database_dump (notmuch_database_t *notmuch,
     }
 
     if (gzclose_w (output) != Z_OK) {
+	fprintf (stderr, "Error closing %s: %s\n", name_for_error,
+		 gzerror (output, NULL));
 	ret = EXIT_FAILURE;
+	output = NULL;
 	goto DONE;
     }
 
@@ -192,6 +195,9 @@ notmuch_database_dump (notmuch_database_t *notmuch,
 
     }
  DONE:
+    if (ret != EXIT_SUCCESS && output)
+	(void) gzclose_w (output);
+
     if (ret != EXIT_SUCCESS && output_file_name)
 	(void) unlink (tempname);
 
diff --git a/notmuch-restore.c b/notmuch-restore.c
index eb5b7b2..7abee0a 100644
--- a/notmuch-restore.c
+++ b/notmuch-restore.c
@@ -129,7 +129,8 @@ notmuch_restore_command (notmuch_config_t *config, int argc, char *argv[])
     tag_op_list_t *tag_ops;
 
     char *input_file_name = NULL;
-    gzFile input;
+    const char *name_for_error = NULL;
+    gzFile input = NULL;
     char *line = NULL;
     void *line_ctx = NULL;
     ssize_t line_len;
@@ -157,19 +158,26 @@ notmuch_restore_command (notmuch_config_t *config, int argc, char *argv[])
     };
 
     opt_index = parse_arguments (argc, argv, options, 1);
-    if (opt_index < 0)
-	return EXIT_FAILURE;
+    if (opt_index < 0) {
+	ret = EXIT_FAILURE;
+	goto DONE;
+    }
+
+    name_for_error = input_file_name ? input_file_name : "stdin";
 
     if (! accumulate)
 	flags |= TAG_FLAG_REMOVE_ALL;
 
+    errno = 0;
     if (input_file_name)
 	input = gzopen (input_file_name, "r");
     else {
 	int infd = dup (STDIN_FILENO);
 	if (infd < 0) {
-	    fprintf (stderr, "Error duping stdin\n");
-	    return EXIT_FAILURE;
+	    fprintf (stderr, "Error duping stdin: %s\n",
+		     strerror (errno));
+	    ret = EXIT_FAILURE;
+	    goto DONE;
 	}
 	input = gzdopen (infd, "r");
 	if (! input)
@@ -178,19 +186,22 @@ notmuch_restore_command (notmuch_config_t *config, int argc, char *argv[])
 
     if (input == NULL) {
 	fprintf (stderr, "Error opening %s for (gzip) reading: %s\n",
-		 input_file_name ? input_file_name : "stdin", strerror (errno));
-	return EXIT_FAILURE;
+		 name_for_error, strerror (errno));
+	ret = EXIT_FAILURE;
+	goto DONE;
     }
 
     if (opt_index < argc) {
 	fprintf (stderr, "Unused positional parameter: %s\n", argv[opt_index]);
-	return EXIT_FAILURE;
+	ret = EXIT_FAILURE;
+	goto DONE;
     }
 
     tag_ops = tag_op_list_create (config);
     if (tag_ops == NULL) {
 	fprintf (stderr, "Out of memory.\n");
-	return EXIT_FAILURE;
+	ret = EXIT_FAILURE;
+	goto DONE;
     }
 
     do {
@@ -199,12 +210,17 @@ notmuch_restore_command (notmuch_config_t *config, int argc, char *argv[])
 	status = gz_getline (line_ctx, &line, &line_len, input);
 
 	/* empty input file not considered an error */
-	if (status == UTIL_EOF)
-	    return EXIT_SUCCESS;
-
-	if (status)
-	    return EXIT_FAILURE;
+	if (status == UTIL_EOF) {
+	    ret = EXIT_SUCCESS;
+	    goto DONE;
+	}
 
+	if (status) {
+	    fprintf (stderr, "Error reading (gzipped) input: %s\n",
+		     gz_error_string(status, input));
+	    ret = EXIT_FAILURE;
+	    goto DONE;
+	}
     } while ((line_len == 0) ||
 	     (line[0] == '#') ||
 	     /* the cast is safe because we checked about for line_len < 0 */
@@ -269,17 +285,37 @@ notmuch_restore_command (notmuch_config_t *config, int argc, char *argv[])
 	if (ret)
 	    break;
 
-    }  while (gz_getline (line_ctx, &line, &line_len, input) == UTIL_SUCCESS);
+    }  while (! (ret = gz_getline (line_ctx, &line, &line_len, input)));
+    
 
-    if (line_ctx != NULL)
-	talloc_free (line_ctx);
+    /* EOF is normal loop termination condition, UTIL_SUCCESS is
+     * impossible here */
+    if (ret == UTIL_EOF) {
+	ret = UTIL_SUCCESS;
+    } else {
+	fprintf (stderr, "Error reading (gzipped) input: %s\n",
+		 gz_error_string (ret, input));
+    }
+
+    /* currently this should not be after DONE: since we don't 
+     * know if the xregcomp was reached
+     */
 
     if (input_format == DUMP_FORMAT_SUP)
 	regfree (&regex);
 
-    notmuch_database_destroy (notmuch);
+ DONE:
+    if (line_ctx != NULL)
+	talloc_free (line_ctx);
 
-    gzclose_r (input);
+    if (notmuch)
+	notmuch_database_destroy (notmuch);
+
+    if (input && gzclose_r (input)) {
+	fprintf (stderr, "Error closing %s: %s\n",
+		 name_for_error, gzerror (input, NULL));
+	ret = EXIT_FAILURE;
+    }
 
     return ret ? EXIT_FAILURE : EXIT_SUCCESS;
 }
diff --git a/util/Makefile.local b/util/Makefile.local
index e2a5b65..905f237 100644
--- a/util/Makefile.local
+++ b/util/Makefile.local
@@ -4,7 +4,8 @@ dir := util
 extra_cflags += -I$(srcdir)/$(dir)
 
 libutil_c_srcs := $(dir)/xutil.c $(dir)/error_util.c $(dir)/hex-escape.c \
-		  $(dir)/string-util.c $(dir)/talloc-extra.c $(dir)/zlib-extra.c
+		  $(dir)/string-util.c $(dir)/talloc-extra.c $(dir)/zlib-extra.c \
+		$(dir)/util.c
 
 libutil_modules := $(libutil_c_srcs:.c=.o)
 
diff --git a/util/util.c b/util/util.c
new file mode 100644
index 0000000..3bd305d
--- /dev/null
+++ b/util/util.c
@@ -0,0 +1,24 @@
+#include "util.h"
+#include "error_util.h"
+#include <string.h>
+#include <errno.h>
+
+const char *
+util_error_string (util_status_t errnum)
+{
+    switch (errnum) {
+    case UTIL_SUCCESS:
+	return "none";
+    case UTIL_OUT_OF_MEMORY:
+	return "out of memory";
+    case UTIL_EOF:
+	return "end of file";
+    case UTIL_ERRNO:
+	return strerror (errno);
+    case UTIL_GZERROR:
+	/* we lack context to be more informative here */
+	return "zlib error";
+    default:
+	INTERNAL_ERROR("unexpected error status %d", errnum);
+    }
+}
diff --git a/util/util.h b/util/util.h
index 8663cfc..d12fadb 100644
--- a/util/util.h
+++ b/util/util.h
@@ -2,11 +2,28 @@
 #define _UTIL_H
 
 typedef enum util_status {
+    /**
+     * No error occurred.
+     */
     UTIL_SUCCESS = 0,
-    UTIL_ERROR = 1,
+    /**
+     * Out of memory.
+     */
     UTIL_OUT_OF_MEMORY,
+    /**
+     * End of stream reached while attempting to read.
+     */
     UTIL_EOF,
-    UTIL_FILE,
+    /**
+     * Low level error occured, consult errno.
+     */
+    UTIL_ERRNO,
+    /**
+     * Zlib error occured, call gzerror for details.
+     */
+    UTIL_GZERROR
 } util_status_t;
 
+const char *
+util_error_string (util_status_t status);
 #endif
diff --git a/util/zlib-extra.c b/util/zlib-extra.c
index 922ab52..cb34845 100644
--- a/util/zlib-extra.c
+++ b/util/zlib-extra.c
@@ -54,9 +54,9 @@ gz_getline (void *talloc_ctx, char **bufptr, ssize_t *bytes_read, gzFile stream)
 		else
 		    goto SUCCESS;
 	    case Z_ERRNO:
-		return UTIL_FILE;
+		return UTIL_ERRNO;
 	    default:
-		return UTIL_ERROR;
+		return UTIL_GZERROR;
 	    }
 	}
 
@@ -75,3 +75,11 @@ gz_getline (void *talloc_ctx, char **bufptr, ssize_t *bytes_read, gzFile stream)
     *bytes_read = offset;
     return UTIL_SUCCESS;
 }
+
+const char *gz_error_string (util_status_t status, gzFile file) 
+{
+    if (status == UTIL_GZERROR)
+	return gzerror (file, NULL);
+    else
+	return util_error_string (status);
+}
diff --git a/util/zlib-extra.h b/util/zlib-extra.h
index ed67115..dbaa0b9 100644
--- a/util/zlib-extra.h
+++ b/util/zlib-extra.h
@@ -4,8 +4,22 @@
 #include "util.h"
 #include <zlib.h>
 
-/* Like getline, but read from a gzFile. Allocation is with talloc */
+/* Like getline, but read from a gzFile. Allocation is with talloc.
+ * Returns:
+ *
+ *   UTIL_SUCCESS, UTIL_OUT_OF_MEMORY, UTIL_ERRNO, UTIL_GZERROR
+ *			Consult util.h for description
+ *
+ *   UTIL_EOF		End of file encountered before 
+ *			any characters read
+ */
 util_status_t
 gz_getline (void *ctx, char **lineptr, ssize_t *bytes_read, gzFile stream);
 
+/* return a suitable error string based on the return status
+ *  from gz_readline
+ */
+
+const char *
+gz_error_string (util_status_t status, gzFile stream);
 #endif


More information about the notmuch mailing list