Return-Path: X-Original-To: notmuch@notmuchmail.org Delivered-To: notmuch@notmuchmail.org Received: from localhost (localhost [127.0.0.1]) by olra.theworths.org (Postfix) with ESMTP id D9475431FAF for ; Sat, 5 Apr 2014 08:44:39 -0700 (PDT) X-Virus-Scanned: Debian amavisd-new at olra.theworths.org X-Spam-Flag: NO X-Spam-Score: 0 X-Spam-Level: X-Spam-Status: No, score=0 tagged_above=-999 required=5 tests=[none] autolearn=disabled Received: from olra.theworths.org ([127.0.0.1]) by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id YKXB9MuOeEk8 for ; Sat, 5 Apr 2014 08:44:33 -0700 (PDT) Received: from mx.xen14.node3324.gplhost.com (gitolite.debian.net [87.98.215.224]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by olra.theworths.org (Postfix) with ESMTPS id A93AD431FAE for ; Sat, 5 Apr 2014 08:44:33 -0700 (PDT) Received: from remotemail by mx.xen14.node3324.gplhost.com with local (Exim 4.72) (envelope-from ) id 1WWSlS-00082G-IP for notmuch@notmuchmail.org; Sat, 05 Apr 2014 15:44:14 +0000 Received: (nullmailer pid 10909 invoked by uid 1000); Sat, 05 Apr 2014 15:43:58 -0000 From: David Bremner To: notmuch@notmuchmail.org Subject: v7 gzip dump restore patches Date: Sat, 5 Apr 2014 12:43:50 -0300 Message-Id: <1396712636-10640-1-git-send-email-david@tethera.net> X-Mailer: git-send-email 1.9.0 X-BeenThere: notmuch@notmuchmail.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: "Use and development of the notmuch mail system." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 05 Apr 2014 15:44:40 -0000 Supercedes id:1396554083-3892-2-git-send-email-david@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 (®ex); - 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 +#include + +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 -/* 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