Re: Avoiding the "huge INBOX of death"
[notmuch-archives.git] / 08 / c39df99b4a585cfb7fcd4fa7dee87137150473
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 80ABA431FD8\r
6         for <notmuch@notmuchmail.org>; Sun, 28 Sep 2014 11:29:24 -0700 (PDT)\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
8 X-Spam-Flag: NO\r
9 X-Spam-Score: 0\r
10 X-Spam-Level: \r
11 X-Spam-Status: No, score=0 tagged_above=-999 required=5 tests=[none]\r
12         autolearn=disabled\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 xS4RMl-BkY4h for <notmuch@notmuchmail.org>;\r
16         Sun, 28 Sep 2014 11:29:19 -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 B2600431FDC\r
21         for <notmuch@notmuchmail.org>; Sun, 28 Sep 2014 11:29:07 -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 1XYJDX-0005gR-8c; Sun, 28 Sep 2014 15:29:07 -0300\r
25 Received: (nullmailer pid 31288 invoked by uid 1000); Sun, 28 Sep 2014\r
26         18:28:49 -0000\r
27 From: David Bremner <david@tethera.net>\r
28 To: notmuch@notmuchmail.org\r
29 Subject: [WIP 2/3] cli/insert: move several file/directory manipulation\r
30         routines into a new util file.\r
31 Date: Sun, 28 Sep 2014 20:28:18 +0200\r
32 Message-Id: <1411928899-29625-3-git-send-email-david@tethera.net>\r
33 X-Mailer: git-send-email 2.1.0\r
34 In-Reply-To: <1411928899-29625-1-git-send-email-david@tethera.net>\r
35 References: <87iok8vog6.fsf@steelpick.2x.cz>\r
36         <1411928899-29625-1-git-send-email-david@tethera.net>\r
37 X-BeenThere: notmuch@notmuchmail.org\r
38 X-Mailman-Version: 2.1.13\r
39 Precedence: list\r
40 List-Id: "Use and development of the notmuch mail system."\r
41         <notmuch.notmuchmail.org>\r
42 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
43         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
44 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
45 List-Post: <mailto:notmuch@notmuchmail.org>\r
46 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
47 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
48         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
49 X-List-Received-Date: Sun, 28 Sep 2014 18:29:25 -0000\r
50 \r
51 This will promote code sharing of low level file operations.\r
52 ---\r
53  notmuch-insert.c    | 79 ++----------------------------------------\r
54  util/Makefile.local |  1 +\r
55  util/file-util.c    | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++\r
56  util/file-util.h    | 20 +++++++++++\r
57  4 files changed, 121 insertions(+), 77 deletions(-)\r
58  create mode 100644 util/file-util.c\r
59  create mode 100644 util/file-util.h\r
60 \r
61 diff --git a/notmuch-insert.c b/notmuch-insert.c\r
62 index 5ef6e66..48bdd28 100644\r
63 --- a/notmuch-insert.c\r
64 +++ b/notmuch-insert.c\r
65 @@ -23,6 +23,7 @@\r
66  \r
67  #include "notmuch-client.h"\r
68  #include "tag-util.h"\r
69 +#include "file-util.h"\r
70  \r
71  #include <sys/types.h>\r
72  #include <sys/stat.h>\r
73 @@ -63,26 +64,6 @@ safe_gethostname (char *hostname, size_t len)\r
74      }\r
75  }\r
76  \r
77 -/* Call fsync() on a directory path. */\r
78 -static notmuch_bool_t\r
79 -sync_dir (const char *dir)\r
80 -{\r
81 -    int fd, r;\r
82 -\r
83 -    fd = open (dir, O_RDONLY);\r
84 -    if (fd == -1) {\r
85 -       fprintf (stderr, "Error: open %s: %s\n", dir, strerror (errno));\r
86 -       return FALSE;\r
87 -    }\r
88 -\r
89 -    r = fsync (fd);\r
90 -    if (r)\r
91 -       fprintf (stderr, "Error: fsync %s: %s\n", dir, strerror (errno));\r
92 -\r
93 -    close (fd);\r
94 -\r
95 -    return r == 0;\r
96 -}\r
97  \r
98  /*\r
99   * Check the specified folder name does not contain a directory\r
100 @@ -92,65 +73,9 @@ sync_dir (const char *dir)\r
101  static notmuch_bool_t\r
102  is_valid_folder_name (const char *folder)\r
103  {\r
104 -    const char *p = folder;\r
105 -\r
106 -    for (;;) {\r
107 -       if ((p[0] == '.') && (p[1] == '.') && (p[2] == '\0' || p[2] == '/'))\r
108 -           return FALSE;\r
109 -       p = strchr (p, '/');\r
110 -       if (!p)\r
111 -           return TRUE;\r
112 -       p++;\r
113 -    }\r
114 +    return ! has_double_dot_component (folder);\r
115  }\r
116  \r
117 -/*\r
118 - * Make the given directory and its parents as necessary, using the\r
119 - * given mode. Return TRUE on success, FALSE otherwise. Partial\r
120 - * results are not cleaned up on errors.\r
121 - */\r
122 -static notmuch_bool_t\r
123 -mkdir_recursive (const void *ctx, const char *path, int mode)\r
124 -{\r
125 -    struct stat st;\r
126 -    int r;\r
127 -    char *parent = NULL, *slash;\r
128 -\r
129 -    /* First check the common case: directory already exists. */\r
130 -    r = stat (path, &st);\r
131 -    if (r == 0) {\r
132 -        if (! S_ISDIR (st.st_mode)) {\r
133 -           fprintf (stderr, "Error: '%s' is not a directory: %s\n",\r
134 -                    path, strerror (EEXIST));\r
135 -           return FALSE;\r
136 -       }\r
137 -\r
138 -       return TRUE;\r
139 -    } else if (errno != ENOENT) {\r
140 -       fprintf (stderr, "Error: stat '%s': %s\n", path, strerror (errno));\r
141 -       return FALSE;\r
142 -    }\r
143 -\r
144 -    /* mkdir parents, if any */\r
145 -    slash = strrchr (path, '/');\r
146 -    if (slash && slash != path) {\r
147 -       parent = talloc_strndup (ctx, path, slash - path);\r
148 -       if (! parent) {\r
149 -           fprintf (stderr, "Error: %s\n", strerror (ENOMEM));\r
150 -           return FALSE;\r
151 -       }\r
152 -\r
153 -       if (! mkdir_recursive (ctx, parent, mode))\r
154 -           return FALSE;\r
155 -    }\r
156 -\r
157 -    if (mkdir (path, mode)) {\r
158 -       fprintf (stderr, "Error: mkdir '%s': %s\n", path, strerror (errno));\r
159 -       return FALSE;\r
160 -    }\r
161 -\r
162 -    return parent ? sync_dir (parent) : TRUE;\r
163 -}\r
164  \r
165  /*\r
166   * Create the given maildir folder, i.e. maildir and its\r
167 diff --git a/util/Makefile.local b/util/Makefile.local\r
168 index 905f237..8749cfb 100644\r
169 --- a/util/Makefile.local\r
170 +++ b/util/Makefile.local\r
171 @@ -5,6 +5,7 @@ extra_cflags += -I$(srcdir)/$(dir)\r
172  \r
173  libutil_c_srcs := $(dir)/xutil.c $(dir)/error_util.c $(dir)/hex-escape.c \\r
174                   $(dir)/string-util.c $(dir)/talloc-extra.c $(dir)/zlib-extra.c \\r
175 +                 $(dir)/file-util.c \\r
176                 $(dir)/util.c\r
177  \r
178  libutil_modules := $(libutil_c_srcs:.c=.o)\r
179 diff --git a/util/file-util.c b/util/file-util.c\r
180 new file mode 100644\r
181 index 0000000..66c4485\r
182 --- /dev/null\r
183 +++ b/util/file-util.c\r
184 @@ -0,0 +1,98 @@\r
185 +#include <errno.h>\r
186 +#include <fcntl.h>\r
187 +#include <stdio.h>\r
188 +#include <string.h>\r
189 +#include <sys/stat.h>\r
190 +#include <sys/types.h>\r
191 +#include <talloc.h>\r
192 +#include <unistd.h>\r
193 +\r
194 +#include "file-util.h"\r
195 +\r
196 +/*\r
197 + * Check whether specified path name contains a directory\r
198 + * component "..". to prevent writes outside of the Maildir\r
199 + */\r
200 +int\r
201 +has_double_dot_component (const char *path)\r
202 +{\r
203 +    const char *p = path;\r
204 +\r
205 +    for (;;) {\r
206 +       if ((p[0] == '.') && (p[1] == '.') && (p[2] == '\0' || p[2] == '/'))\r
207 +           return TRUE;\r
208 +       p = strchr (p, '/');\r
209 +       if (!p)\r
210 +           return FALSE;\r
211 +       p++;\r
212 +    }\r
213 +}\r
214 +\r
215 +/*\r
216 + * Make the given directory and its parents as necessary, using the\r
217 + * given mode. return TRUE on success, 0 otherwise. Partial\r
218 + * results are not cleaned up on errors.\r
219 + */\r
220 +int\r
221 +mkdir_recursive (const void *ctx, const char *path, int mode)\r
222 +{\r
223 +    struct stat st;\r
224 +    int r;\r
225 +    char *parent = NULL, *slash;\r
226 +\r
227 +    /* First check the common case: directory already exists. */\r
228 +    r = stat (path, &st);\r
229 +    if (r == 0) {\r
230 +        if (! S_ISDIR (st.st_mode)) {\r
231 +           fprintf (stderr, "Error: '%s' is not a directory: %s\n",\r
232 +                    path, strerror (EEXIST));\r
233 +           return FALSE;\r
234 +       }\r
235 +\r
236 +       return TRUE;\r
237 +    } else if (errno != ENOENT) {\r
238 +       fprintf (stderr, "Error: stat '%s': %s\n", path, strerror (errno));\r
239 +       return FALSE;\r
240 +    }\r
241 +\r
242 +    /* mkdir parents, if any */\r
243 +    slash = strrchr (path, '/');\r
244 +    if (slash && slash != path) {\r
245 +       parent = talloc_strndup (ctx, path, slash - path);\r
246 +       if (! parent) {\r
247 +           fprintf (stderr, "Error: %s\n", strerror (ENOMEM));\r
248 +           return FALSE;\r
249 +       }\r
250 +\r
251 +       if (! mkdir_recursive (ctx, parent, mode))\r
252 +           return FALSE;\r
253 +    }\r
254 +\r
255 +    if (mkdir (path, mode)) {\r
256 +       fprintf (stderr, "Error: mkdir '%s': %s\n", path, strerror (errno));\r
257 +       return FALSE;\r
258 +    }\r
259 +\r
260 +    return parent ? sync_dir (parent) : TRUE;\r
261 +}\r
262 +\r
263 +/* Call fsync() on a directory path. */\r
264 +int\r
265 +sync_dir (const char *dir)\r
266 +{\r
267 +    int fd, r;\r
268 +\r
269 +    fd = open (dir, O_RDONLY);\r
270 +    if (fd == -1) {\r
271 +       fprintf (stderr, "Error: open %s: %s\n", dir, strerror (errno));\r
272 +       return FALSE;\r
273 +    }\r
274 +\r
275 +    r = fsync (fd);\r
276 +    if (r)\r
277 +       fprintf (stderr, "Error: fsync %s: %s\n", dir, strerror (errno));\r
278 +\r
279 +    close (fd);\r
280 +\r
281 +    return r == 0;\r
282 +}\r
283 diff --git a/util/file-util.h b/util/file-util.h\r
284 new file mode 100644\r
285 index 0000000..4f96957\r
286 --- /dev/null\r
287 +++ b/util/file-util.h\r
288 @@ -0,0 +1,20 @@\r
289 +#ifndef _FILE_UTIL_H\r
290 +#define _FILE_UTIL_H\r
291 +\r
292 +#ifndef FALSE \r
293 +#define FALSE 0\r
294 +#endif\r
295 +#ifndef TRUE\r
296 +#define TRUE 1\r
297 +#endif\r
298 +\r
299 +int\r
300 +has_double_dot_component (const char *path);\r
301 +\r
302 +int\r
303 +mkdir_recursive (const void *ctx, const char *path, int mode);\r
304 +\r
305 +int\r
306 +sync_dir (const char *path);\r
307 +\r
308 +#endif\r
309 -- \r
310 2.1.0\r
311 \r