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 (®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 <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