--- /dev/null
+Return-Path: <bremner@tesseract.cs.unb.ca>\r
+X-Original-To: notmuch@notmuchmail.org\r
+Delivered-To: notmuch@notmuchmail.org\r
+Received: from localhost (localhost [127.0.0.1])\r
+ by olra.theworths.org (Postfix) with ESMTP id D9475431FAF\r
+ for <notmuch@notmuchmail.org>; Sat, 5 Apr 2014 08:44:39 -0700 (PDT)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: 0\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=0 tagged_above=-999 required=5 tests=[none]\r
+ autolearn=disabled\r
+Received: from olra.theworths.org ([127.0.0.1])\r
+ by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
+ with ESMTP id YKXB9MuOeEk8 for <notmuch@notmuchmail.org>;\r
+ Sat, 5 Apr 2014 08:44:33 -0700 (PDT)\r
+Received: from mx.xen14.node3324.gplhost.com (gitolite.debian.net\r
+ [87.98.215.224]) (using TLSv1 with cipher AES256-SHA (256/256 bits))\r
+ (No client certificate requested)\r
+ by olra.theworths.org (Postfix) with ESMTPS id A93AD431FAE\r
+ for <notmuch@notmuchmail.org>; Sat, 5 Apr 2014 08:44:33 -0700 (PDT)\r
+Received: from remotemail by mx.xen14.node3324.gplhost.com with local (Exim\r
+ 4.72) (envelope-from <bremner@tesseract.cs.unb.ca>)\r
+ id 1WWSlS-00082G-IP\r
+ for notmuch@notmuchmail.org; Sat, 05 Apr 2014 15:44:14 +0000\r
+Received: (nullmailer pid 10909 invoked by uid 1000); Sat, 05 Apr 2014\r
+ 15:43:58 -0000\r
+From: David Bremner <david@tethera.net>\r
+To: notmuch@notmuchmail.org\r
+Subject: v7 gzip dump restore patches\r
+Date: Sat, 5 Apr 2014 12:43:50 -0300\r
+Message-Id: <1396712636-10640-1-git-send-email-david@tethera.net>\r
+X-Mailer: git-send-email 1.9.0\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.13\r
+Precedence: list\r
+List-Id: "Use and development of the notmuch mail system."\r
+ <notmuch.notmuchmail.org>\r
+List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
+List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
+List-Post: <mailto:notmuch@notmuchmail.org>\r
+List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
+List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
+X-List-Received-Date: Sat, 05 Apr 2014 15:44:40 -0000\r
+\r
+Supercedes \r
+\r
+ id:1396554083-3892-2-git-send-email-david@tethera.net\r
+\r
+- adds new analogues of strerror\r
+ - util_error_string\r
+ - gz_error_string\r
+\r
+Interdiff:\r
+\r
+diff --git a/configure b/configure\r
+index 1d624f7..83b4af7 100755\r
+--- a/configure\r
++++ b/configure\r
+@@ -509,7 +509,7 @@ EOF\r
+ echo " http://xapian.org/"\r
+ fi\r
+ if [ $have_zlib -eq 0 ]; then\r
+- echo " zlib library (including development files such as headers)"\r
++ echo " zlib library (>= version 1.2.5.2, including development files such as headers)"\r
+ echo " http://zlib.net/"\r
+ echo\r
+ fi\r
+diff --git a/notmuch-dump.c b/notmuch-dump.c\r
+index 2a7252a..2849eab 100644\r
+--- a/notmuch-dump.c\r
++++ b/notmuch-dump.c\r
+@@ -127,7 +127,7 @@ notmuch_database_dump (notmuch_database_t *notmuch,\r
+ dump_format_t output_format,\r
+ notmuch_bool_t gzip_output)\r
+ {\r
+- gzFile output;\r
++ gzFile output = NULL;\r
+ const char *mode = gzip_output ? "w9" : "wT";\r
+ const char *name_for_error = output_file_name ? output_file_name : "stdout";\r
+ \r
+@@ -178,7 +178,10 @@ notmuch_database_dump (notmuch_database_t *notmuch,\r
+ }\r
+ \r
+ if (gzclose_w (output) != Z_OK) {\r
++ fprintf (stderr, "Error closing %s: %s\n", name_for_error,\r
++ gzerror (output, NULL));\r
+ ret = EXIT_FAILURE;\r
++ output = NULL;\r
+ goto DONE;\r
+ }\r
+ \r
+@@ -192,6 +195,9 @@ notmuch_database_dump (notmuch_database_t *notmuch,\r
+ \r
+ }\r
+ DONE:\r
++ if (ret != EXIT_SUCCESS && output)\r
++ (void) gzclose_w (output);\r
++\r
+ if (ret != EXIT_SUCCESS && output_file_name)\r
+ (void) unlink (tempname);\r
+ \r
+diff --git a/notmuch-restore.c b/notmuch-restore.c\r
+index eb5b7b2..7abee0a 100644\r
+--- a/notmuch-restore.c\r
++++ b/notmuch-restore.c\r
+@@ -129,7 +129,8 @@ notmuch_restore_command (notmuch_config_t *config, int argc, char *argv[])\r
+ tag_op_list_t *tag_ops;\r
+ \r
+ char *input_file_name = NULL;\r
+- gzFile input;\r
++ const char *name_for_error = NULL;\r
++ gzFile input = NULL;\r
+ char *line = NULL;\r
+ void *line_ctx = NULL;\r
+ ssize_t line_len;\r
+@@ -157,19 +158,26 @@ notmuch_restore_command (notmuch_config_t *config, int argc, char *argv[])\r
+ };\r
+ \r
+ opt_index = parse_arguments (argc, argv, options, 1);\r
+- if (opt_index < 0)\r
+- return EXIT_FAILURE;\r
++ if (opt_index < 0) {\r
++ ret = EXIT_FAILURE;\r
++ goto DONE;\r
++ }\r
++\r
++ name_for_error = input_file_name ? input_file_name : "stdin";\r
+ \r
+ if (! accumulate)\r
+ flags |= TAG_FLAG_REMOVE_ALL;\r
+ \r
++ errno = 0;\r
+ if (input_file_name)\r
+ input = gzopen (input_file_name, "r");\r
+ else {\r
+ int infd = dup (STDIN_FILENO);\r
+ if (infd < 0) {\r
+- fprintf (stderr, "Error duping stdin\n");\r
+- return EXIT_FAILURE;\r
++ fprintf (stderr, "Error duping stdin: %s\n",\r
++ strerror (errno));\r
++ ret = EXIT_FAILURE;\r
++ goto DONE;\r
+ }\r
+ input = gzdopen (infd, "r");\r
+ if (! input)\r
+@@ -178,19 +186,22 @@ notmuch_restore_command (notmuch_config_t *config, int argc, char *argv[])\r
+ \r
+ if (input == NULL) {\r
+ fprintf (stderr, "Error opening %s for (gzip) reading: %s\n",\r
+- input_file_name ? input_file_name : "stdin", strerror (errno));\r
+- return EXIT_FAILURE;\r
++ name_for_error, strerror (errno));\r
++ ret = EXIT_FAILURE;\r
++ goto DONE;\r
+ }\r
+ \r
+ if (opt_index < argc) {\r
+ fprintf (stderr, "Unused positional parameter: %s\n", argv[opt_index]);\r
+- return EXIT_FAILURE;\r
++ ret = EXIT_FAILURE;\r
++ goto DONE;\r
+ }\r
+ \r
+ tag_ops = tag_op_list_create (config);\r
+ if (tag_ops == NULL) {\r
+ fprintf (stderr, "Out of memory.\n");\r
+- return EXIT_FAILURE;\r
++ ret = EXIT_FAILURE;\r
++ goto DONE;\r
+ }\r
+ \r
+ do {\r
+@@ -199,12 +210,17 @@ notmuch_restore_command (notmuch_config_t *config, int argc, char *argv[])\r
+ status = gz_getline (line_ctx, &line, &line_len, input);\r
+ \r
+ /* empty input file not considered an error */\r
+- if (status == UTIL_EOF)\r
+- return EXIT_SUCCESS;\r
+-\r
+- if (status)\r
+- return EXIT_FAILURE;\r
++ if (status == UTIL_EOF) {\r
++ ret = EXIT_SUCCESS;\r
++ goto DONE;\r
++ }\r
+ \r
++ if (status) {\r
++ fprintf (stderr, "Error reading (gzipped) input: %s\n",\r
++ gz_error_string(status, input));\r
++ ret = EXIT_FAILURE;\r
++ goto DONE;\r
++ }\r
+ } while ((line_len == 0) ||\r
+ (line[0] == '#') ||\r
+ /* the cast is safe because we checked about for line_len < 0 */\r
+@@ -269,17 +285,37 @@ notmuch_restore_command (notmuch_config_t *config, int argc, char *argv[])\r
+ if (ret)\r
+ break;\r
+ \r
+- } while (gz_getline (line_ctx, &line, &line_len, input) == UTIL_SUCCESS);\r
++ } while (! (ret = gz_getline (line_ctx, &line, &line_len, input)));\r
++ \r
+ \r
+- if (line_ctx != NULL)\r
+- talloc_free (line_ctx);\r
++ /* EOF is normal loop termination condition, UTIL_SUCCESS is\r
++ * impossible here */\r
++ if (ret == UTIL_EOF) {\r
++ ret = UTIL_SUCCESS;\r
++ } else {\r
++ fprintf (stderr, "Error reading (gzipped) input: %s\n",\r
++ gz_error_string (ret, input));\r
++ }\r
++\r
++ /* currently this should not be after DONE: since we don't \r
++ * know if the xregcomp was reached\r
++ */\r
+ \r
+ if (input_format == DUMP_FORMAT_SUP)\r
+ regfree (®ex);\r
+ \r
+- notmuch_database_destroy (notmuch);\r
++ DONE:\r
++ if (line_ctx != NULL)\r
++ talloc_free (line_ctx);\r
+ \r
+- gzclose_r (input);\r
++ if (notmuch)\r
++ notmuch_database_destroy (notmuch);\r
++\r
++ if (input && gzclose_r (input)) {\r
++ fprintf (stderr, "Error closing %s: %s\n",\r
++ name_for_error, gzerror (input, NULL));\r
++ ret = EXIT_FAILURE;\r
++ }\r
+ \r
+ return ret ? EXIT_FAILURE : EXIT_SUCCESS;\r
+ }\r
+diff --git a/util/Makefile.local b/util/Makefile.local\r
+index e2a5b65..905f237 100644\r
+--- a/util/Makefile.local\r
++++ b/util/Makefile.local\r
+@@ -4,7 +4,8 @@ dir := util\r
+ extra_cflags += -I$(srcdir)/$(dir)\r
+ \r
+ libutil_c_srcs := $(dir)/xutil.c $(dir)/error_util.c $(dir)/hex-escape.c \\r
+- $(dir)/string-util.c $(dir)/talloc-extra.c $(dir)/zlib-extra.c\r
++ $(dir)/string-util.c $(dir)/talloc-extra.c $(dir)/zlib-extra.c \\r
++ $(dir)/util.c\r
+ \r
+ libutil_modules := $(libutil_c_srcs:.c=.o)\r
+ \r
+diff --git a/util/util.c b/util/util.c\r
+new file mode 100644\r
+index 0000000..3bd305d\r
+--- /dev/null\r
++++ b/util/util.c\r
+@@ -0,0 +1,24 @@\r
++#include "util.h"\r
++#include "error_util.h"\r
++#include <string.h>\r
++#include <errno.h>\r
++\r
++const char *\r
++util_error_string (util_status_t errnum)\r
++{\r
++ switch (errnum) {\r
++ case UTIL_SUCCESS:\r
++ return "none";\r
++ case UTIL_OUT_OF_MEMORY:\r
++ return "out of memory";\r
++ case UTIL_EOF:\r
++ return "end of file";\r
++ case UTIL_ERRNO:\r
++ return strerror (errno);\r
++ case UTIL_GZERROR:\r
++ /* we lack context to be more informative here */\r
++ return "zlib error";\r
++ default:\r
++ INTERNAL_ERROR("unexpected error status %d", errnum);\r
++ }\r
++}\r
+diff --git a/util/util.h b/util/util.h\r
+index 8663cfc..d12fadb 100644\r
+--- a/util/util.h\r
++++ b/util/util.h\r
+@@ -2,11 +2,28 @@\r
+ #define _UTIL_H\r
+ \r
+ typedef enum util_status {\r
++ /**\r
++ * No error occurred.\r
++ */\r
+ UTIL_SUCCESS = 0,\r
+- UTIL_ERROR = 1,\r
++ /**\r
++ * Out of memory.\r
++ */\r
+ UTIL_OUT_OF_MEMORY,\r
++ /**\r
++ * End of stream reached while attempting to read.\r
++ */\r
+ UTIL_EOF,\r
+- UTIL_FILE,\r
++ /**\r
++ * Low level error occured, consult errno.\r
++ */\r
++ UTIL_ERRNO,\r
++ /**\r
++ * Zlib error occured, call gzerror for details.\r
++ */\r
++ UTIL_GZERROR\r
+ } util_status_t;\r
+ \r
++const char *\r
++util_error_string (util_status_t status);\r
+ #endif\r
+diff --git a/util/zlib-extra.c b/util/zlib-extra.c\r
+index 922ab52..cb34845 100644\r
+--- a/util/zlib-extra.c\r
++++ b/util/zlib-extra.c\r
+@@ -54,9 +54,9 @@ gz_getline (void *talloc_ctx, char **bufptr, ssize_t *bytes_read, gzFile stream)\r
+ else\r
+ goto SUCCESS;\r
+ case Z_ERRNO:\r
+- return UTIL_FILE;\r
++ return UTIL_ERRNO;\r
+ default:\r
+- return UTIL_ERROR;\r
++ return UTIL_GZERROR;\r
+ }\r
+ }\r
+ \r
+@@ -75,3 +75,11 @@ gz_getline (void *talloc_ctx, char **bufptr, ssize_t *bytes_read, gzFile stream)\r
+ *bytes_read = offset;\r
+ return UTIL_SUCCESS;\r
+ }\r
++\r
++const char *gz_error_string (util_status_t status, gzFile file) \r
++{\r
++ if (status == UTIL_GZERROR)\r
++ return gzerror (file, NULL);\r
++ else\r
++ return util_error_string (status);\r
++}\r
+diff --git a/util/zlib-extra.h b/util/zlib-extra.h\r
+index ed67115..dbaa0b9 100644\r
+--- a/util/zlib-extra.h\r
++++ b/util/zlib-extra.h\r
+@@ -4,8 +4,22 @@\r
+ #include "util.h"\r
+ #include <zlib.h>\r
+ \r
+-/* Like getline, but read from a gzFile. Allocation is with talloc */\r
++/* Like getline, but read from a gzFile. Allocation is with talloc.\r
++ * Returns:\r
++ *\r
++ * UTIL_SUCCESS, UTIL_OUT_OF_MEMORY, UTIL_ERRNO, UTIL_GZERROR\r
++ * Consult util.h for description\r
++ *\r
++ * UTIL_EOF End of file encountered before \r
++ * any characters read\r
++ */\r
+ util_status_t\r
+ gz_getline (void *ctx, char **lineptr, ssize_t *bytes_read, gzFile stream);\r
+ \r
++/* return a suitable error string based on the return status\r
++ * from gz_readline\r
++ */\r
++\r
++const char *\r
++gz_error_string (util_status_t status, gzFile stream);\r
+ #endif\r