[PATCH 3/3] cli/notmuch-show: support gzipped files
David Bremner
david at tethera.net
Sat Mar 30 07:06:33 PDT 2019
This drops "file" from mime_node_context and just uses a local
variable. It also uses the new gzip aware utility routines recently
added to util/gmime-extra.c. The use of gzopen / gzfile in addition is
a bit icky, but the choice is between that, and providing yet another
readline implimentation that understands GMime streams.
---
mime-node.c | 22 +++++++++---------
notmuch-show.c | 50 +++++++++++++++++++++++------------------
test/T740-gzip.sh | 57 ++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 95 insertions(+), 34 deletions(-)
diff --git a/mime-node.c b/mime-node.c
index 2a24e537..4170da03 100644
--- a/mime-node.c
+++ b/mime-node.c
@@ -21,13 +21,16 @@
* Austin Clements <aclements at csail.mit.edu>
*/
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
#include "notmuch-client.h"
/* Context that gets inherited from the root node. */
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 +51,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 +62,7 @@ mime_node_open (const void *ctx, notmuch_message_t *message,
mime_node_context_t *mctx;
mime_node_t *root;
notmuch_status_t status;
+ int fd;
root = talloc_zero (ctx, mime_node_t);
if (root == NULL) {
@@ -80,8 +81,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) {
+ fd = open (filename, O_RDONLY);
+ if (fd == -1) {
/* 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 +93,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)
+ fd = open (filename, O_RDONLY);
+ if (fd != -1)
break;
}
talloc_free (filenames);
- if (! mctx->file) {
+ if (fd == -1) {
/* Give up */
fprintf (stderr, "Error opening %s: %s\n", filename, strerror (errno));
status = NOTMUCH_STATUS_FILE_ERROR;
@@ -106,13 +107,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 (fd);
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..4b48c64e 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,44 @@ 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;
- size_t size;
+ GMimeStream *stream = NULL;
+ ssize_t ssize;
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");
- if (file == NULL) {
+ stream = g_mime_stream_gzfile_open (filename);
+ if (stream == 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)) {
+ while (! g_mime_stream_eos (stream)) {
+ ssize = g_mime_stream_read (stream, buf, sizeof(buf));
+ if (ssize < 0) {
fprintf (stderr, "Error: Read failed from %s\n", filename);
- fclose (file);
- return NOTMUCH_STATUS_FILE_ERROR;
+ goto DONE;
}
- if (fwrite (buf, size, 1, stdout) != 1) {
- fprintf (stderr, "Error: Write failed\n");
- fclose (file);
- return NOTMUCH_STATUS_FILE_ERROR;
+ if (ssize > 0 && fwrite (buf, ssize, 1, stdout) != 1) {
+ fprintf (stderr, "Error: Write %ld chars to stdout failed\n", ssize);
+ 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 (stream)
+ g_object_unref (stream);
+
+ 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 96464956..5b678fa1 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 at notmuch-test-suite | notmuch_show_sanitize > OUTPUT
+cat <<EOF > EXPECTED
+From test_suite at notmuchmail.org Fri Jan 5 15:43:51 2001
+From: Notmuch Test Suite <test_suite at notmuchmail.org>
+To: Notmuch Test Suite <test_suite at notmuchmail.org>
+Message-Id: <msg-006 at notmuch-test-suite>
+Subject: Multiple new messages, one gzipped (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 at notmuch-test-suite | notmuch_show_sanitize > OUTPUT
+cat <<EOF > EXPECTED
+From: Notmuch Test Suite <test_suite at notmuchmail.org>
+To: Notmuch Test Suite <test_suite at notmuchmail.org>
+Message-Id: <msg-006 at notmuch-test-suite>
+Subject: Multiple new messages, one gzipped (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 at notmuch-test-suite | notmuch_show_sanitize > OUTPUT
cat <<EOF > EXPECTED
message{ id:msg-007 at 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 at notmuch-test-suite | notmuch_show_sanitize > OUTPUT
+cat <<EOF > EXPECTED
+From test_suite at notmuchmail.org Fri Jan 5 15:43:50 2001
+From: Notmuch Test Suite <test_suite at notmuchmail.org>
+To: Notmuch Test Suite <test_suite at notmuchmail.org>
+Message-Id: <msg-007 at 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 at notmuch-test-suite | notmuch_show_sanitize > OUTPUT
+cat <<EOF > EXPECTED
+From: Notmuch Test Suite <test_suite at notmuchmail.org>
+To: Notmuch Test Suite <test_suite at notmuchmail.org>
+Message-Id: <msg-007 at 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
More information about the notmuch
mailing list