unofficial mirror of notmuch@notmuchmail.org
 help / color / mirror / code / Atom feed
From: Ethan Glasser-Camp <ethan.glasser.camp@gmail.com>
To: notmuch@notmuchmail.org
Cc: Ethan Glasser-Camp <ethan@betacantrips.com>
Subject: [PATCH v2 6/8] mailstore: support for mbox:// URIs
Date: Sun,  1 Jul 2012 12:39:48 -0400	[thread overview]
Message-ID: <1341160790-14525-7-git-send-email-ethan@betacantrips.com> (raw)
In-Reply-To: <1341160790-14525-1-git-send-email-ethan@betacantrips.com>

No code uses this yet.

Signed-off-by: Ethan Glasser-Camp <ethan@betacantrips.com>
---
 lib/mailstore.c |  117 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 116 insertions(+), 1 deletion(-)

diff --git a/lib/mailstore.c b/lib/mailstore.c
index 48acd47..a29d734 100644
--- a/lib/mailstore.c
+++ b/lib/mailstore.c
@@ -17,18 +17,133 @@
  *
  * Author: Carl Worth <cworth@cworth.org>
  */
+#include <uriparser/Uri.h>
 #include <stdio.h>
+#include <glib.h>
 
 #include "notmuch-private.h"
 
+static FILE *
+notmuch_mailstore_basic_open (const char *filename)
+{
+    return fopen (filename, "r");
+}
+
+/* Since we have to return a FILE*, we use fmemopen to turn buffers
+ * into FILE* streams. But when we close these streams, we have to
+ * free() the buffers. Use a hash to associate the two.
+ */
+static GHashTable *_mbox_files_to_strings = NULL;
+
+static void
+_ensure_mbox_files_to_strings () {
+    if (_mbox_files_to_strings == NULL)
+        _mbox_files_to_strings = g_hash_table_new (NULL, NULL);
+}
+
+static FILE *
+notmuch_mailstore_mbox_open (UriUriA *uri)
+{
+    FILE *ret = NULL, *mbox = NULL;
+    char *filename, *message, *length_s;
+    const char *error;
+    long int offset, length, this_read;
+    _ensure_mbox_files_to_strings ();
+
+    offset = strtol (uri->fragment.first, &length_s, 10);
+    length = strtol (length_s+1, NULL, 10);
+
+    filename = talloc_strndup (NULL, uri->pathHead->text.first-1,
+                               uri->pathTail->text.afterLast-uri->pathHead->text.first+1);
+
+    if (filename == NULL)
+        goto DONE;
+
+    mbox = fopen (filename, "r");
+    if (mbox == NULL) {
+        fprintf (stderr, "Couldn't open message %s: %s.\n", uri->scheme.first,
+                 strerror (errno));
+        goto DONE;
+    }
+
+    message = talloc_array (NULL, char, length);
+    fseek (mbox, offset, SEEK_SET);
+
+    this_read = fread (message, sizeof(char), length, mbox);
+    if (this_read != length) {
+        if (feof (mbox))
+            error = "end of file reached";
+        if (ferror (mbox))
+            error = strerror (ferror (mbox));
+
+        fprintf (stderr, "Couldn't read message %s: %s.\n", uri->scheme.first, error);
+        goto DONE;
+    }
+
+    ret = fmemopen (message, length, "r");
+    if (ret == NULL) {
+        /* No fclose will ever be called, so let's free message now */
+        talloc_free (message);
+        goto DONE;
+    }
+
+    g_hash_table_insert (_mbox_files_to_strings, ret, message);
+DONE:
+    if (filename)
+        talloc_free (filename);
+    if (mbox)
+        fclose (mbox);
+
+    return ret;
+}
+
 FILE *
 notmuch_mailstore_open (const char *filename)
 {
-    return fopen (filename, "r");
+    FILE *ret = NULL;
+    UriUriA parsed;
+    UriParserStateA state;
+    state.uri = &parsed;
+    if (uriParseUriA (&state, filename) != URI_SUCCESS) {
+        /* Failure. Fall back to fopen and hope for the best. */
+        ret = notmuch_mailstore_basic_open (filename);
+        goto DONE;
+    }
+
+    if (parsed.scheme.first == NULL) {
+        /* No scheme. Probably not really a URL but just an ordinary
+         * filename, such as a Maildir message. */
+        ret = notmuch_mailstore_basic_open (filename);
+        goto DONE;
+    }
+
+    if (0 == strncmp (parsed.scheme.first, "mbox",
+                      parsed.scheme.afterLast-parsed.scheme.first)) {
+        /* mbox URI of the form mbox:///path/to/file#offset+length.
+         * Just pass the parsed URI. */
+        ret = notmuch_mailstore_mbox_open (&parsed);
+        goto DONE;
+    }
+
+    /* Default case */
+    fprintf (stderr, "Error: Could not open URI %s: unknown scheme.\n",
+             filename);
+
+DONE:
+    uriFreeUriMembersA (&parsed);
+    return ret;
 }
 
 int
 notmuch_mailstore_close (FILE *file)
 {
+    char *file_buffer;
+    if (_mbox_files_to_strings != NULL) {
+        file_buffer = g_hash_table_lookup (_mbox_files_to_strings, file);
+        if (file_buffer != NULL)
+            talloc_free (file_buffer);
+
+        g_hash_table_remove (_mbox_files_to_strings, file);
+    }
     return fclose (file);
 }
-- 
1.7.9.5

  parent reply	other threads:[~2012-07-01 16:46 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-06-25 20:41 [RFC PATCH 00/14] modular mail stores based on URIs Ethan Glasser-Camp
2012-06-25 20:41 ` [RFC PATCH 01/14] All access to mail files goes through the mailstore module Ethan Glasser-Camp
2012-06-28 20:48   ` Mark Walters
2012-06-25 20:41 ` [RFC PATCH 02/14] Introduce uriparser Ethan Glasser-Camp
2012-06-25 20:41 ` [RFC PATCH 03/14] mailstore can read from maildir: URLs Ethan Glasser-Camp
2012-06-25 20:41 ` [RFC PATCH 04/14] Not all filenames need to be converted to absolute paths Ethan Glasser-Camp
2012-06-27  9:17 ` [RFC PATCH 00/14] modular mail stores based on URIs Mark Walters
2012-06-28  7:39   ` Ethan
2012-06-28 15:13     ` David Bremner
2012-06-28 20:41       ` Robert Horn
2012-06-28 20:45     ` Mark Walters
2012-07-01 16:02       ` Ethan
2012-07-01 16:39         ` [PATCH v2 0/8] URI-based modular mail stores Ethan Glasser-Camp
2012-07-01 16:39           ` [PATCH v2 1/8] All access to mail files goes through the mailstore module Ethan Glasser-Camp
2012-07-01 19:48             ` Mark Walters
2012-07-01 16:39           ` [PATCH v2 2/8] Introduce uriparser Ethan Glasser-Camp
2012-07-01 16:39           ` [PATCH v2 3/8] Not all filenames need to be converted to absolute paths Ethan Glasser-Camp
2012-07-01 16:39           ` [PATCH v2 4/8] new: add "scan" option Ethan Glasser-Camp
2012-07-01 16:39           ` [PATCH v2 5/8] notmuch-new: pull out useful bits of add_files_recursive Ethan Glasser-Camp
2012-07-01 19:55             ` Mark Walters
2012-07-01 16:39           ` Ethan Glasser-Camp [this message]
2012-07-01 16:39           ` [PATCH v2 7/8] Tests for mbox support Ethan Glasser-Camp
2012-07-01 16:39           ` [PATCH v2 8/8] new: Add scan support for mbox:// URIs Ethan Glasser-Camp
2012-07-01 16:48         ` [RFC PATCH 00/14] modular mail stores based on URIs Mark Walters
2012-07-03  8:40         ` Jameson Graef Rollins
2012-06-28 17:36 ` Jameson Graef Rollins
2012-06-28 18:39   ` Ethan
2012-06-28 22:00 ` Mark Walters
2012-06-29  6:43   ` Ethan
2012-06-29  7:00     ` Mark Walters
2012-06-29  7:43     ` Jani Nikula

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://notmuchmail.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1341160790-14525-7-git-send-email-ethan@betacantrips.com \
    --to=ethan.glasser.camp@gmail.com \
    --cc=ethan@betacantrips.com \
    --cc=notmuch@notmuchmail.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://yhetil.org/notmuch.git/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).