Return-Path: X-Original-To: notmuch@notmuchmail.org Delivered-To: notmuch@notmuchmail.org Received: from localhost (localhost [127.0.0.1]) by olra.theworths.org (Postfix) with ESMTP id 90FC8431FD5 for ; Sun, 1 Jul 2012 09:46:53 -0700 (PDT) X-Virus-Scanned: Debian amavisd-new at olra.theworths.org X-Spam-Flag: NO X-Spam-Score: 1.061 X-Spam-Level: * X-Spam-Status: No, score=1.061 tagged_above=-999 required=5 tests=[DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_BL_SPAMCOP_NET=1.246, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_SORBS_WEB=0.614] autolearn=disabled Received: from olra.theworths.org ([127.0.0.1]) by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Z03ZRztmBC2A for ; Sun, 1 Jul 2012 09:46:52 -0700 (PDT) Received: from mail-wg0-f45.google.com (mail-wg0-f45.google.com [74.125.82.45]) (using TLSv1 with cipher RC4-SHA (128/128 bits)) (No client certificate requested) by olra.theworths.org (Postfix) with ESMTPS id 9F494431FAF for ; Sun, 1 Jul 2012 09:46:52 -0700 (PDT) Received: by wgbdt14 with SMTP id dt14so3721202wgb.2 for ; Sun, 01 Jul 2012 09:46:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=54eATWlqXhrQjA1ylMkbX/ULIrBItf9YQiBbwo+7pI8=; b=n/z7wpE7Qot4PKORZumWR2bRqzQLf1OU4CkGmHBrVBsbpvfeZhvwhmtLpNMk2TtLhb 9FSEqWmKeZXG/25Oo6Dp6XdHODi+EbGReQTrdLD8I7K3Lsz8TpObrEd+rgbtoSDlBztf dbqdJUYLBnItSTm2I6P1YXb0OGRDWiGCRnuTeNFtWRr/VeWpGB1vY35OVnnUObtcKLW6 wziXOfNR8HIjXhi1mbwNd2MUAX4nn0YhyiDS5gndluFJRj7ybgWS/UTYNP3/RM6iF3le yINm4d01L3QplolPU9OStvOP5prE0TknkjMoKmK6euNIJSIkgyhIJC5p4lL4awCcVF0u cVVw== Received: by 10.180.81.10 with SMTP id v10mr17893561wix.17.1341161211300; Sun, 01 Jul 2012 09:46:51 -0700 (PDT) Received: from localhost ([195.24.209.21]) by mx.google.com with ESMTPS id y2sm19711605wix.7.2012.07.01.09.46.35 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 01 Jul 2012 09:46:46 -0700 (PDT) From: Ethan Glasser-Camp To: notmuch@notmuchmail.org Subject: [PATCH v2 6/8] mailstore: support for mbox:// URIs Date: Sun, 1 Jul 2012 12:39:48 -0400 Message-Id: <1341160790-14525-7-git-send-email-ethan@betacantrips.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1341160790-14525-1-git-send-email-ethan@betacantrips.com> References: <1341160790-14525-1-git-send-email-ethan@betacantrips.com> Cc: Ethan Glasser-Camp X-BeenThere: notmuch@notmuchmail.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: "Use and development of the notmuch mail system." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 01 Jul 2012 16:46:53 -0000 No code uses this yet. Signed-off-by: Ethan Glasser-Camp --- 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 */ +#include #include +#include #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