1 Return-Path: <bremner@tesseract.cs.unb.ca>
\r
2 X-Original-To: notmuch@notmuchmail.org
\r
3 Delivered-To: notmuch@notmuchmail.org
\r
4 Received: from localhost (localhost [127.0.0.1])
\r
5 by olra.theworths.org (Postfix) with ESMTP id AEFF1431FD0
\r
6 for <notmuch@notmuchmail.org>; Sun, 28 Sep 2014 11:29:13 -0700 (PDT)
\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org
\r
11 X-Spam-Status: No, score=0 tagged_above=-999 required=5 tests=[none]
\r
13 Received: from olra.theworths.org ([127.0.0.1])
\r
14 by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)
\r
15 with ESMTP id vttyfHCfwrR7 for <notmuch@notmuchmail.org>;
\r
16 Sun, 28 Sep 2014 11:29:08 -0700 (PDT)
\r
17 Received: from yantan.tethera.net (yantan.tethera.net [199.188.72.155])
\r
18 (using TLSv1 with cipher DHE-RSA-AES128-SHA (128/128 bits))
\r
19 (No client certificate requested)
\r
20 by olra.theworths.org (Postfix) with ESMTPS id 7F2FE431FD2
\r
21 for <notmuch@notmuchmail.org>; Sun, 28 Sep 2014 11:29:01 -0700 (PDT)
\r
22 Received: from remotemail by yantan.tethera.net with local (Exim 4.80)
\r
23 (envelope-from <bremner@tesseract.cs.unb.ca>)
\r
24 id 1XYJDR-0005gE-6N; Sun, 28 Sep 2014 15:29:01 -0300
\r
25 Received: (nullmailer pid 31290 invoked by uid 1000); Sun, 28 Sep 2014
\r
27 From: David Bremner <david@tethera.net>
\r
28 To: notmuch@notmuchmail.org
\r
29 Subject: [WIP 3/3] lib: add configuration framework.
\r
30 Date: Sun, 28 Sep 2014 20:28:19 +0200
\r
31 Message-Id: <1411928899-29625-4-git-send-email-david@tethera.net>
\r
32 X-Mailer: git-send-email 2.1.0
\r
33 In-Reply-To: <1411928899-29625-1-git-send-email-david@tethera.net>
\r
34 References: <87iok8vog6.fsf@steelpick.2x.cz>
\r
35 <1411928899-29625-1-git-send-email-david@tethera.net>
\r
36 X-BeenThere: notmuch@notmuchmail.org
\r
37 X-Mailman-Version: 2.1.13
\r
39 List-Id: "Use and development of the notmuch mail system."
\r
40 <notmuch.notmuchmail.org>
\r
41 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,
\r
42 <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>
\r
43 List-Archive: <http://notmuchmail.org/pipermail/notmuch>
\r
44 List-Post: <mailto:notmuch@notmuchmail.org>
\r
45 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>
\r
46 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,
\r
47 <mailto:notmuch-request@notmuchmail.org?subject=subscribe>
\r
48 X-List-Received-Date: Sun, 28 Sep 2014 18:29:14 -0000
\r
50 Allow clients to atomically get and set key value pairs.
\r
52 lib/Makefile.local | 1 +
\r
53 lib/config.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++++
\r
54 lib/notmuch.h | 7 +++
\r
55 test/Makefile.local | 7 +++
\r
56 test/T560-lib-config.sh | 15 +++++
\r
57 test/config-test.c | 28 +++++++++
\r
58 6 files changed, 214 insertions(+)
\r
59 create mode 100644 lib/config.c
\r
60 create mode 100755 test/T560-lib-config.sh
\r
61 create mode 100644 test/config-test.c
\r
63 diff --git a/lib/Makefile.local b/lib/Makefile.local
\r
64 index 4120390..7ca2b3b 100644
\r
65 --- a/lib/Makefile.local
\r
66 +++ b/lib/Makefile.local
\r
67 @@ -54,6 +54,7 @@ lib := $(dir)
\r
69 libnotmuch_c_srcs = \
\r
70 $(notmuch_compat_srcs) \
\r
72 $(dir)/filenames.c \
\r
73 $(dir)/string-list.c \
\r
75 diff --git a/lib/config.c b/lib/config.c
\r
76 new file mode 100644
\r
77 index 0000000..c3b8f39
\r
81 +#include "notmuch-private.h"
\r
82 +#include "string-util.h"
\r
83 +#include "file-util.h"
\r
84 +#include <talloc.h>
\r
86 +static notmuch_status_t
\r
87 +compute_paths (void *ctx, const char *notmuch_path, const char *key,
\r
88 + char **parent_out, char **dest_out) {
\r
90 + char *parent, *dest, *final_component, *last_slash;
\r
92 + parent = talloc_asprintf (ctx, "%s/config/%s", notmuch_path, key);
\r
94 + return NOTMUCH_STATUS_OUT_OF_MEMORY;
\r
96 + last_slash = strrchr (parent, '/');
\r
97 + *last_slash = '\0';
\r
99 + final_component = talloc_strdup (ctx, last_slash + 1);
\r
101 + dest = talloc_asprintf(ctx, "%s/_%s", parent, final_component);
\r
103 + return NOTMUCH_STATUS_OUT_OF_MEMORY;
\r
105 + *parent_out = parent;
\r
106 + *dest_out = dest;
\r
108 + return NOTMUCH_STATUS_SUCCESS;
\r
113 +notmuch_config_get (const char *notmuch_path, const char *key, const char **val){
\r
115 + char *line = NULL;
\r
116 + size_t line_size;
\r
117 + ssize_t line_len;
\r
118 + char *buf = NULL;
\r
119 + char *file_name, *parent;
\r
120 + notmuch_status_t status;
\r
121 + void *local = NULL;
\r
122 + FILE *file_ptr = NULL;
\r
124 + if (notmuch_path == NULL || key == NULL || val == NULL)
\r
125 + return NOTMUCH_STATUS_NULL_POINTER;
\r
127 + local = talloc_new (NULL);
\r
129 + status = compute_paths (local, notmuch_path, key, &parent, &file_name);
\r
133 + file_ptr = fopen (file_name, "r");
\r
134 + if (file_ptr == NULL) {
\r
135 + status = NOTMUCH_STATUS_FILE_ERROR;
\r
139 + while ((line_len = getline (&line, &line_size, file_ptr)) != -1) {
\r
142 + buf = talloc_asprintf (local, "%s%s", buf, line);
\r
144 + buf = talloc_strdup (local, line);
\r
146 + if (buf == NULL) {
\r
147 + status = NOTMUCH_STATUS_OUT_OF_MEMORY;
\r
154 + /* remove the last newline. Convenient for the single line case. */
\r
155 + chomp_newline (buf);
\r
158 + status = NOTMUCH_STATUS_SUCCESS;
\r
165 + fclose (file_ptr);
\r
167 + talloc_free (local);
\r
173 +notmuch_config_set (const char *notmuch_path, const char *key, const char *val){
\r
175 + char *parent, *path, *temp_path;
\r
177 + notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;
\r
178 + void *local = NULL;
\r
181 + if (notmuch_path == NULL || key == NULL || val == NULL)
\r
182 + return NOTMUCH_STATUS_NULL_POINTER;
\r
184 + if (has_double_dot_component (key))
\r
185 + return NOTMUCH_STATUS_UNSUPPORTED_OPERATION;
\r
187 + local = talloc_new (NULL);
\r
189 + status = compute_paths (local, notmuch_path, key, &parent, &path);
\r
193 + if (! mkdir_recursive (local, parent, 0700)) {
\r
194 + status = NOTMUCH_STATUS_FILE_ERROR;
\r
198 + temp_path = talloc_asprintf (local, "%s/tmp.XXXXXX", parent);
\r
199 + if (temp_path == NULL) {
\r
200 + status = NOTMUCH_STATUS_OUT_OF_MEMORY;
\r
204 + out_fd = mkstemp (temp_path);
\r
205 + if (out_fd == -1) {
\r
206 + status = NOTMUCH_STATUS_FILE_ERROR;
\r
210 + out_file = fdopen (out_fd, "w");
\r
211 + if (out_file == NULL) {
\r
212 + status = NOTMUCH_STATUS_FILE_ERROR;
\r
216 + if (fputs (val, out_file) == EOF) {
\r
217 + status = NOTMUCH_STATUS_FILE_ERROR;
\r
221 + if (fclose (out_file)) {
\r
222 + status = NOTMUCH_STATUS_FILE_ERROR;
\r
226 + if (rename (temp_path, path) < 0) {
\r
227 + status = NOTMUCH_STATUS_FILE_ERROR;
\r
233 + talloc_free(local);
\r
237 diff --git a/lib/notmuch.h b/lib/notmuch.h
\r
238 index fe2340b..9a5f9df 100644
\r
239 --- a/lib/notmuch.h
\r
240 +++ b/lib/notmuch.h
\r
241 @@ -192,6 +192,13 @@ typedef struct _notmuch_directory notmuch_directory_t;
\r
242 typedef struct _notmuch_filenames notmuch_filenames_t;
\r
243 #endif /* __DOXYGEN__ */
\r
247 +notmuch_config_get (const char *notmuch_path, const char *key, const char **val);
\r
250 +notmuch_config_set (const char *notmuch_path, const char *key, const char *val);
\r
253 * Create a new, empty notmuch database located at 'path'.
\r
255 diff --git a/test/Makefile.local b/test/Makefile.local
\r
256 index a2d58fc..8a203f0 100644
\r
257 --- a/test/Makefile.local
\r
258 +++ b/test/Makefile.local
\r
259 @@ -23,6 +23,9 @@ random_corpus_deps = $(dir)/random-corpus.o $(dir)/database-test.o \
\r
260 lib/libnotmuch.a util/libutil.a \
\r
261 parse-time-string/libparse-time-string.a
\r
263 +config_test_deps = $(dir)/config-test.o \
\r
264 + lib/libnotmuch.a util/libutil.a
\r
266 $(dir)/random-corpus: $(random_corpus_deps)
\r
267 $(call quiet,CXX) $(CFLAGS_FINAL) $^ -o $@ $(CONFIGURE_LDFLAGS)
\r
269 @@ -38,6 +41,9 @@ $(dir)/parse-time: $(dir)/parse-time.o parse-time-string/parse-time-string.o
\r
270 $(dir)/make-db-version: $(dir)/make-db-version.o
\r
271 $(call quiet,CXX) $^ -o $@ $(XAPIAN_LDFLAGS)
\r
273 +$(dir)/config-test: $(config_test_deps)
\r
274 + $(call quiet,CXX) $(CFLAGS_FINAL) $^ -o $@ $(CONFIGURE_LDFLAGS)
\r
278 test_main_srcs=$(dir)/arg-test.c \
\r
279 @@ -47,6 +53,7 @@ test_main_srcs=$(dir)/arg-test.c \
\r
280 $(dir)/smtp-dummy.c \
\r
281 $(dir)/symbol-test.cc \
\r
282 $(dir)/make-db-version.cc \
\r
283 + $(dir)/config-test.c \
\r
285 test_srcs=$(test_main_srcs) $(dir)/database-test.c
\r
287 diff --git a/test/T560-lib-config.sh b/test/T560-lib-config.sh
\r
288 new file mode 100755
\r
289 index 0000000..ec8ddbe
\r
291 +++ b/test/T560-lib-config.sh
\r
293 +#!/usr/bin/env bash
\r
294 +test_description="library config handling"
\r
298 +test_begin_subtest "getting and setting"
\r
299 +${TEST_DIRECTORY}/config-test ${MAIL_DIR}/.notmuch set a foo
\r
300 +${TEST_DIRECTORY}/config-test ${MAIL_DIR}/.notmuch set a/b bar
\r
301 +${TEST_DIRECTORY}/config-test ${MAIL_DIR}/.notmuch set b/a fub
\r
302 +${TEST_DIRECTORY}/config-test ${MAIL_DIR}/.notmuch get a >> OUTPUT
\r
303 +${TEST_DIRECTORY}/config-test ${MAIL_DIR}/.notmuch get a/b >> OUTPUT
\r
304 +${TEST_DIRECTORY}/config-test ${MAIL_DIR}/.notmuch get b/a >> OUTPUT
\r
305 +test_expect_equal "$(cat OUTPUT)" "foobarfub"
\r
308 diff --git a/test/config-test.c b/test/config-test.c
\r
309 new file mode 100644
\r
310 index 0000000..d9a1116
\r
312 +++ b/test/config-test.c
\r
314 +#include <stdio.h>
\r
315 +#include <string.h>
\r
317 +#include "notmuch.h"
\r
320 +main (int argc, char **argv) {
\r
322 + notmuch_status_t status;
\r
324 + if (argc == 4 && strcmp (argv[2], "get") == 0) {
\r
326 + status = notmuch_config_get (argv[1], argv[3], &val);
\r
329 + fputs (val, stdout);
\r
332 + } else if (argc == 5 && strcmp (argv[2], "set") == 0) {
\r
334 + status = notmuch_config_set (argv[1], argv[3], argv[4]);
\r