[WIP 2/2] WIP/notmuch-show: support gzipped files

Subject: [WIP 2/2] WIP/notmuch-show: support gzipped files

Date: Sun, 24 Mar 2019 00:32:44 -0300

To: David Bremner, notmuch@notmuchmail.org

Cc:

From: David Bremner


This drops "file" from mime_node_context and just uses a local variable.
---
 mime-node.c       | 18 ++++++---------
 notmuch-show.c    | 50 +++++++++++++++++++++++++----------------
 test/T740-gzip.sh | 57 ++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 94 insertions(+), 31 deletions(-)

diff --git a/mime-node.c b/mime-node.c
index 2a24e537..a77acef0 100644
--- a/mime-node.c
+++ b/mime-node.c
@@ -27,7 +27,6 @@
 typedef struct mime_node_context {
     /* Per-message resources.  These are allocated internally and must
      * be destroyed. */
-    FILE *file;
     GMimeStream *stream;
     GMimeParser *parser;
     GMimeMessage *mime_message;
@@ -48,9 +47,6 @@ _mime_node_context_free (mime_node_context_t *res)
     if (res->stream)
 	g_object_unref (res->stream);
 
-    if (res->file)
-	fclose (res->file);
-
     return 0;
 }
 
@@ -62,6 +58,7 @@ mime_node_open (const void *ctx, notmuch_message_t *message,
     mime_node_context_t *mctx;
     mime_node_t *root;
     notmuch_status_t status;
+    FILE *file;
 
     root = talloc_zero (ctx, mime_node_t);
     if (root == NULL) {
@@ -80,8 +77,8 @@ mime_node_open (const void *ctx, notmuch_message_t *message,
     talloc_set_destructor (mctx, _mime_node_context_free);
 
     /* Fast path */
-    mctx->file = fopen (filename, "r");
-    if (! mctx->file) {
+    file = fopen (filename, "r");
+    if (! file) {
 	/* Slow path - for some reason the first file in the list is
 	 * not available anymore. This is clearly a problem in the
 	 * database, but we are not going to let this problem be a
@@ -92,13 +89,13 @@ mime_node_open (const void *ctx, notmuch_message_t *message,
 	     notmuch_filenames_move_to_next (filenames))
 	{
 	    filename = notmuch_filenames_get (filenames);
-	    mctx->file = fopen (filename, "r");
-	    if (mctx->file)
+	    file = fopen (filename, "r");
+	    if (file)
 		break;
 	}
 
 	talloc_free (filenames);
-	if (! mctx->file) {
+	if (! file) {
 	    /* Give up */
 	    fprintf (stderr, "Error opening %s: %s\n", filename, strerror (errno));
 		status = NOTMUCH_STATUS_FILE_ERROR;
@@ -106,13 +103,12 @@ mime_node_open (const void *ctx, notmuch_message_t *message,
 	    }
 	}
 
-    mctx->stream = g_mime_stream_file_new (mctx->file);
+    mctx->stream = g_mime_stream_gzfile_new (file);
     if (!mctx->stream) {
 	fprintf (stderr, "Out of memory.\n");
 	status = NOTMUCH_STATUS_OUT_OF_MEMORY;
 	goto DONE;
     }
-    g_mime_stream_file_set_owner (GMIME_STREAM_FILE (mctx->stream), false);
 
     mctx->parser = g_mime_parser_new_with_stream (mctx->stream);
     if (!mctx->parser) {
diff --git a/notmuch-show.c b/notmuch-show.c
index 07e9a5db..5f63b07e 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -21,6 +21,7 @@
 #include "notmuch-client.h"
 #include "gmime-filter-reply.h"
 #include "sprinter.h"
+#include "zlib-extra.h"
 
 static const char *
 _get_tags_as_string (const void *ctx, notmuch_message_t *message)
@@ -781,7 +782,7 @@ format_part_mbox (const void *ctx, unused (sprinter_t *sp), mime_node_t *node,
     notmuch_message_t *message = node->envelope_file;
 
     const char *filename;
-    FILE *file;
+    gzFile file;
     const char *from;
 
     time_t date;
@@ -789,14 +790,14 @@ format_part_mbox (const void *ctx, unused (sprinter_t *sp), mime_node_t *node,
     char date_asctime[26];
 
     char *line = NULL;
-    size_t line_size;
+    ssize_t line_size;
     ssize_t line_len;
 
     if (!message)
 	INTERNAL_ERROR ("format_part_mbox requires a root part");
 
     filename = notmuch_message_get_filename (message);
-    file = fopen (filename, "r");
+    file = gzopen (filename, "r");
     if (file == NULL) {
 	fprintf (stderr, "Failed to open %s: %s\n",
 		 filename, strerror (errno));
@@ -812,7 +813,7 @@ format_part_mbox (const void *ctx, unused (sprinter_t *sp), mime_node_t *node,
 
     printf ("From %s %s", from, date_asctime);
 
-    while ((line_len = getline (&line, &line_size, file)) != -1 ) {
+    while ((line_len = gz_getline (message, &line, &line_size, file)) != UTIL_EOF ) {
 	if (_is_from_line (line))
 	    putchar ('>');
 	printf ("%s", line);
@@ -820,7 +821,7 @@ format_part_mbox (const void *ctx, unused (sprinter_t *sp), mime_node_t *node,
 
     printf ("\n");
 
-    fclose (file);
+    gzclose (file);
 
     return NOTMUCH_STATUS_SUCCESS;
 }
@@ -833,39 +834,50 @@ format_part_raw (unused (const void *ctx), unused (sprinter_t *sp),
     if (node->envelope_file) {
 	/* Special case the entire message to avoid MIME parsing. */
 	const char *filename;
-	FILE *file;
+	gzFile file = NULL;
 	size_t size;
 	char buf[4096];
+	notmuch_status_t ret = NOTMUCH_STATUS_FILE_ERROR;
 
 	filename = notmuch_message_get_filename (node->envelope_file);
 	if (filename == NULL) {
 	    fprintf (stderr, "Error: Cannot get message filename.\n");
-	    return NOTMUCH_STATUS_FILE_ERROR;
+	    goto DONE;
 	}
 
-	file = fopen (filename, "r");
+	file = gzopen (filename, "r");
 	if (file == NULL) {
 	    fprintf (stderr, "Error: Cannot open file %s: %s\n", filename, strerror (errno));
-	    return NOTMUCH_STATUS_FILE_ERROR;
+	    goto DONE;
 	}
 
-	while (!feof (file)) {
-	    size = fread (buf, 1, sizeof (buf), file);
-	    if (ferror (file)) {
-		fprintf (stderr, "Error: Read failed from %s\n", filename);
-		fclose (file);
-		return NOTMUCH_STATUS_FILE_ERROR;
+	while (!gzeof (file)) {
+	    size = gzread (file, buf, 1);
+	    if (size != 1) {
+		int zlib_status = 0;
+		gzerror (file, &zlib_status);
+		if (zlib_status == Z_OK)
+		    break;
+		else {
+		    fprintf (stderr, "Error: Read failed from %s\n", filename);
+		}
+		goto DONE;
 	    }
 
 	    if (fwrite (buf, size, 1, stdout) != 1) {
 		fprintf (stderr, "Error: Write failed\n");
-		fclose (file);
-		return NOTMUCH_STATUS_FILE_ERROR;
+		goto DONE;
 	    }
 	}
 
-	fclose (file);
-	return NOTMUCH_STATUS_SUCCESS;
+	ret = NOTMUCH_STATUS_SUCCESS;
+
+	/* XXX This DONE is just for the special case of a node in a single file */
+    DONE:
+	if (file)
+	    gzclose (file);
+
+	return ret;
     }
 
     GMimeStream *stream_filter = g_mime_stream_filter_new (params->out_stream);
diff --git a/test/T740-gzip.sh b/test/T740-gzip.sh
index 26f22aa0..e4c72b8a 100755
--- a/test/T740-gzip.sh
+++ b/test/T740-gzip.sh
@@ -91,8 +91,35 @@ This is just a test message (#6)
 EOF
 test_expect_equal_file EXPECTED OUTPUT
 
+test_begin_subtest "show un-gzipped message (format mbox)"
+notmuch show --format=mbox id:msg-006@notmuch-test-suite | notmuch_show_sanitize > OUTPUT
+cat <<EOF > EXPECTED
+From test_suite@notmuchmail.org Fri Jan  5 15:43:51 2001
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To: Notmuch Test Suite <test_suite@notmuchmail.org>
+Message-Id: <msg-006@notmuch-test-suite>
+Subject: Multiple new messages (full-scan)
+Date: Fri, 05 Jan 2001 15:43:51 +0000
+
+This is just a test message (#6)
+
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest "show un-gzipped message (format raw)"
+notmuch show --format=raw id:msg-006@notmuch-test-suite | notmuch_show_sanitize > OUTPUT
+cat <<EOF > EXPECTED
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To: Notmuch Test Suite <test_suite@notmuchmail.org>
+Message-Id: <msg-006@notmuch-test-suite>
+Subject: Multiple new messages (full-scan)
+Date: Fri, 05 Jan 2001 15:43:51 +0000
+
+This is just a test message (#6)
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+
 test_begin_subtest "show gzipped message"
-test_subtest_known_broken
 notmuch show id:msg-007@notmuch-test-suite | notmuch_show_sanitize > OUTPUT
 cat <<EOF > EXPECTED
 message{ id:msg-007@notmuch-test-suite depth:0 match:1 excluded:0 filename:/XXX/mail/msg-007.gz
@@ -112,4 +139,32 @@ This is just a test message (#7)
 EOF
 test_expect_equal_file EXPECTED OUTPUT
 
+test_begin_subtest "show gzipped message (mbox)"
+notmuch show --format=mbox id:msg-007@notmuch-test-suite | notmuch_show_sanitize > OUTPUT
+cat <<EOF > EXPECTED
+From test_suite@notmuchmail.org Fri Jan  5 15:43:50 2001
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To: Notmuch Test Suite <test_suite@notmuchmail.org>
+Message-Id: <msg-007@notmuch-test-suite>
+Subject: Renamed (gzipped) message
+Date: Fri, 05 Jan 2001 15:43:50 +0000
+
+This is just a test message (#7)
+
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest "show gzipped message (raw)"
+notmuch show --format=raw id:msg-007@notmuch-test-suite | notmuch_show_sanitize > OUTPUT
+cat <<EOF > EXPECTED
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To: Notmuch Test Suite <test_suite@notmuchmail.org>
+Message-Id: <msg-007@notmuch-test-suite>
+Subject: Renamed (gzipped) message
+Date: Fri, 05 Jan 2001 15:43:50 +0000
+
+This is just a test message (#7)
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+
 test_done
-- 
2.20.1

_______________________________________________
notmuch mailing list
notmuch@notmuchmail.org
https://notmuchmail.org/mailman/listinfo/notmuch

Thread: