[PATCH v2 6/8] mailstore: support for mbox:// URIs
Ethan Glasser-Camp
ethan.glasser.camp at gmail.com
Sun Jul 1 09:39:48 PDT 2012
No code uses this yet.
Signed-off-by: Ethan Glasser-Camp <ethan at 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 at 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
More information about the notmuch
mailing list