Share folder implementation between mbox, mh and maildir. Fix mu_folder_delete.
* include/mailutils/folder.h (_mu_fsfolder_init): New proto. * include/mailutils/mailbox.h (mu_mailbox_create_at): New proto. * libmailutils/mailbox/mailbox.c (mu_mailbox_create_at): New function. * libmailutils/mailbox/Makefile.am (libmailbox_la_SOURCES): Add fsfolder.c * libmailutils/mailbox/folder.c (mu_folder_delete): If folder does not provide its own method for deletion, use mu_mailbox_remove. (mu_folder_open, mu_folder_close, mu_folder_enumerate) (mu_folder_lsub, mu_folder_subscribe, mu_folder_unsubscribe) (mu_folder_rename): Return EINVAL if folder is NULL. (mu_folder_match): Bugfix: don't pass folder flags to fnmatch. * libmailutils/mailbox/fsfolder.c: New file. Implementation of file-system based folders. * libmailutils/mailbox/mailbox (_create_mailbox0): Propagate error return from mu_registrar_lookup_url. * libmailutils/tests/fsfolder00.at: New test case. * libmailutils/tests/fsfolder01.at: New test case. * libmailutils/tests/fsfolder02.at: New test case. * libmailutils/tests/Makefile.am (noinst_PROGRAMS): Add fsfolder. (TESTSUITE_AT): Add fsfolder tests. * libmailutils/tests/testsuite.at: Include fsfolder tests. * libproto/mbox/folder.c: Use fsfolder. (_mh_is_scheme): Check file even if scheme matches. * libproto/maildir/folder.c: Likewise. (_maildir_is_scheme): Check file even if scheme matches. * libproto/mh/folder.c: Likewise. * testsuite/fldel.c: New file. * testsuite/Makefile.am (noinst_PROGRAMS): Buld fldel.
Showing
20 changed files
with
1271 additions
and
567 deletions
... | @@ -92,6 +92,8 @@ extern int mu_folder_get_property (mu_folder_t, mu_property_t *); | ... | @@ -92,6 +92,8 @@ extern int mu_folder_get_property (mu_folder_t, mu_property_t *); |
92 | extern int mu_folder_decrement (mu_folder_t); | 92 | extern int mu_folder_decrement (mu_folder_t); |
93 | 93 | ||
94 | extern void mu_list_response_free (void *data); | 94 | extern void mu_list_response_free (void *data); |
95 | |||
96 | int _mu_fsfolder_init (mu_folder_t folder); | ||
95 | 97 | ||
96 | #ifdef __cplusplus | 98 | #ifdef __cplusplus |
97 | } | 99 | } | ... | ... |
... | @@ -43,6 +43,8 @@ extern int mu_mailbox_create_from_record (mu_mailbox_t *pmbox, | ... | @@ -43,6 +43,8 @@ extern int mu_mailbox_create_from_record (mu_mailbox_t *pmbox, |
43 | mu_record_t record, | 43 | mu_record_t record, |
44 | const char *name); | 44 | const char *name); |
45 | extern int mu_mailbox_create_default (mu_mailbox_t *, const char *); | 45 | extern int mu_mailbox_create_default (mu_mailbox_t *, const char *); |
46 | extern int mu_mailbox_create_at (mu_mailbox_t *pmbox, mu_folder_t folder, | ||
47 | const char *name); | ||
46 | 48 | ||
47 | extern void mu_mailbox_destroy (mu_mailbox_t *); | 49 | extern void mu_mailbox_destroy (mu_mailbox_t *); |
48 | 50 | ... | ... |
... | @@ -36,6 +36,7 @@ | ... | @@ -36,6 +36,7 @@ |
36 | #include <mailutils/url.h> | 36 | #include <mailutils/url.h> |
37 | #include <mailutils/errno.h> | 37 | #include <mailutils/errno.h> |
38 | #include <mailutils/property.h> | 38 | #include <mailutils/property.h> |
39 | #include <mailutils/mailbox.h> | ||
39 | 40 | ||
40 | #include <mailutils/sys/folder.h> | 41 | #include <mailutils/sys/folder.h> |
41 | 42 | ||
... | @@ -49,7 +50,7 @@ static struct mu_monitor folder_lock = MU_MONITOR_INITIALIZER; | ... | @@ -49,7 +50,7 @@ static struct mu_monitor folder_lock = MU_MONITOR_INITIALIZER; |
49 | int | 50 | int |
50 | mu_folder_match (const char *name, void *pattern, int flags) | 51 | mu_folder_match (const char *name, void *pattern, int flags) |
51 | { | 52 | { |
52 | return fnmatch (pattern, name[0] == '/' ? name + 1 : name, flags); | 53 | return fnmatch (pattern, name[0] == '/' ? name + 1 : name, 0); |
53 | } | 54 | } |
54 | 55 | ||
55 | /* A folder could be remote (IMAP), or local(a spool directory) like $HOME/Mail | 56 | /* A folder could be remote (IMAP), or local(a spool directory) like $HOME/Mail |
... | @@ -249,7 +250,9 @@ mu_folder_get_property (mu_folder_t folder, mu_property_t *prop) | ... | @@ -249,7 +250,9 @@ mu_folder_get_property (mu_folder_t folder, mu_property_t *prop) |
249 | int | 250 | int |
250 | mu_folder_open (mu_folder_t folder, int flags) | 251 | mu_folder_open (mu_folder_t folder, int flags) |
251 | { | 252 | { |
252 | if (folder == NULL || folder->_open == NULL) | 253 | if (folder == NULL) |
254 | return EINVAL; | ||
255 | if (folder->_open == NULL) | ||
253 | return ENOSYS; | 256 | return ENOSYS; |
254 | return folder->_open (folder, flags); | 257 | return folder->_open (folder, flags); |
255 | } | 258 | } |
... | @@ -257,7 +260,9 @@ mu_folder_open (mu_folder_t folder, int flags) | ... | @@ -257,7 +260,9 @@ mu_folder_open (mu_folder_t folder, int flags) |
257 | int | 260 | int |
258 | mu_folder_close (mu_folder_t folder) | 261 | mu_folder_close (mu_folder_t folder) |
259 | { | 262 | { |
260 | if (folder == NULL || folder->_close == NULL) | 263 | if (folder == NULL) |
264 | return EINVAL; | ||
265 | if (folder->_close == NULL) | ||
261 | return ENOSYS; | 266 | return ENOSYS; |
262 | return folder->_close (folder); | 267 | return folder->_close (folder); |
263 | } | 268 | } |
... | @@ -381,8 +386,10 @@ mu_folder_enumerate (mu_folder_t folder, const char *name, | ... | @@ -381,8 +386,10 @@ mu_folder_enumerate (mu_folder_t folder, const char *name, |
381 | mu_folder_enumerate_fp enumfun, void *enumdata) | 386 | mu_folder_enumerate_fp enumfun, void *enumdata) |
382 | { | 387 | { |
383 | int status; | 388 | int status; |
384 | if (folder == NULL || folder->_list == NULL) | 389 | if (folder == NULL) |
385 | return EINVAL; | 390 | return EINVAL; |
391 | else if (folder->_list == NULL) | ||
392 | return ENOSYS; | ||
386 | else | 393 | else |
387 | { | 394 | { |
388 | mu_list_t list = NULL; | 395 | mu_list_t list = NULL; |
... | @@ -412,7 +419,9 @@ mu_folder_lsub (mu_folder_t folder, const char *dirname, const char *basename, | ... | @@ -412,7 +419,9 @@ mu_folder_lsub (mu_folder_t folder, const char *dirname, const char *basename, |
412 | { | 419 | { |
413 | int status; | 420 | int status; |
414 | 421 | ||
415 | if (folder == NULL || folder->_lsub == NULL) | 422 | if (folder == NULL) |
423 | return EINVAL; | ||
424 | else if (folder->_lsub == NULL) | ||
416 | return ENOSYS; | 425 | return ENOSYS; |
417 | else | 426 | else |
418 | { | 427 | { |
... | @@ -428,31 +437,64 @@ mu_folder_lsub (mu_folder_t folder, const char *dirname, const char *basename, | ... | @@ -428,31 +437,64 @@ mu_folder_lsub (mu_folder_t folder, const char *dirname, const char *basename, |
428 | int | 437 | int |
429 | mu_folder_subscribe (mu_folder_t folder, const char *name) | 438 | mu_folder_subscribe (mu_folder_t folder, const char *name) |
430 | { | 439 | { |
431 | if (folder == NULL || folder->_subscribe == NULL) | 440 | if (folder == NULL) |
432 | return EINVAL; | 441 | return EINVAL; |
442 | if (folder->_subscribe == NULL) | ||
443 | return ENOSYS; | ||
433 | return folder->_subscribe (folder, name); | 444 | return folder->_subscribe (folder, name); |
434 | } | 445 | } |
435 | 446 | ||
436 | int | 447 | int |
437 | mu_folder_unsubscribe (mu_folder_t folder, const char *name) | 448 | mu_folder_unsubscribe (mu_folder_t folder, const char *name) |
438 | { | 449 | { |
439 | if (folder == NULL || folder->_unsubscribe == NULL) | 450 | if (folder == NULL) |
440 | return EINVAL; | 451 | return EINVAL; |
452 | if (folder->_unsubscribe == NULL) | ||
453 | return ENOSYS; | ||
441 | return folder->_unsubscribe (folder, name); | 454 | return folder->_unsubscribe (folder, name); |
442 | } | 455 | } |
443 | 456 | ||
444 | int | 457 | int |
445 | mu_folder_delete (mu_folder_t folder, const char *name) | 458 | mu_folder_delete (mu_folder_t folder, const char *name) |
446 | { | 459 | { |
447 | if (folder == NULL || folder->_delete == NULL) | 460 | int rc; |
448 | return ENOSYS; | 461 | |
449 | return folder->_delete (folder, name); | 462 | if (folder == NULL) |
463 | return EINVAL; | ||
464 | if (folder->_delete) | ||
465 | rc = folder->_delete (folder, name); | ||
466 | else | ||
467 | { | ||
468 | /* If there is no folder-specific _delete method, then try to create the | ||
469 | mailbox and call mailbox delete (remove) method. This is necessary | ||
470 | because certain types of mailboxes share a common folder (e.g. mbox, | ||
471 | maildir and mh all use filesystem folder), but have a different | ||
472 | internal structure. Supplying mu_folder_t with a knowledge of mailbox | ||
473 | internals will harm separation of concerns. On the other hand, | ||
474 | removing something without looking into it may well yield undesired | ||
475 | results. For example, a MH mailbox can hold another mailboxes, i.e. | ||
476 | be a folder itself. Removing it blindly would result in removing | ||
477 | these mailboxes as well, which is clearly not indended. | ||
478 | |||
479 | To solve this folder and mailbox delete methods are tightly paired, | ||
480 | but without looking into each-others internal mechanisms. */ | ||
481 | mu_mailbox_t mbox; | ||
482 | rc = mu_mailbox_create_at (&mbox, folder, name); | ||
483 | if (rc == 0) | ||
484 | { | ||
485 | rc = mu_mailbox_remove (mbox); | ||
486 | mu_mailbox_destroy (&mbox); | ||
487 | } | ||
488 | } | ||
489 | return rc; | ||
450 | } | 490 | } |
451 | 491 | ||
452 | int | 492 | int |
453 | mu_folder_rename (mu_folder_t folder, const char *oldname, const char *newname) | 493 | mu_folder_rename (mu_folder_t folder, const char *oldname, const char *newname) |
454 | { | 494 | { |
455 | if (folder == NULL || folder->_rename == NULL) | 495 | if (folder == NULL) |
496 | return EINVAL; | ||
497 | if (folder->_rename == NULL) | ||
456 | return ENOSYS; | 498 | return ENOSYS; |
457 | return folder->_rename (folder, oldname, newname); | 499 | return folder->_rename (folder, oldname, newname); |
458 | } | 500 | } | ... | ... |
libmailutils/mailbox/fsfolder.c
0 → 100644
1 | /* Implementation of file-system folder for GNU Mailutils | ||
2 | Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008, | ||
3 | 2010, 2011 Free Software Foundation, Inc. | ||
4 | |||
5 | This library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Lesser General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 3 of the License, or (at your option) any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Lesser General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Lesser General | ||
16 | Public License along with this library. If not, see | ||
17 | <http://www.gnu.org/licenses/>. */ | ||
18 | |||
19 | #ifdef HAVE_CONFIG_H | ||
20 | # include <config.h> | ||
21 | #endif | ||
22 | |||
23 | #include <errno.h> | ||
24 | #include <sys/types.h> | ||
25 | #include <dirent.h> | ||
26 | #include <sys/stat.h> | ||
27 | #include <fcntl.h> | ||
28 | #include <unistd.h> | ||
29 | #include <string.h> | ||
30 | #include <glob.h> | ||
31 | #include <fnmatch.h> | ||
32 | #include <stdio.h> | ||
33 | #include <stdlib.h> | ||
34 | |||
35 | #include <mailutils/sys/folder.h> | ||
36 | #include <mailutils/sys/registrar.h> | ||
37 | |||
38 | #include <mailutils/auth.h> | ||
39 | #include <mailutils/url.h> | ||
40 | #include <mailutils/stream.h> | ||
41 | #include <mailutils/util.h> | ||
42 | #include <mailutils/errno.h> | ||
43 | #include <mailutils/debug.h> | ||
44 | #include <mailutils/property.h> | ||
45 | #include <mailutils/iterator.h> | ||
46 | |||
47 | /* File-system folder is shared between UNIX mbox, maildir and MH | ||
48 | mailboxes. It implements all usual folder methods, excepting | ||
49 | for _delete, which is implemented on the mailbox level. See | ||
50 | comment to mu_folder_delete in folder.c */ | ||
51 | |||
52 | struct _mu_fsfolder | ||
53 | { | ||
54 | char *dirname; | ||
55 | mu_property_t subscription; | ||
56 | }; | ||
57 | |||
58 | static int | ||
59 | open_subscription (struct _mu_fsfolder *folder) | ||
60 | { | ||
61 | int rc; | ||
62 | mu_property_t prop; | ||
63 | mu_stream_t str; | ||
64 | char *filename = mu_make_file_name (folder->dirname, ".mu-subscr"); | ||
65 | |||
66 | rc = mu_file_stream_create (&str, filename, MU_STREAM_RDWR|MU_STREAM_CREAT); | ||
67 | if (rc) | ||
68 | return rc; | ||
69 | rc = mu_property_create_init (&prop, mu_assoc_property_init, str); | ||
70 | free (filename); | ||
71 | if (rc == 0) | ||
72 | folder->subscription = prop; | ||
73 | return rc; | ||
74 | } | ||
75 | |||
76 | |||
77 | static char * | ||
78 | get_pathname (const char *dirname, const char *basename) | ||
79 | { | ||
80 | char *pathname = NULL, *p; | ||
81 | |||
82 | /* Skip eventual protocol designator. */ | ||
83 | p = strchr (dirname, ':'); | ||
84 | if (p && p[1] == '/' && p[2] == '/') | ||
85 | dirname = p + 3; | ||
86 | |||
87 | /* null basename gives dirname. */ | ||
88 | if (basename == NULL) | ||
89 | pathname = (dirname) ? strdup (dirname) : strdup ("."); | ||
90 | /* Absolute. */ | ||
91 | else if (basename[0] == '/') | ||
92 | pathname = strdup (basename); | ||
93 | /* Relative. */ | ||
94 | else | ||
95 | { | ||
96 | size_t baselen = strlen (basename); | ||
97 | size_t dirlen = strlen (dirname); | ||
98 | while (dirlen > 0 && dirname[dirlen-1] == '/') | ||
99 | dirlen--; | ||
100 | pathname = calloc (dirlen + baselen + 2, sizeof (char)); | ||
101 | if (pathname) | ||
102 | { | ||
103 | memcpy (pathname, dirname, dirlen); | ||
104 | pathname[dirlen] = '/'; | ||
105 | strcpy (pathname + dirlen + 1, basename); | ||
106 | } | ||
107 | } | ||
108 | return pathname; | ||
109 | } | ||
110 | |||
111 | static void | ||
112 | _fsfolder_destroy (mu_folder_t folder) | ||
113 | { | ||
114 | if (folder->data) | ||
115 | { | ||
116 | struct _mu_fsfolder *fsfolder = folder->data; | ||
117 | free (fsfolder->dirname); | ||
118 | mu_property_destroy (&fsfolder->subscription); | ||
119 | free (folder->data); | ||
120 | folder->data = NULL; | ||
121 | } | ||
122 | } | ||
123 | |||
124 | /* Noop. */ | ||
125 | static int | ||
126 | _fsfolder_open (mu_folder_t folder, int flags MU_ARG_UNUSED) | ||
127 | { | ||
128 | struct _mu_fsfolder *fsfolder = folder->data; | ||
129 | if (flags & MU_STREAM_CREAT) | ||
130 | { | ||
131 | return (mkdir (fsfolder->dirname, S_IRWXU) == 0) ? 0 : errno; | ||
132 | } | ||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | /* Noop. */ | ||
137 | static int | ||
138 | _fsfolder_close (mu_folder_t folder MU_ARG_UNUSED) | ||
139 | { | ||
140 | int rc = 0; | ||
141 | struct _mu_fsfolder *fsfolder = folder->data; | ||
142 | |||
143 | if (fsfolder->subscription) | ||
144 | rc = mu_property_save (fsfolder->subscription); | ||
145 | return rc; | ||
146 | } | ||
147 | |||
148 | static int | ||
149 | _fsfolder_rename (mu_folder_t folder, const char *oldpath, | ||
150 | const char *newpath) | ||
151 | { | ||
152 | struct _mu_fsfolder *fsfolder = folder->data; | ||
153 | if (oldpath && newpath) | ||
154 | { | ||
155 | int status = 0; | ||
156 | char *pathold = get_pathname (fsfolder->dirname, oldpath); | ||
157 | if (pathold) | ||
158 | { | ||
159 | char *pathnew = get_pathname (fsfolder->dirname, newpath); | ||
160 | if (pathnew) | ||
161 | { | ||
162 | if (access (pathnew, F_OK) == 0) | ||
163 | status = EEXIST; | ||
164 | else if (rename (pathold, pathnew) != 0) | ||
165 | status = errno; | ||
166 | free (pathnew); | ||
167 | } | ||
168 | else | ||
169 | status = ENOMEM; | ||
170 | free (pathold); | ||
171 | } | ||
172 | else | ||
173 | status = ENOMEM; | ||
174 | return status; | ||
175 | } | ||
176 | return EINVAL; | ||
177 | } | ||
178 | |||
179 | struct inode_list /* Inode/dev number list used to cut off | ||
180 | recursion */ | ||
181 | { | ||
182 | struct inode_list *next; | ||
183 | ino_t inode; | ||
184 | dev_t dev; | ||
185 | }; | ||
186 | |||
187 | struct search_data | ||
188 | { | ||
189 | mu_list_t result; | ||
190 | mu_folder_enumerate_fp enumfun; | ||
191 | void *enumdata; | ||
192 | char *dirname; | ||
193 | size_t dirlen; | ||
194 | void *pattern; | ||
195 | int flags; | ||
196 | size_t max_level; | ||
197 | size_t errcnt; | ||
198 | mu_folder_t folder; | ||
199 | }; | ||
200 | |||
201 | static int | ||
202 | inode_list_lookup (struct inode_list *list, struct stat *st) | ||
203 | { | ||
204 | for (; list; list = list->next) | ||
205 | if (list->inode == st->st_ino && list->dev == st->st_dev) | ||
206 | return 1; | ||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | static int | ||
211 | list_helper (struct search_data *data, mu_record_t record, | ||
212 | const char *dirname, size_t level, | ||
213 | struct inode_list *ilist) | ||
214 | { | ||
215 | DIR *dirp; | ||
216 | struct dirent *dp; | ||
217 | int stop = 0; | ||
218 | |||
219 | if (data->max_level && level > data->max_level) | ||
220 | return 0; | ||
221 | |||
222 | dirp = opendir (dirname); | ||
223 | if (dirp == NULL) | ||
224 | { | ||
225 | mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_ERROR, | ||
226 | ("list_helper cannot open directory %s: %s", | ||
227 | dirname, mu_strerror (errno))); | ||
228 | data->errcnt++; | ||
229 | return 1; | ||
230 | } | ||
231 | |||
232 | if (!record) | ||
233 | { | ||
234 | int type; | ||
235 | mu_registrar_lookup (dirname, MU_FOLDER_ATTRIBUTE_ALL, | ||
236 | &record, &type); | ||
237 | } | ||
238 | |||
239 | while ((dp = readdir (dirp))) | ||
240 | { | ||
241 | char const *ename = dp->d_name; | ||
242 | char *fname; | ||
243 | struct stat st; | ||
244 | |||
245 | if (ename[ename[0] != '.' ? 0 : ename[1] != '.' ? 1 : 2] == 0) | ||
246 | continue; | ||
247 | if (strncmp (ename, ".mu-", 4) == 0) | ||
248 | continue; | ||
249 | fname = get_pathname (dirname, ename); | ||
250 | if (lstat (fname, &st) == 0) | ||
251 | { | ||
252 | int f; | ||
253 | if (S_ISDIR (st.st_mode)) | ||
254 | f = MU_FOLDER_ATTRIBUTE_DIRECTORY; | ||
255 | else if (S_ISREG (st.st_mode)) | ||
256 | f = MU_FOLDER_ATTRIBUTE_FILE; | ||
257 | else if (S_ISLNK (st.st_mode)) | ||
258 | f = MU_FOLDER_ATTRIBUTE_LINK; | ||
259 | else | ||
260 | f = 0; | ||
261 | if (mu_record_list_p (record, ename, f)) | ||
262 | { | ||
263 | if (data->folder->_match == NULL | ||
264 | || data->folder->_match (fname + data->dirlen + | ||
265 | ((data->dirlen > 1 | ||
266 | && data->dirname[data->dirlen-1] != '/') ? | ||
267 | 1 : 0), | ||
268 | data->pattern, | ||
269 | data->flags) == 0) | ||
270 | { | ||
271 | char *refname = fname; | ||
272 | int type = 0; | ||
273 | struct mu_list_response *resp; | ||
274 | mu_record_t rec = NULL; | ||
275 | |||
276 | resp = malloc (sizeof (*resp)); | ||
277 | if (resp == NULL) | ||
278 | { | ||
279 | mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_ERROR, | ||
280 | ("list_helper: %s", mu_strerror (ENOMEM))); | ||
281 | data->errcnt++; | ||
282 | free (fname); | ||
283 | continue; | ||
284 | } | ||
285 | |||
286 | mu_registrar_lookup (refname, MU_FOLDER_ATTRIBUTE_ALL, | ||
287 | &rec, &type); | ||
288 | |||
289 | resp->name = fname; | ||
290 | resp->level = level; | ||
291 | resp->separator = '/'; | ||
292 | resp->type = type; | ||
293 | resp->format = rec; | ||
294 | |||
295 | if (resp->type == 0) | ||
296 | { | ||
297 | free (resp->name); | ||
298 | free (resp); | ||
299 | continue; | ||
300 | } | ||
301 | |||
302 | if (data->enumfun) | ||
303 | { | ||
304 | if (data->enumfun (data->folder, resp, data->enumdata)) | ||
305 | { | ||
306 | free (resp->name); | ||
307 | free (resp); | ||
308 | stop = 1; | ||
309 | break; | ||
310 | } | ||
311 | } | ||
312 | |||
313 | if (data->result) | ||
314 | { | ||
315 | fname = NULL; | ||
316 | mu_list_append (data->result, resp); | ||
317 | } | ||
318 | else | ||
319 | free (resp); | ||
320 | |||
321 | if ((type & MU_FOLDER_ATTRIBUTE_DIRECTORY) | ||
322 | && !inode_list_lookup (ilist, &st)) | ||
323 | { | ||
324 | struct inode_list idata; | ||
325 | |||
326 | idata.inode = st.st_ino; | ||
327 | idata.dev = st.st_dev; | ||
328 | idata.next = ilist; | ||
329 | stop = list_helper (data, rec, refname, level + 1, | ||
330 | &idata); | ||
331 | } | ||
332 | } | ||
333 | else if (S_ISDIR (st.st_mode)) | ||
334 | { | ||
335 | struct inode_list idata; | ||
336 | |||
337 | idata.inode = st.st_ino; | ||
338 | idata.dev = st.st_dev; | ||
339 | idata.next = ilist; | ||
340 | stop = list_helper (data, NULL, fname, level + 1, &idata); | ||
341 | } | ||
342 | } | ||
343 | } | ||
344 | else | ||
345 | { | ||
346 | mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_ERROR, | ||
347 | ("list_helper cannot stat %s: %s", | ||
348 | fname, mu_strerror (errno))); | ||
349 | } | ||
350 | free (fname); | ||
351 | } | ||
352 | closedir (dirp); | ||
353 | return stop; | ||
354 | } | ||
355 | |||
356 | static int | ||
357 | _fsfolder_list (mu_folder_t folder, const char *ref, | ||
358 | void *pattern, | ||
359 | int flags, | ||
360 | size_t max_level, | ||
361 | mu_list_t flist, | ||
362 | mu_folder_enumerate_fp enumfun, void *enumdata) | ||
363 | { | ||
364 | struct _mu_fsfolder *fsfolder = folder->data; | ||
365 | struct inode_list iroot; | ||
366 | struct search_data sdata; | ||
367 | |||
368 | memset (&iroot, 0, sizeof iroot); | ||
369 | sdata.dirname = get_pathname (fsfolder->dirname, ref); | ||
370 | sdata.dirlen = strlen (sdata.dirname); | ||
371 | sdata.result = flist; | ||
372 | sdata.enumfun = enumfun; | ||
373 | sdata.enumdata = enumdata; | ||
374 | sdata.pattern = pattern; | ||
375 | sdata.flags = flags; | ||
376 | sdata.max_level = max_level; | ||
377 | sdata.folder = folder; | ||
378 | sdata.errcnt = 0; | ||
379 | list_helper (&sdata, NULL, sdata.dirname, 0, &iroot); | ||
380 | free (sdata.dirname); | ||
381 | /* FIXME: error code */ | ||
382 | return 0; | ||
383 | } | ||
384 | |||
385 | static int | ||
386 | _fsfolder_lsub (mu_folder_t folder, const char *ref, const char *name, | ||
387 | mu_list_t flist) | ||
388 | { | ||
389 | struct _mu_fsfolder *fsfolder = folder->data; | ||
390 | int rc; | ||
391 | char *pattern; | ||
392 | mu_iterator_t itr; | ||
393 | |||
394 | if (name == NULL || *name == '\0') | ||
395 | name = "*"; | ||
396 | |||
397 | if (!fsfolder->subscription && (rc = open_subscription (fsfolder))) | ||
398 | return rc; | ||
399 | |||
400 | pattern = mu_make_file_name (ref, name); | ||
401 | |||
402 | rc = mu_property_get_iterator (fsfolder->subscription, &itr); | ||
403 | if (rc == 0) | ||
404 | { | ||
405 | for (mu_iterator_first (itr); !mu_iterator_is_done (itr); | ||
406 | mu_iterator_next (itr)) | ||
407 | { | ||
408 | const char *key, *val; | ||
409 | |||
410 | mu_iterator_current_kv (itr, (const void **)&key, (void**)&val); | ||
411 | |||
412 | if (fnmatch (pattern, key, 0) == 0) | ||
413 | { | ||
414 | struct mu_list_response *resp; | ||
415 | resp = malloc (sizeof (*resp)); | ||
416 | if (resp == NULL) | ||
417 | { | ||
418 | rc = ENOMEM; | ||
419 | break; | ||
420 | } | ||
421 | else if ((resp->name = strdup (key)) == NULL) | ||
422 | { | ||
423 | free (resp); | ||
424 | rc = ENOMEM; | ||
425 | break; | ||
426 | } | ||
427 | resp->type = MU_FOLDER_ATTRIBUTE_FILE; | ||
428 | resp->level = 0; | ||
429 | resp->separator = '/'; | ||
430 | rc = mu_list_append (flist, resp); | ||
431 | if (rc) | ||
432 | { | ||
433 | free (resp); | ||
434 | break; | ||
435 | } | ||
436 | } | ||
437 | } | ||
438 | mu_iterator_destroy (&itr); | ||
439 | } | ||
440 | free (pattern); | ||
441 | return rc; | ||
442 | } | ||
443 | |||
444 | static int | ||
445 | _fsfolder_subscribe (mu_folder_t folder, const char *name) | ||
446 | { | ||
447 | struct _mu_fsfolder *fsfolder = folder->data; | ||
448 | int rc; | ||
449 | |||
450 | if (!fsfolder->subscription && (rc = open_subscription (fsfolder))) | ||
451 | return rc; | ||
452 | |||
453 | return mu_property_set_value (fsfolder->subscription, name, "", 1); | ||
454 | } | ||
455 | |||
456 | static int | ||
457 | _fsfolder_unsubscribe (mu_folder_t folder, const char *name) | ||
458 | { | ||
459 | struct _mu_fsfolder *fsfolder = folder->data; | ||
460 | int rc; | ||
461 | |||
462 | if (!fsfolder->subscription && (rc = open_subscription (fsfolder))) | ||
463 | return rc; | ||
464 | |||
465 | return mu_property_unset (fsfolder->subscription, name); | ||
466 | } | ||
467 | |||
468 | static int | ||
469 | _fsfolder_get_authority (mu_folder_t folder, mu_authority_t *pauth) | ||
470 | { | ||
471 | int status = 0; | ||
472 | if (folder->authority == NULL) | ||
473 | status = mu_authority_create_null (&folder->authority, folder); | ||
474 | if (!status && pauth) | ||
475 | *pauth = folder->authority; | ||
476 | return status; | ||
477 | } | ||
478 | |||
479 | int | ||
480 | _mu_fsfolder_init (mu_folder_t folder) | ||
481 | { | ||
482 | struct _mu_fsfolder *dfolder; | ||
483 | int status = 0; | ||
484 | |||
485 | /* We create an authority so the API is uniform across the mailbox | ||
486 | types. */ | ||
487 | status = _fsfolder_get_authority (folder, NULL); | ||
488 | if (status != 0) | ||
489 | return status; | ||
490 | |||
491 | dfolder = folder->data = calloc (1, sizeof (*dfolder)); | ||
492 | if (dfolder == NULL) | ||
493 | return ENOMEM; | ||
494 | |||
495 | status = mu_url_aget_path (folder->url, &dfolder->dirname); | ||
496 | if (status == MU_ERR_NOENT) | ||
497 | { | ||
498 | dfolder->dirname = malloc (2); | ||
499 | if (dfolder->dirname == NULL) | ||
500 | status = ENOMEM; | ||
501 | else | ||
502 | { | ||
503 | strcpy (dfolder->dirname, "."); | ||
504 | status = 0; | ||
505 | } | ||
506 | } | ||
507 | |||
508 | if (status) | ||
509 | { | ||
510 | free (dfolder); | ||
511 | folder->data = NULL; | ||
512 | return status; | ||
513 | } | ||
514 | |||
515 | folder->_destroy = _fsfolder_destroy; | ||
516 | |||
517 | folder->_open = _fsfolder_open; | ||
518 | folder->_close = _fsfolder_close; | ||
519 | |||
520 | folder->_list = _fsfolder_list; | ||
521 | folder->_lsub = _fsfolder_lsub; | ||
522 | folder->_subscribe = _fsfolder_subscribe; | ||
523 | folder->_unsubscribe = _fsfolder_unsubscribe; | ||
524 | folder->_delete = NULL; | ||
525 | folder->_rename = _fsfolder_rename; | ||
526 | return 0; | ||
527 | } | ||
528 |
... | @@ -41,6 +41,7 @@ | ... | @@ -41,6 +41,7 @@ |
41 | #include <mailutils/util.h> | 41 | #include <mailutils/util.h> |
42 | 42 | ||
43 | #include <mailutils/sys/mailbox.h> | 43 | #include <mailutils/sys/mailbox.h> |
44 | #include <mailutils/sys/folder.h> | ||
44 | #include <mailutils/sys/url.h> | 45 | #include <mailutils/sys/url.h> |
45 | 46 | ||
46 | /* Mailbox-specific flags */ | 47 | /* Mailbox-specific flags */ |
... | @@ -76,7 +77,8 @@ mailbox_folder_create (mu_mailbox_t mbox, const char *name, | ... | @@ -76,7 +77,8 @@ mailbox_folder_create (mu_mailbox_t mbox, const char *name, |
76 | int | 77 | int |
77 | _mailbox_create_from_record (mu_mailbox_t *pmbox, | 78 | _mailbox_create_from_record (mu_mailbox_t *pmbox, |
78 | mu_record_t record, | 79 | mu_record_t record, |
79 | mu_url_t url, | 80 | mu_url_t url, |
81 | mu_folder_t folder, | ||
80 | const char *name) | 82 | const char *name) |
81 | { | 83 | { |
82 | int (*m_init) (mu_mailbox_t) = NULL; | 84 | int (*m_init) (mu_mailbox_t) = NULL; |
... | @@ -127,10 +129,16 @@ _mailbox_create_from_record (mu_mailbox_t *pmbox, | ... | @@ -127,10 +129,16 @@ _mailbox_create_from_record (mu_mailbox_t *pmbox, |
127 | } | 129 | } |
128 | 130 | ||
129 | mbox->url = url; | 131 | mbox->url = url; |
130 | 132 | ||
131 | /* Create the folder before initializing the concrete mailbox. | 133 | if (folder) |
132 | The mailbox needs it's back pointer. */ | 134 | { |
133 | status = mailbox_folder_create (mbox, name, record); | 135 | folder->ref++; /* FIXME: No ref/unref function for folders */ |
136 | mbox->folder = folder; | ||
137 | } | ||
138 | else | ||
139 | /* Create the folder before initializing the concrete mailbox. | ||
140 | The mailbox needs it's back pointer. */ | ||
141 | status = mailbox_folder_create (mbox, name, record); | ||
134 | 142 | ||
135 | if (status == 0) | 143 | if (status == 0) |
136 | status = m_init (mbox); /* Create the concrete mailbox type. */ | 144 | status = m_init (mbox); /* Create the concrete mailbox type. */ |
... | @@ -152,11 +160,12 @@ static int | ... | @@ -152,11 +160,12 @@ static int |
152 | _create_mailbox0 (mu_mailbox_t *pmbox, mu_url_t url, const char *name) | 160 | _create_mailbox0 (mu_mailbox_t *pmbox, mu_url_t url, const char *name) |
153 | { | 161 | { |
154 | mu_record_t record = NULL; | 162 | mu_record_t record = NULL; |
155 | 163 | int rc; | |
156 | if (mu_registrar_lookup_url (url, MU_FOLDER_ATTRIBUTE_FILE, &record, NULL) | 164 | |
157 | == 0) | 165 | rc = mu_registrar_lookup_url (url, MU_FOLDER_ATTRIBUTE_FILE, &record, NULL); |
158 | return _mailbox_create_from_record (pmbox, record, url, name); | 166 | if (rc == 0) |
159 | return ENOSYS; | 167 | rc = _mailbox_create_from_record (pmbox, record, url, NULL, name); |
168 | return rc; | ||
160 | } | 169 | } |
161 | 170 | ||
162 | static int | 171 | static int |
... | @@ -203,7 +212,71 @@ mu_mailbox_create_from_record (mu_mailbox_t *pmbox, mu_record_t record, | ... | @@ -203,7 +212,71 @@ mu_mailbox_create_from_record (mu_mailbox_t *pmbox, mu_record_t record, |
203 | rc = mu_url_create (&url, name); | 212 | rc = mu_url_create (&url, name); |
204 | if (rc) | 213 | if (rc) |
205 | return rc; | 214 | return rc; |
206 | rc = _mailbox_create_from_record (pmbox, record, url, name); | 215 | rc = _mailbox_create_from_record (pmbox, record, url, NULL, name); |
216 | if (rc) | ||
217 | mu_url_destroy (&url); | ||
218 | return rc; | ||
219 | } | ||
220 | |||
221 | int | ||
222 | mu_mailbox_create_at (mu_mailbox_t *pmbox, mu_folder_t folder, | ||
223 | const char *name) | ||
224 | { | ||
225 | int rc; | ||
226 | mu_url_t url; | ||
227 | const char *oldpath; | ||
228 | |||
229 | rc = mu_url_dup (folder->url, &url); | ||
230 | if (rc) | ||
231 | return rc; | ||
232 | do | ||
233 | { | ||
234 | char *path; | ||
235 | size_t oldlen, len; | ||
236 | mu_record_t record; | ||
237 | |||
238 | rc = mu_url_sget_path (url, &oldpath); | ||
239 | if (rc) | ||
240 | break; | ||
241 | |||
242 | oldlen = strlen (oldpath); | ||
243 | if (oldlen == 0) | ||
244 | { | ||
245 | path = strdup (name); | ||
246 | if (!path) | ||
247 | { | ||
248 | rc = ENOMEM; | ||
249 | break; | ||
250 | } | ||
251 | } | ||
252 | else | ||
253 | { | ||
254 | if (oldpath[oldlen-1] == '/') | ||
255 | oldlen--; | ||
256 | len = oldlen + 1 + strlen (name) + 1; | ||
257 | path = malloc (len); | ||
258 | if (!path) | ||
259 | { | ||
260 | rc = ENOMEM; | ||
261 | break; | ||
262 | } | ||
263 | memcpy (path, oldpath, oldlen); | ||
264 | path[oldlen++] = '/'; | ||
265 | strcpy (path + oldlen, name); | ||
266 | } | ||
267 | rc = mu_url_set_path (url, path); | ||
268 | free (path); | ||
269 | if (rc) | ||
270 | break; | ||
271 | |||
272 | rc = mu_registrar_lookup_url (url, MU_FOLDER_ATTRIBUTE_FILE, | ||
273 | &record, NULL); | ||
274 | if (rc) | ||
275 | break; | ||
276 | rc = _mailbox_create_from_record (pmbox, record, url, folder, name); | ||
277 | } | ||
278 | while (0); | ||
279 | |||
207 | if (rc) | 280 | if (rc) |
208 | mu_url_destroy (&url); | 281 | mu_url_destroy (&url); |
209 | return rc; | 282 | return rc; |
... | @@ -314,7 +387,24 @@ mu_mailbox_remove (mu_mailbox_t mbox) | ... | @@ -314,7 +387,24 @@ mu_mailbox_remove (mu_mailbox_t mbox) |
314 | if (mbox->flags & _MU_MAILBOX_REMOVED) | 387 | if (mbox->flags & _MU_MAILBOX_REMOVED) |
315 | return MU_ERR_MBX_REMOVED; | 388 | return MU_ERR_MBX_REMOVED; |
316 | if (!mbox->_remove) | 389 | if (!mbox->_remove) |
317 | return MU_ERR_EMPTY_VFN; | 390 | { |
391 | /* Try the owning folder delete method. See comment to mu_folder_delete | ||
392 | in folder.c. This may result in a recursive call to mu_mailbox_remove | ||
393 | which is blocked by setting the _MU_MAILBOX_REMOVED flag. */ | ||
394 | |||
395 | int rc; | ||
396 | const char *path; | ||
397 | |||
398 | rc = mu_url_sget_path (mbox->url, &path); | ||
399 | if (rc == 0) | ||
400 | { | ||
401 | mbox->flags |= _MU_MAILBOX_REMOVED; | ||
402 | rc = mu_folder_delete (mbox->folder, path); | ||
403 | if (rc) | ||
404 | mbox->flags &= ~_MU_MAILBOX_REMOVED; | ||
405 | } | ||
406 | return rc; | ||
407 | } | ||
318 | return mbox->_remove (mbox); | 408 | return mbox->_remove (mbox); |
319 | } | 409 | } |
320 | 410 | ||
... | @@ -689,7 +779,7 @@ mu_mailbox_set_folder (mu_mailbox_t mbox, mu_folder_t folder) | ... | @@ -689,7 +779,7 @@ mu_mailbox_set_folder (mu_mailbox_t mbox, mu_folder_t folder) |
689 | { | 779 | { |
690 | if (mbox == NULL) | 780 | if (mbox == NULL) |
691 | return EINVAL; | 781 | return EINVAL; |
692 | mbox->folder = folder; | 782 | mbox->folder = folder; |
693 | return 0; | 783 | return 0; |
694 | } | 784 | } |
695 | 785 | ... | ... |
... | @@ -47,6 +47,7 @@ noinst_PROGRAMS = \ | ... | @@ -47,6 +47,7 @@ noinst_PROGRAMS = \ |
47 | encode2047\ | 47 | encode2047\ |
48 | fltst\ | 48 | fltst\ |
49 | fsaf\ | 49 | fsaf\ |
50 | fsfolder\ | ||
50 | imapio\ | 51 | imapio\ |
51 | listop\ | 52 | listop\ |
52 | mailcap\ | 53 | mailcap\ |
... | @@ -78,6 +79,9 @@ TESTSUITE_AT = \ | ... | @@ -78,6 +79,9 @@ TESTSUITE_AT = \ |
78 | encode2047.at\ | 79 | encode2047.at\ |
79 | fromflt.at\ | 80 | fromflt.at\ |
80 | fsaf.at\ | 81 | fsaf.at\ |
82 | fsfolder00.at\ | ||
83 | fsfolder01.at\ | ||
84 | fsfolder02.at\ | ||
81 | hdrflt.at\ | 85 | hdrflt.at\ |
82 | imapio.at\ | 86 | imapio.at\ |
83 | inline-comment.at\ | 87 | inline-comment.at\ | ... | ... |
libmailutils/tests/fsfolder.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2011 Free Software Foundation, Inc. | ||
3 | |||
4 | GNU Mailutils is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 3, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | GNU Mailutils is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ | ||
16 | |||
17 | #ifdef HAVE_CONFIG_H | ||
18 | # include <config.h> | ||
19 | #endif | ||
20 | #include <stdlib.h> | ||
21 | #include <string.h> | ||
22 | #include <mailutils/error.h> | ||
23 | #include <mailutils/errno.h> | ||
24 | #include <mailutils/folder.h> | ||
25 | #include <mailutils/stream.h> | ||
26 | #include <mailutils/stdstream.h> | ||
27 | #include <mailutils/list.h> | ||
28 | #include <mailutils/url.h> | ||
29 | #include <mailutils/util.h> | ||
30 | #include <mailutils/registrar.h> | ||
31 | #include <mailutils/sys/folder.h> | ||
32 | #include <mailutils/sys/registrar.h> | ||
33 | |||
34 | int sort_option; | ||
35 | int prefix_len; | ||
36 | |||
37 | struct command | ||
38 | { | ||
39 | char *verb; | ||
40 | int nargs; | ||
41 | char *args; | ||
42 | void (*handler) (mu_folder_t folder, char **argv); | ||
43 | }; | ||
44 | |||
45 | static int | ||
46 | compare_response (void const *a, void const *b) | ||
47 | { | ||
48 | struct mu_list_response const *ra = a; | ||
49 | struct mu_list_response const *rb = b; | ||
50 | |||
51 | if (ra->level < rb->level) | ||
52 | return -1; | ||
53 | if (ra->level > rb->level) | ||
54 | return 1; | ||
55 | return strcmp (ra->name, rb->name); | ||
56 | } | ||
57 | |||
58 | static int | ||
59 | _print_list_entry (void *item, void *data) | ||
60 | { | ||
61 | struct mu_list_response *resp = item; | ||
62 | int len = data ? *(int*) data : 0; | ||
63 | mu_printf ("%c%c %c %4d %s\n", | ||
64 | (resp->type & MU_FOLDER_ATTRIBUTE_DIRECTORY) ? 'd' : '-', | ||
65 | (resp->type & MU_FOLDER_ATTRIBUTE_FILE) ? 'f' : '-', | ||
66 | resp->separator ? resp->separator : ' ', | ||
67 | resp->level, | ||
68 | resp->name + len); | ||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | static void | ||
73 | com_list (mu_folder_t folder, char **argv) | ||
74 | { | ||
75 | int rc; | ||
76 | mu_list_t list; | ||
77 | |||
78 | mu_printf ("listing '%s' '%s'\n", argv[0], argv[1]); | ||
79 | rc = mu_folder_list (folder, argv[0], argv[1], 0, &list); | ||
80 | if (rc) | ||
81 | mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_list", argv[0], rc); | ||
82 | else | ||
83 | { | ||
84 | if (sort_option) | ||
85 | mu_list_sort (list, compare_response); | ||
86 | mu_list_foreach (list, _print_list_entry, &prefix_len); | ||
87 | mu_list_destroy (&list); | ||
88 | } | ||
89 | } | ||
90 | |||
91 | static void | ||
92 | com_lsub (mu_folder_t folder, char **argv) | ||
93 | { | ||
94 | int rc; | ||
95 | mu_list_t list; | ||
96 | |||
97 | mu_printf ("listing subscriptions for '%s' '%s'\n", argv[0], argv[1]); | ||
98 | rc = mu_folder_lsub (folder, argv[0], argv[1], &list); | ||
99 | if (rc) | ||
100 | mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_lsub", argv[0], rc); | ||
101 | else | ||
102 | { | ||
103 | if (sort_option) | ||
104 | mu_list_sort (list, compare_response); | ||
105 | mu_list_foreach (list, _print_list_entry, NULL); | ||
106 | mu_list_destroy (&list); | ||
107 | } | ||
108 | } | ||
109 | |||
110 | static void | ||
111 | com_rename (mu_folder_t folder, char **argv) | ||
112 | { | ||
113 | int rc; | ||
114 | |||
115 | mu_printf ("renaming %s to %s\n", argv[0], argv[1]); | ||
116 | rc = mu_folder_rename (folder, argv[0], argv[1]); | ||
117 | if (rc) | ||
118 | mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_rename", argv[0], rc); | ||
119 | else | ||
120 | mu_printf ("rename successful\n"); | ||
121 | } | ||
122 | |||
123 | static void | ||
124 | com_subscribe (mu_folder_t folder, char **argv) | ||
125 | { | ||
126 | int rc; | ||
127 | |||
128 | mu_printf ("subscribing %s\n", argv[0]); | ||
129 | rc = mu_folder_subscribe (folder, argv[0]); | ||
130 | if (rc) | ||
131 | mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_subscribe", argv[0], rc); | ||
132 | else | ||
133 | mu_printf ("subscribe successful\n"); | ||
134 | } | ||
135 | |||
136 | static void | ||
137 | com_unsubscribe (mu_folder_t folder, char **argv) | ||
138 | { | ||
139 | int rc; | ||
140 | |||
141 | mu_printf ("unsubscribing %s\n", argv[0]); | ||
142 | rc = mu_folder_unsubscribe (folder, argv[0]); | ||
143 | if (rc) | ||
144 | mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_unsubscribe", argv[0], rc); | ||
145 | else | ||
146 | mu_printf ("unsubscribe successful\n"); | ||
147 | } | ||
148 | |||
149 | static struct command comtab[] = { | ||
150 | { "list", 2, "REF MBX", com_list }, | ||
151 | { "lsub", 2, "REF MBX", com_lsub }, | ||
152 | { "rename", 2, "OLD NEW", com_rename }, | ||
153 | { "subscribe", 1, "MBX", com_subscribe }, | ||
154 | { "unsubscribe", 1, "MBX", com_unsubscribe }, | ||
155 | { NULL } | ||
156 | }; | ||
157 | |||
158 | static struct command * | ||
159 | find_command (const char *name) | ||
160 | { | ||
161 | struct command *cp; | ||
162 | |||
163 | for (cp = comtab; cp->verb; cp++) | ||
164 | if (strcmp (cp->verb, name) == 0) | ||
165 | return cp; | ||
166 | return NULL; | ||
167 | } | ||
168 | |||
169 | static void | ||
170 | usage () | ||
171 | { | ||
172 | struct command *cp; | ||
173 | |||
174 | mu_printf ( | ||
175 | "usage: %s [debug=SPEC] name=URL OP ARG [ARG...] [OP ARG [ARG...]...]\n", | ||
176 | mu_program_name); | ||
177 | mu_printf ("OPerations and corresponding ARGuments are:\n"); | ||
178 | for (cp = comtab; cp->verb; cp++) | ||
179 | mu_printf (" %s %s\n", cp->verb, cp->args); | ||
180 | } | ||
181 | |||
182 | static int | ||
183 | _always_is_scheme (mu_record_t record, mu_url_t url, int flags) | ||
184 | { | ||
185 | return 1; | ||
186 | } | ||
187 | |||
188 | static struct _mu_record test_record = | ||
189 | { | ||
190 | 0, | ||
191 | "file", | ||
192 | MU_RECORD_LOCAL, | ||
193 | MU_URL_SCHEME | MU_URL_PATH, | ||
194 | MU_URL_PATH, | ||
195 | mu_url_expand_path, /* URL init. */ | ||
196 | NULL, /* Mailbox init. */ | ||
197 | NULL, /* Mailer init. */ | ||
198 | _mu_fsfolder_init, /* Folder init. */ | ||
199 | NULL, /* No need for an back pointer. */ | ||
200 | _always_is_scheme, /* _is_scheme method. */ | ||
201 | NULL, /* _get_url method. */ | ||
202 | NULL, /* _get_mailbox method. */ | ||
203 | NULL, /* _get_mailer method. */ | ||
204 | NULL /* _get_folder method. */ | ||
205 | }; | ||
206 | |||
207 | int | ||
208 | main (int argc, char **argv) | ||
209 | { | ||
210 | int i; | ||
211 | int rc; | ||
212 | mu_folder_t folder; | ||
213 | char *fname = NULL; | ||
214 | |||
215 | mu_set_program_name (argv[0]); | ||
216 | mu_registrar_record (&test_record); | ||
217 | |||
218 | if (argc == 1) | ||
219 | { | ||
220 | usage (); | ||
221 | exit (0); | ||
222 | } | ||
223 | |||
224 | for (i = 1; i < argc; i++) | ||
225 | { | ||
226 | if (strncmp (argv[i], "debug=", 6) == 0) | ||
227 | mu_debug_parse_spec (argv[i] + 6); | ||
228 | else if (strncmp (argv[i], "name=", 5) == 0) | ||
229 | fname = argv[i] + 5; | ||
230 | else if (strcmp (argv[i], "sort") == 0) | ||
231 | sort_option = 1; | ||
232 | else | ||
233 | break; | ||
234 | } | ||
235 | |||
236 | if (!fname) | ||
237 | { | ||
238 | mu_error ("name not specified"); | ||
239 | exit (1); | ||
240 | } | ||
241 | |||
242 | if (fname[0] != '/') | ||
243 | { | ||
244 | char *cwd = mu_getcwd (); | ||
245 | prefix_len = strlen (cwd); | ||
246 | if (cwd[prefix_len-1] != '/') | ||
247 | prefix_len++; | ||
248 | fname = mu_make_file_name (cwd, fname); | ||
249 | free (cwd); | ||
250 | } | ||
251 | |||
252 | rc = mu_folder_create (&folder, fname); | ||
253 | if (rc) | ||
254 | { | ||
255 | mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_create", fname, rc); | ||
256 | return 1; | ||
257 | } | ||
258 | rc = mu_folder_open (folder, MU_STREAM_READ); | ||
259 | if (rc) | ||
260 | { | ||
261 | mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_open", fname, rc); | ||
262 | return 1; | ||
263 | } | ||
264 | |||
265 | while (i < argc) | ||
266 | { | ||
267 | char *comargs[2]; | ||
268 | struct command *cmd; | ||
269 | |||
270 | cmd = find_command (argv[i]); | ||
271 | if (!cmd) | ||
272 | { | ||
273 | mu_error ("unknown command %s\n", argv[i]); | ||
274 | break; | ||
275 | } | ||
276 | |||
277 | i++; | ||
278 | if (i + cmd->nargs > argc) | ||
279 | { | ||
280 | mu_error ("not enough arguments for %s", cmd->verb); | ||
281 | break; | ||
282 | } | ||
283 | memcpy (comargs, argv + i, cmd->nargs * sizeof (comargs[0])); | ||
284 | i += cmd->nargs; | ||
285 | |||
286 | cmd->handler (folder, comargs); | ||
287 | } | ||
288 | |||
289 | mu_folder_close (folder); | ||
290 | mu_folder_destroy (&folder); | ||
291 | |||
292 | return 0; | ||
293 | } |
libmailutils/tests/fsfolder00.at
0 → 100644
1 | # This file is part of GNU Mailutils. -*- Autotest -*- | ||
2 | # Copyright (C) 2011 Free Software Foundation, Inc. | ||
3 | # | ||
4 | # GNU Mailutils is free software; you can redistribute it and/or | ||
5 | # modify it under the terms of the GNU General Public License as | ||
6 | # published by the Free Software Foundation; either version 3, or (at | ||
7 | # your option) any later version. | ||
8 | # | ||
9 | # GNU Mailutils is distributed in the hope that it will be useful, but | ||
10 | # WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | # General Public License for more details. | ||
13 | # | ||
14 | # You should have received a copy of the GNU General Public License | ||
15 | # along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. | ||
16 | |||
17 | AT_SETUP([List]) | ||
18 | AT_KEYWORDS([fsfolder folder-list]) | ||
19 | |||
20 | AT_CHECK([ | ||
21 | mkdir dir | ||
22 | > dir/foo | ||
23 | > dir/bar | ||
24 | > dir/foo.mbox | ||
25 | mkdir dir/subdir | ||
26 | > dir/subdir/file | ||
27 | > dir/subdir/baz.mbox | ||
28 | |||
29 | fsfolder name=dir sort dnl | ||
30 | list "" "*" dnl | ||
31 | list subdir "*" dnl | ||
32 | list "" "*.mbox" dnl | ||
33 | list "subdir" "*.mbox" | ||
34 | ], | ||
35 | [0], | ||
36 | [listing '' '*' | ||
37 | d- / 0 dir/bar | ||
38 | d- / 0 dir/foo | ||
39 | d- / 0 dir/foo.mbox | ||
40 | d- / 0 dir/subdir | ||
41 | d- / 1 dir/subdir/baz.mbox | ||
42 | d- / 1 dir/subdir/file | ||
43 | listing 'subdir' '*' | ||
44 | d- / 0 dir/subdir/baz.mbox | ||
45 | d- / 0 dir/subdir/file | ||
46 | listing '' '*.mbox' | ||
47 | d- / 0 dir/foo.mbox | ||
48 | d- / 1 dir/subdir/baz.mbox | ||
49 | listing 'subdir' '*.mbox' | ||
50 | d- / 0 dir/subdir/baz.mbox | ||
51 | ]) | ||
52 | |||
53 | AT_CLEANUP |
libmailutils/tests/fsfolder01.at
0 → 100644
1 | # This file is part of GNU Mailutils. -*- Autotest -*- | ||
2 | # Copyright (C) 2011 Free Software Foundation, Inc. | ||
3 | # | ||
4 | # GNU Mailutils is free software; you can redistribute it and/or | ||
5 | # modify it under the terms of the GNU General Public License as | ||
6 | # published by the Free Software Foundation; either version 3, or (at | ||
7 | # your option) any later version. | ||
8 | # | ||
9 | # GNU Mailutils is distributed in the hope that it will be useful, but | ||
10 | # WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | # General Public License for more details. | ||
13 | # | ||
14 | # You should have received a copy of the GNU General Public License | ||
15 | # along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. | ||
16 | |||
17 | AT_SETUP([Subscriptions]) | ||
18 | AT_KEYWORDS([fsfolder folder-subscribe]) | ||
19 | |||
20 | AT_CHECK([ | ||
21 | mkdir dir | ||
22 | fsfolder name=dir sort lsub "" "*" | ||
23 | fsfolder name=dir subscribe foo | ||
24 | fsfolder name=dir sort lsub "" "*" | ||
25 | fsfolder name=dir subscribe baz subscribe foo/baz subscribe foo/bar | ||
26 | fsfolder name=dir sort lsub "" "*" | ||
27 | fsfolder name=dir sort lsub foo "*" | ||
28 | fsfolder name=dir sort lsub "" 'foo*' | ||
29 | fsfolder name=dir unsubscribe baz | ||
30 | fsfolder name=dir sort lsub "" "*" | ||
31 | fsfolder name=dir unsubscribe foo | ||
32 | fsfolder name=dir sort lsub "" "*" | ||
33 | ], | ||
34 | [0], | ||
35 | [listing subscriptions for '' '*' | ||
36 | subscribing foo | ||
37 | subscribe successful | ||
38 | listing subscriptions for '' '*' | ||
39 | -f / 0 foo | ||
40 | subscribing baz | ||
41 | subscribe successful | ||
42 | subscribing foo/baz | ||
43 | subscribe successful | ||
44 | subscribing foo/bar | ||
45 | subscribe successful | ||
46 | listing subscriptions for '' '*' | ||
47 | -f / 0 baz | ||
48 | -f / 0 foo | ||
49 | -f / 0 foo/bar | ||
50 | -f / 0 foo/baz | ||
51 | listing subscriptions for 'foo' '*' | ||
52 | -f / 0 foo/bar | ||
53 | -f / 0 foo/baz | ||
54 | listing subscriptions for '' 'foo*' | ||
55 | -f / 0 foo | ||
56 | -f / 0 foo/bar | ||
57 | -f / 0 foo/baz | ||
58 | unsubscribing baz | ||
59 | unsubscribe successful | ||
60 | listing subscriptions for '' '*' | ||
61 | -f / 0 foo | ||
62 | -f / 0 foo/bar | ||
63 | -f / 0 foo/baz | ||
64 | unsubscribing foo | ||
65 | unsubscribe successful | ||
66 | listing subscriptions for '' '*' | ||
67 | -f / 0 foo/bar | ||
68 | -f / 0 foo/baz | ||
69 | ]) | ||
70 | |||
71 | AT_CLEANUP | ||
72 | |||
73 | |||
74 |
libmailutils/tests/fsfolder02.at
0 → 100644
1 | # This file is part of GNU Mailutils. -*- Autotest -*- | ||
2 | # Copyright (C) 2011 Free Software Foundation, Inc. | ||
3 | # | ||
4 | # GNU Mailutils is free software; you can redistribute it and/or | ||
5 | # modify it under the terms of the GNU General Public License as | ||
6 | # published by the Free Software Foundation; either version 3, or (at | ||
7 | # your option) any later version. | ||
8 | # | ||
9 | # GNU Mailutils is distributed in the hope that it will be useful, but | ||
10 | # WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | # General Public License for more details. | ||
13 | # | ||
14 | # You should have received a copy of the GNU General Public License | ||
15 | # along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. | ||
16 | |||
17 | AT_SETUP([Rename]) | ||
18 | AT_KEYWORDS([fsfolder folder-rename]) | ||
19 | |||
20 | AT_CHECK([ | ||
21 | mkdir dir | ||
22 | > dir/foo | ||
23 | fsfolder name=dir rename foo bar | ||
24 | fsfolder name=dir list "" "*" | ||
25 | > dir/baz | ||
26 | fsfolder name=dir rename bar baz | ||
27 | ], | ||
28 | [0], | ||
29 | [renaming foo to bar | ||
30 | rename successful | ||
31 | listing '' '*' | ||
32 | d- / 0 dir/bar | ||
33 | renaming bar to baz | ||
34 | ], | ||
35 | [fsfolder: mu_folder_rename(bar) failed: File exists | ||
36 | ]) | ||
37 | |||
38 | AT_CLEANUP | ||
39 |
... | @@ -68,6 +68,11 @@ m4_include([mailcap.at]) | ... | @@ -68,6 +68,11 @@ m4_include([mailcap.at]) |
68 | m4_include([wicket.at]) | 68 | m4_include([wicket.at]) |
69 | m4_include([prop.at]) | 69 | m4_include([prop.at]) |
70 | 70 | ||
71 | AT_BANNER(File-system folder) | ||
72 | m4_include([fsfolder00.at]) | ||
73 | m4_include([fsfolder01.at]) | ||
74 | m4_include([fsfolder02.at]) | ||
75 | |||
71 | AT_BANNER(Base64) | 76 | AT_BANNER(Base64) |
72 | m4_include([base64e.at]) | 77 | m4_include([base64e.at]) |
73 | m4_include([base64d.at]) | 78 | m4_include([base64d.at]) | ... | ... |
... | @@ -133,7 +133,6 @@ static struct command comtab[] = { | ... | @@ -133,7 +133,6 @@ static struct command comtab[] = { |
133 | { "lsub", 2, "REF MBX", com_lsub }, | 133 | { "lsub", 2, "REF MBX", com_lsub }, |
134 | { "delete", 1, "MBX", com_delete }, | 134 | { "delete", 1, "MBX", com_delete }, |
135 | { "rename", 2, "OLD NEW", com_rename }, | 135 | { "rename", 2, "OLD NEW", com_rename }, |
136 | { "delete", 1, "MBOX", com_delete }, | ||
137 | { "subscribe", 1, "MBX", com_subscribe }, | 136 | { "subscribe", 1, "MBX", com_subscribe }, |
138 | { "unsubscribe", 1, "MBX", com_unsubscribe }, | 137 | { "unsubscribe", 1, "MBX", com_unsubscribe }, |
139 | { NULL } | 138 | { NULL } | ... | ... |
... | @@ -37,12 +37,6 @@ | ... | @@ -37,12 +37,6 @@ |
37 | #include <mailutils/sys/amd.h> | 37 | #include <mailutils/sys/amd.h> |
38 | 38 | ||
39 | static int | 39 | static int |
40 | _maildir_folder_init (mu_folder_t folder MU_ARG_UNUSED) | ||
41 | { | ||
42 | return 0; | ||
43 | } | ||
44 | |||
45 | static int | ||
46 | dir_exists (const char *name, const char *suf) | 40 | dir_exists (const char *name, const char *suf) |
47 | { | 41 | { |
48 | struct stat st; | 42 | struct stat st; |
... | @@ -59,31 +53,42 @@ dir_exists (const char *name, const char *suf) | ... | @@ -59,31 +53,42 @@ dir_exists (const char *name, const char *suf) |
59 | static int | 53 | static int |
60 | _maildir_is_scheme (mu_record_t record, mu_url_t url, int flags) | 54 | _maildir_is_scheme (mu_record_t record, mu_url_t url, int flags) |
61 | { | 55 | { |
62 | if (mu_url_is_scheme (url, record->scheme)) | 56 | int scheme_matched = mu_url_is_scheme (url, record->scheme); |
63 | return MU_FOLDER_ATTRIBUTE_FILE & flags; | 57 | int rc = 0; |
64 | 58 | ||
65 | if (mu_scheme_autodetect_p (url)) | 59 | if (scheme_matched || mu_scheme_autodetect_p (url)) |
66 | { | 60 | { |
67 | /* Attemp auto-detection */ | 61 | /* Attemp auto-detection */ |
68 | const char *path; | 62 | const char *path; |
69 | struct stat st; | 63 | struct stat st; |
70 | 64 | ||
71 | if (mu_url_sget_path (url, &path)) | 65 | if (mu_url_sget_path (url, &path)) |
72 | return 0; | 66 | return 0; |
73 | 67 | ||
74 | if (stat (path, &st) < 0) | 68 | if (stat (path, &st) < 0) |
75 | return 0; | 69 | { |
76 | 70 | if (errno == ENOENT && scheme_matched) | |
71 | return MU_FOLDER_ATTRIBUTE_ALL & flags; | ||
72 | return 0; | ||
73 | } | ||
74 | |||
77 | if (!S_ISDIR (st.st_mode)) | 75 | if (!S_ISDIR (st.st_mode)) |
78 | return 0; | 76 | return 0; |
79 | 77 | ||
80 | if ((flags & MU_FOLDER_ATTRIBUTE_FILE) | 78 | if (scheme_matched) |
81 | && dir_exists (path, TMPSUF) | 79 | rc = MU_FOLDER_ATTRIBUTE_ALL; |
82 | && dir_exists (path, CURSUF) | 80 | else |
83 | && dir_exists (path, NEWSUF)) | 81 | { |
84 | return MU_FOLDER_ATTRIBUTE_FILE|MU_FOLDER_ATTRIBUTE_DIRECTORY; | 82 | rc |= MU_FOLDER_ATTRIBUTE_DIRECTORY; |
83 | |||
84 | if ((flags & MU_FOLDER_ATTRIBUTE_FILE) | ||
85 | && dir_exists (path, TMPSUF) | ||
86 | && dir_exists (path, CURSUF) | ||
87 | && dir_exists (path, NEWSUF)) | ||
88 | rc |= MU_FOLDER_ATTRIBUTE_FILE; | ||
89 | } | ||
85 | } | 90 | } |
86 | return 0; | 91 | return rc & flags; |
87 | } | 92 | } |
88 | 93 | ||
89 | static int | 94 | static int |
... | @@ -106,7 +111,7 @@ static struct _mu_record _maildir_record = | ... | @@ -106,7 +111,7 @@ static struct _mu_record _maildir_record = |
106 | mu_url_expand_path, /* Url init. */ | 111 | mu_url_expand_path, /* Url init. */ |
107 | _mailbox_maildir_init, /* Mailbox init. */ | 112 | _mailbox_maildir_init, /* Mailbox init. */ |
108 | NULL, /* Mailer init. */ | 113 | NULL, /* Mailer init. */ |
109 | _maildir_folder_init, /* Folder init. */ | 114 | _mu_fsfolder_init, /* Folder init. */ |
110 | NULL, /* back pointer. */ | 115 | NULL, /* back pointer. */ |
111 | _maildir_is_scheme, /* _is_scheme method. */ | 116 | _maildir_is_scheme, /* _is_scheme method. */ |
112 | NULL, /* _get_url method. */ | 117 | NULL, /* _get_url method. */ | ... | ... |
... | @@ -49,19 +49,23 @@ static int | ... | @@ -49,19 +49,23 @@ static int |
49 | _mbox_is_scheme (mu_record_t record, mu_url_t url, int flags) | 49 | _mbox_is_scheme (mu_record_t record, mu_url_t url, int flags) |
50 | { | 50 | { |
51 | int rc = 0; | 51 | int rc = 0; |
52 | 52 | int scheme_matched = mu_url_is_scheme (url, record->scheme); | |
53 | if (mu_url_is_scheme (url, record->scheme)) | 53 | if (scheme_matched || mu_scheme_autodetect_p (url)) |
54 | return MU_FOLDER_ATTRIBUTE_FILE & flags; | ||
55 | |||
56 | if (mu_scheme_autodetect_p (url)) | ||
57 | { | 54 | { |
58 | struct stat st; | 55 | struct stat st; |
59 | const char *path; | 56 | const char *path; |
60 | 57 | ||
61 | mu_url_sget_path (url, &path); | 58 | mu_url_sget_path (url, &path); |
62 | if (stat (path, &st) < 0) | 59 | if (stat (path, &st) < 0) |
63 | return 0; | 60 | { |
64 | 61 | if (errno == ENOENT) | |
62 | { | ||
63 | if (scheme_matched) | ||
64 | return MU_FOLDER_ATTRIBUTE_FILE & flags; | ||
65 | } | ||
66 | return 0; | ||
67 | } | ||
68 | |||
65 | if (S_ISREG (st.st_mode) || S_ISCHR (st.st_mode)) | 69 | if (S_ISREG (st.st_mode) || S_ISCHR (st.st_mode)) |
66 | { | 70 | { |
67 | if (st.st_size == 0) | 71 | if (st.st_size == 0) |
... | @@ -71,7 +75,7 @@ _mbox_is_scheme (mu_record_t record, mu_url_t url, int flags) | ... | @@ -71,7 +75,7 @@ _mbox_is_scheme (mu_record_t record, mu_url_t url, int flags) |
71 | else if (flags & MU_FOLDER_ATTRIBUTE_FILE) | 75 | else if (flags & MU_FOLDER_ATTRIBUTE_FILE) |
72 | { | 76 | { |
73 | #if 0 | 77 | #if 0 |
74 | /* This effectively sieves out all non-mailbox files, | 78 | /* FIXME: This effectively sieves out all non-mailbox files, |
75 | but it makes mu_folder_enumerate crawl, which is | 79 | but it makes mu_folder_enumerate crawl, which is |
76 | intolerable for imap4d LIST command. */ | 80 | intolerable for imap4d LIST command. */ |
77 | int fd = open (path, O_RDONLY); | 81 | int fd = open (path, O_RDONLY); |
... | @@ -106,7 +110,7 @@ static struct _mu_record _mbox_record = | ... | @@ -106,7 +110,7 @@ static struct _mu_record _mbox_record = |
106 | mu_url_expand_path, /* URL init. */ | 110 | mu_url_expand_path, /* URL init. */ |
107 | _mailbox_mbox_init, /* Mailbox init. */ | 111 | _mailbox_mbox_init, /* Mailbox init. */ |
108 | NULL, /* Mailer init. */ | 112 | NULL, /* Mailer init. */ |
109 | _folder_mbox_init, /* Folder init. */ | 113 | _mu_fsfolder_init, /* Folder init. */ |
110 | NULL, /* No need for an back pointer. */ | 114 | NULL, /* No need for an back pointer. */ |
111 | _mbox_is_scheme, /* _is_scheme method. */ | 115 | _mbox_is_scheme, /* _is_scheme method. */ |
112 | NULL, /* _get_url method. */ | 116 | NULL, /* _get_url method. */ |
... | @@ -116,499 +120,4 @@ static struct _mu_record _mbox_record = | ... | @@ -116,499 +120,4 @@ static struct _mu_record _mbox_record = |
116 | }; | 120 | }; |
117 | mu_record_t mu_mbox_record = &_mbox_record; | 121 | mu_record_t mu_mbox_record = &_mbox_record; |
118 | 122 | ||
119 | /* lsub/subscribe/unsubscribe are not needed. */ | ||
120 | static void folder_mbox_destroy (mu_folder_t); | ||
121 | static int folder_mbox_open (mu_folder_t, int); | ||
122 | static int folder_mbox_close (mu_folder_t); | ||
123 | static int folder_mbox_delete (mu_folder_t, const char *); | ||
124 | static int folder_mbox_rename (mu_folder_t , const char *, const char *); | ||
125 | static int folder_mbox_list (mu_folder_t, const char *, void *, int, | ||
126 | size_t, mu_list_t, mu_folder_enumerate_fp, | ||
127 | void *); | ||
128 | static int folder_mbox_subscribe (mu_folder_t, const char *); | ||
129 | static int folder_mbox_unsubscribe (mu_folder_t, const char *); | ||
130 | static int folder_mbox_lsub (mu_folder_t, const char *, const char *, | ||
131 | mu_list_t); | ||
132 | |||
133 | |||
134 | static char *get_pathname (const char *, const char *); | ||
135 | |||
136 | static int folder_mbox_get_authority (mu_folder_t folder, mu_authority_t * pauth); | ||
137 | |||
138 | struct _fmbox | ||
139 | { | ||
140 | char *dirname; | ||
141 | char **subscribe; | ||
142 | size_t sublen; | ||
143 | }; | ||
144 | typedef struct _fmbox *fmbox_t; | ||
145 | |||
146 | |||
147 | int | ||
148 | _folder_mbox_init (mu_folder_t folder) | ||
149 | { | ||
150 | fmbox_t dfolder; | ||
151 | int status = 0; | ||
152 | |||
153 | /* We create an authority so the API is uniform across the mailbox | ||
154 | types. */ | ||
155 | status = folder_mbox_get_authority (folder, NULL); | ||
156 | if (status != 0) | ||
157 | return status; | ||
158 | |||
159 | dfolder = folder->data = calloc (1, sizeof (*dfolder)); | ||
160 | if (dfolder == NULL) | ||
161 | return ENOMEM; | ||
162 | |||
163 | status = mu_url_aget_path (folder->url, &dfolder->dirname); | ||
164 | if (status == MU_ERR_NOENT) | ||
165 | { | ||
166 | dfolder->dirname = malloc (2); | ||
167 | if (dfolder->dirname == NULL) | ||
168 | status = ENOMEM; | ||
169 | else | ||
170 | { | ||
171 | strcpy (dfolder->dirname, "."); | ||
172 | status = 0; | ||
173 | } | ||
174 | } | ||
175 | |||
176 | if (status) | ||
177 | { | ||
178 | free (dfolder); | ||
179 | folder->data = NULL; | ||
180 | return status; | ||
181 | } | ||
182 | |||
183 | folder->_destroy = folder_mbox_destroy; | ||
184 | |||
185 | folder->_open = folder_mbox_open; | ||
186 | folder->_close = folder_mbox_close; | ||
187 | |||
188 | folder->_list = folder_mbox_list; | ||
189 | folder->_lsub = folder_mbox_lsub; | ||
190 | folder->_subscribe = folder_mbox_subscribe; | ||
191 | folder->_unsubscribe = folder_mbox_unsubscribe; | ||
192 | folder->_delete = folder_mbox_delete; | ||
193 | folder->_rename = folder_mbox_rename; | ||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | void | ||
198 | folder_mbox_destroy (mu_folder_t folder) | ||
199 | { | ||
200 | if (folder->data) | ||
201 | { | ||
202 | fmbox_t fmbox = folder->data; | ||
203 | if (fmbox->dirname) | ||
204 | free (fmbox->dirname); | ||
205 | if (fmbox->subscribe) | ||
206 | free (fmbox->subscribe); | ||
207 | free (folder->data); | ||
208 | folder->data = NULL; | ||
209 | } | ||
210 | } | ||
211 | |||
212 | /* Noop. */ | ||
213 | static int | ||
214 | folder_mbox_open (mu_folder_t folder, int flags MU_ARG_UNUSED) | ||
215 | { | ||
216 | fmbox_t fmbox = folder->data; | ||
217 | if (flags & MU_STREAM_CREAT) | ||
218 | { | ||
219 | return (mkdir (fmbox->dirname, S_IRWXU) == 0) ? 0 : errno; | ||
220 | } | ||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | /* Noop. */ | ||
225 | static int | ||
226 | folder_mbox_close (mu_folder_t folder MU_ARG_UNUSED) | ||
227 | { | ||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static int | ||
232 | folder_mbox_delete (mu_folder_t folder, const char *filename) | ||
233 | { | ||
234 | fmbox_t fmbox = folder->data; | ||
235 | if (filename) | ||
236 | { | ||
237 | int status = 0; | ||
238 | char *pathname = get_pathname (fmbox->dirname, filename); | ||
239 | if (pathname) | ||
240 | { | ||
241 | if (remove (pathname) != 0) | ||
242 | status = errno; | ||
243 | free (pathname); | ||
244 | } | ||
245 | else | ||
246 | status = ENOMEM; | ||
247 | return status; | ||
248 | } | ||
249 | return EINVAL; | ||
250 | } | ||
251 | |||
252 | static int | ||
253 | folder_mbox_rename (mu_folder_t folder, const char *oldpath, | ||
254 | const char *newpath) | ||
255 | { | ||
256 | fmbox_t fmbox = folder->data; | ||
257 | if (oldpath && newpath) | ||
258 | { | ||
259 | int status = 0; | ||
260 | char *pathold = get_pathname (fmbox->dirname, oldpath); | ||
261 | if (pathold) | ||
262 | { | ||
263 | char *pathnew = get_pathname (fmbox->dirname, newpath); | ||
264 | if (pathnew) | ||
265 | { | ||
266 | if (rename (pathold, pathnew) != 0) | ||
267 | status = errno; | ||
268 | free (pathnew); | ||
269 | } | ||
270 | else | ||
271 | status = ENOMEM; | ||
272 | free (pathold); | ||
273 | } | ||
274 | else | ||
275 | status = ENOMEM; | ||
276 | return status; | ||
277 | } | ||
278 | return EINVAL; | ||
279 | } | ||
280 | |||
281 | struct inode_list /* Inode/dev number list used to cut off | ||
282 | recursion */ | ||
283 | { | ||
284 | struct inode_list *next; | ||
285 | ino_t inode; | ||
286 | dev_t dev; | ||
287 | }; | ||
288 | |||
289 | struct search_data | ||
290 | { | ||
291 | mu_list_t result; | ||
292 | mu_folder_enumerate_fp enumfun; | ||
293 | void *enumdata; | ||
294 | char *dirname; | ||
295 | size_t dirlen; | ||
296 | void *pattern; | ||
297 | int flags; | ||
298 | size_t max_level; | ||
299 | size_t errcnt; | ||
300 | mu_folder_t folder; | ||
301 | }; | ||
302 | |||
303 | static int | ||
304 | inode_list_lookup (struct inode_list *list, struct stat *st) | ||
305 | { | ||
306 | for (; list; list = list->next) | ||
307 | if (list->inode == st->st_ino && list->dev == st->st_dev) | ||
308 | return 1; | ||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | static int | ||
313 | list_helper (struct search_data *data, mu_record_t record, | ||
314 | const char *dirname, size_t level, | ||
315 | struct inode_list *ilist) | ||
316 | { | ||
317 | DIR *dirp; | ||
318 | struct dirent *dp; | ||
319 | int stop = 0; | ||
320 | |||
321 | if (data->max_level && level > data->max_level) | ||
322 | return 0; | ||
323 | |||
324 | dirp = opendir (dirname); | ||
325 | if (dirp == NULL) | ||
326 | { | ||
327 | mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_ERROR, | ||
328 | ("list_helper cannot open directory %s: %s", | ||
329 | dirname, mu_strerror (errno))); | ||
330 | data->errcnt++; | ||
331 | return 1; | ||
332 | } | ||
333 | |||
334 | if (!record) | ||
335 | { | ||
336 | int type; | ||
337 | mu_registrar_lookup (dirname, MU_FOLDER_ATTRIBUTE_ALL, | ||
338 | &record, &type); | ||
339 | } | ||
340 | |||
341 | while ((dp = readdir (dirp))) | ||
342 | { | ||
343 | char const *ename = dp->d_name; | ||
344 | char *fname; | ||
345 | struct stat st; | ||
346 | |||
347 | if (ename[ename[0] != '.' ? 0 : ename[1] != '.' ? 1 : 2] == 0) | ||
348 | continue; | ||
349 | fname = get_pathname (dirname, ename); | ||
350 | if (lstat (fname, &st) == 0) | ||
351 | { | ||
352 | int f; | ||
353 | if (S_ISDIR (st.st_mode)) | ||
354 | f = MU_FOLDER_ATTRIBUTE_DIRECTORY; | ||
355 | else if (S_ISREG (st.st_mode)) | ||
356 | f = MU_FOLDER_ATTRIBUTE_FILE; | ||
357 | else if (S_ISLNK (st.st_mode)) | ||
358 | f = MU_FOLDER_ATTRIBUTE_LINK; | ||
359 | else | ||
360 | f = 0; | ||
361 | if (mu_record_list_p (record, ename, f)) | ||
362 | { | ||
363 | if (data->folder->_match == NULL | ||
364 | || data->folder->_match (fname + data->dirlen + | ||
365 | ((data->dirlen > 1 | ||
366 | && data->dirname[data->dirlen-1] != '/') ? | ||
367 | 1 : 0), | ||
368 | data->pattern, | ||
369 | data->flags) == 0) | ||
370 | { | ||
371 | char *refname = fname; | ||
372 | int type = 0; | ||
373 | struct mu_list_response *resp; | ||
374 | mu_record_t rec = NULL; | ||
375 | |||
376 | resp = malloc (sizeof (*resp)); | ||
377 | if (resp == NULL) | ||
378 | { | ||
379 | mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_ERROR, | ||
380 | ("list_helper: %s", mu_strerror (ENOMEM))); | ||
381 | data->errcnt++; | ||
382 | free (fname); | ||
383 | continue; | ||
384 | } | ||
385 | |||
386 | mu_registrar_lookup (refname, MU_FOLDER_ATTRIBUTE_ALL, | ||
387 | &rec, &type); | ||
388 | |||
389 | resp->name = fname; | ||
390 | resp->level = level; | ||
391 | resp->separator = '/'; | ||
392 | resp->type = type; | ||
393 | resp->format = rec; | ||
394 | |||
395 | if (resp->type == 0) | ||
396 | { | ||
397 | free (resp->name); | ||
398 | free (resp); | ||
399 | continue; | ||
400 | } | ||
401 | |||
402 | if (data->enumfun) | ||
403 | { | ||
404 | if (data->enumfun (data->folder, resp, data->enumdata)) | ||
405 | { | ||
406 | free (resp->name); | ||
407 | free (resp); | ||
408 | stop = 1; | ||
409 | break; | ||
410 | } | ||
411 | } | ||
412 | |||
413 | if (data->result) | ||
414 | { | ||
415 | fname = NULL; | ||
416 | mu_list_append (data->result, resp); | ||
417 | } | ||
418 | else | ||
419 | free (resp); | ||
420 | |||
421 | if ((type & MU_FOLDER_ATTRIBUTE_DIRECTORY) | ||
422 | && !inode_list_lookup (ilist, &st)) | ||
423 | { | ||
424 | struct inode_list idata; | ||
425 | |||
426 | idata.inode = st.st_ino; | ||
427 | idata.dev = st.st_dev; | ||
428 | idata.next = ilist; | ||
429 | stop = list_helper (data, rec, refname, level + 1, | ||
430 | &idata); | ||
431 | } | ||
432 | } | ||
433 | else if (S_ISDIR (st.st_mode)) | ||
434 | { | ||
435 | struct inode_list idata; | ||
436 | |||
437 | idata.inode = st.st_ino; | ||
438 | idata.dev = st.st_dev; | ||
439 | idata.next = ilist; | ||
440 | stop = list_helper (data, NULL, fname, level + 1, &idata); | ||
441 | } | ||
442 | } | ||
443 | } | ||
444 | else | ||
445 | { | ||
446 | mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_ERROR, | ||
447 | ("list_helper cannot stat %s: %s", | ||
448 | fname, mu_strerror (errno))); | ||
449 | } | ||
450 | free (fname); | ||
451 | } | ||
452 | closedir (dirp); | ||
453 | return stop; | ||
454 | } | ||
455 | |||
456 | static int | ||
457 | folder_mbox_list (mu_folder_t folder, const char *ref, | ||
458 | void *pattern, | ||
459 | int flags, | ||
460 | size_t max_level, | ||
461 | mu_list_t flist, | ||
462 | mu_folder_enumerate_fp enumfun, void *enumdata) | ||
463 | { | ||
464 | fmbox_t fmbox = folder->data; | ||
465 | struct inode_list iroot; | ||
466 | struct search_data sdata; | ||
467 | |||
468 | memset (&iroot, 0, sizeof iroot); | ||
469 | sdata.dirname = get_pathname (fmbox->dirname, ref); | ||
470 | sdata.dirlen = strlen (sdata.dirname); | ||
471 | sdata.result = flist; | ||
472 | sdata.enumfun = enumfun; | ||
473 | sdata.enumdata = enumdata; | ||
474 | sdata.pattern = pattern; | ||
475 | sdata.flags = flags; | ||
476 | sdata.max_level = max_level; | ||
477 | sdata.folder = folder; | ||
478 | sdata.errcnt = 0; | ||
479 | list_helper (&sdata, NULL, sdata.dirname, 0, &iroot); | ||
480 | free (sdata.dirname); | ||
481 | /* FIXME: error code */ | ||
482 | return 0; | ||
483 | } | ||
484 | |||
485 | static int | ||
486 | folder_mbox_lsub (mu_folder_t folder, const char *ref MU_ARG_UNUSED, | ||
487 | const char *name, | ||
488 | mu_list_t flist) | ||
489 | { | ||
490 | fmbox_t fmbox = folder->data; | ||
491 | int status; | ||
492 | |||
493 | if (name == NULL || *name == '\0') | ||
494 | name = "*"; | ||
495 | |||
496 | if (fmbox->sublen > 0) | ||
497 | { | ||
498 | size_t i; | ||
499 | |||
500 | for (i = 0; i < fmbox->sublen; i++) | ||
501 | { | ||
502 | if (fmbox->subscribe[i] | ||
503 | && fnmatch (name, fmbox->subscribe[i], 0) == 0) | ||
504 | { | ||
505 | struct mu_list_response *resp; | ||
506 | resp = malloc (sizeof (*resp)); | ||
507 | if (resp == NULL) | ||
508 | { | ||
509 | status = ENOMEM; | ||
510 | break; | ||
511 | } | ||
512 | else if ((resp->name = strdup (fmbox->subscribe[i])) == NULL) | ||
513 | { | ||
514 | free (resp); | ||
515 | status = ENOMEM; | ||
516 | break; | ||
517 | } | ||
518 | resp->type = MU_FOLDER_ATTRIBUTE_FILE; | ||
519 | resp->level = 0; | ||
520 | resp->separator = '/'; | ||
521 | } | ||
522 | } | ||
523 | } | ||
524 | return status; | ||
525 | } | ||
526 | |||
527 | static int | ||
528 | folder_mbox_subscribe (mu_folder_t folder, const char *name) | ||
529 | { | ||
530 | fmbox_t fmbox = folder->data; | ||
531 | char **tmp; | ||
532 | size_t i; | ||
533 | for (i = 0; i < fmbox->sublen; i++) | ||
534 | { | ||
535 | if (fmbox->subscribe[i] && strcmp (fmbox->subscribe[i], name) == 0) | ||
536 | return 0; | ||
537 | } | ||
538 | tmp = realloc (fmbox->subscribe, (fmbox->sublen + 1) * sizeof (*tmp)); | ||
539 | if (tmp == NULL) | ||
540 | return ENOMEM; | ||
541 | fmbox->subscribe = tmp; | ||
542 | fmbox->subscribe[fmbox->sublen] = strdup (name); | ||
543 | if (fmbox->subscribe[fmbox->sublen] == NULL) | ||
544 | return ENOMEM; | ||
545 | fmbox->sublen++; | ||
546 | return 0; | ||
547 | } | ||
548 | |||
549 | static int | ||
550 | folder_mbox_unsubscribe (mu_folder_t folder, const char *name) | ||
551 | { | ||
552 | fmbox_t fmbox = folder->data; | ||
553 | size_t i; | ||
554 | for (i = 0; i < fmbox->sublen; i++) | ||
555 | { | ||
556 | if (fmbox->subscribe[i] && strcmp (fmbox->subscribe[i], name) == 0) | ||
557 | { | ||
558 | free (fmbox->subscribe[i]); | ||
559 | fmbox->subscribe[i] = NULL; | ||
560 | return 0; | ||
561 | } | ||
562 | } | ||
563 | return MU_ERR_NOENT; | ||
564 | } | ||
565 | |||
566 | static char * | ||
567 | get_pathname (const char *dirname, const char *basename) | ||
568 | { | ||
569 | char *pathname = NULL; | ||
570 | |||
571 | /* Skip eventual protocol designator. | ||
572 | FIXME: Actually, any valid URL spec should be allowed as dirname ... */ | ||
573 | if (strncmp (dirname, MU_MBOX_SCHEME, MU_MBOX_SCHEME_LEN) == 0) | ||
574 | dirname += MU_MBOX_SCHEME_LEN; | ||
575 | else if (strncmp (dirname, MU_FILE_SCHEME, MU_FILE_SCHEME_LEN) == 0) | ||
576 | dirname += MU_FILE_SCHEME_LEN; | ||
577 | |||
578 | /* null basename gives dirname. */ | ||
579 | if (basename == NULL) | ||
580 | pathname = (dirname) ? strdup (dirname) : strdup ("."); | ||
581 | /* Absolute. */ | ||
582 | else if (basename[0] == '/') | ||
583 | pathname = strdup (basename); | ||
584 | /* Relative. */ | ||
585 | else | ||
586 | { | ||
587 | size_t baselen = strlen (basename); | ||
588 | size_t dirlen = strlen (dirname); | ||
589 | while (dirlen > 0 && dirname[dirlen-1] == '/') | ||
590 | dirlen--; | ||
591 | pathname = calloc (dirlen + baselen + 2, sizeof (char)); | ||
592 | if (pathname) | ||
593 | { | ||
594 | memcpy (pathname, dirname, dirlen); | ||
595 | pathname[dirlen] = '/'; | ||
596 | strcpy (pathname + dirlen + 1, basename); | ||
597 | } | ||
598 | } | ||
599 | return pathname; | ||
600 | } | ||
601 | |||
602 | static int | ||
603 | folder_mbox_get_authority (mu_folder_t folder, mu_authority_t *pauth) | ||
604 | { | ||
605 | int status = 0; | ||
606 | if (folder->authority == NULL) | ||
607 | { | ||
608 | status = mu_authority_create_null (&folder->authority, folder); | ||
609 | } | ||
610 | if (!status && pauth) | ||
611 | *pauth = folder->authority; | ||
612 | return status; | ||
613 | } | ||
614 | 123 | ... | ... |
... | @@ -37,12 +37,6 @@ | ... | @@ -37,12 +37,6 @@ |
37 | #include <mailutils/util.h> | 37 | #include <mailutils/util.h> |
38 | #include <mailutils/cctype.h> | 38 | #include <mailutils/cctype.h> |
39 | 39 | ||
40 | static int | ||
41 | _mh_folder_init (mu_folder_t folder MU_ARG_UNUSED) | ||
42 | { | ||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | /* Check if NAME is a valid MH message name */ | 40 | /* Check if NAME is a valid MH message name */ |
47 | static int | 41 | static int |
48 | mh_message_name_p (const char *name) | 42 | mh_message_name_p (const char *name) |
... | @@ -90,13 +84,11 @@ static int | ... | @@ -90,13 +84,11 @@ static int |
90 | _mh_is_scheme (mu_record_t record, mu_url_t url, int flags) | 84 | _mh_is_scheme (mu_record_t record, mu_url_t url, int flags) |
91 | { | 85 | { |
92 | int rc = 0; | 86 | int rc = 0; |
87 | int scheme_matched = mu_url_is_scheme (url, record->scheme); | ||
93 | 88 | ||
94 | if (mu_url_is_scheme (url, record->scheme)) | 89 | if (scheme_matched || mu_scheme_autodetect_p (url)) |
95 | return MU_FOLDER_ATTRIBUTE_ALL & flags; | ||
96 | |||
97 | if (mu_scheme_autodetect_p (url)) | ||
98 | { | 90 | { |
99 | /* Attemp auto-detection */ | 91 | /* Attempt auto-detection */ |
100 | const char *path; | 92 | const char *path; |
101 | struct stat st; | 93 | struct stat st; |
102 | 94 | ||
... | @@ -104,18 +96,27 @@ _mh_is_scheme (mu_record_t record, mu_url_t url, int flags) | ... | @@ -104,18 +96,27 @@ _mh_is_scheme (mu_record_t record, mu_url_t url, int flags) |
104 | return 0; | 96 | return 0; |
105 | 97 | ||
106 | if (stat (path, &st) < 0) | 98 | if (stat (path, &st) < 0) |
107 | return 0; /* mu_mailbox_open will complain*/ | 99 | { |
108 | 100 | if (errno == ENOENT && scheme_matched) | |
101 | return MU_FOLDER_ATTRIBUTE_ALL & flags; | ||
102 | return 0; /* mu_mailbox_open will complain*/ | ||
103 | } | ||
104 | |||
109 | if (!S_ISDIR (st.st_mode)) | 105 | if (!S_ISDIR (st.st_mode)) |
110 | return 0; | 106 | return 0; |
111 | 107 | ||
112 | rc |= (MU_FOLDER_ATTRIBUTE_DIRECTORY & flags); | 108 | if (scheme_matched) |
109 | rc = MU_FOLDER_ATTRIBUTE_ALL; | ||
110 | else | ||
111 | { | ||
112 | rc |= MU_FOLDER_ATTRIBUTE_DIRECTORY; | ||
113 | 113 | ||
114 | if ((flags & MU_FOLDER_ATTRIBUTE_FILE) && mh_dir_p (path)) | 114 | if ((flags & MU_FOLDER_ATTRIBUTE_FILE) && mh_dir_p (path)) |
115 | return rc | MU_FOLDER_ATTRIBUTE_FILE; | 115 | rc |= MU_FOLDER_ATTRIBUTE_FILE; |
116 | } | ||
116 | } | 117 | } |
117 | 118 | ||
118 | return 0; | 119 | return rc & flags; |
119 | } | 120 | } |
120 | 121 | ||
121 | static int | 122 | static int |
... | @@ -142,7 +143,7 @@ static struct _mu_record _mh_record = | ... | @@ -142,7 +143,7 @@ static struct _mu_record _mh_record = |
142 | mu_url_expand_path, /* Url init. */ | 143 | mu_url_expand_path, /* Url init. */ |
143 | _mailbox_mh_init, /* Mailbox init. */ | 144 | _mailbox_mh_init, /* Mailbox init. */ |
144 | NULL, /* Mailer init. */ | 145 | NULL, /* Mailer init. */ |
145 | _mh_folder_init, /* Folder init. */ | 146 | _mu_fsfolder_init, /* Folder init. */ |
146 | NULL, /* back pointer. */ | 147 | NULL, /* back pointer. */ |
147 | _mh_is_scheme, /* _is_scheme method. */ | 148 | _mh_is_scheme, /* _is_scheme method. */ |
148 | NULL, /* _get_url method. */ | 149 | NULL, /* _get_url method. */ | ... | ... |
... | @@ -50,6 +50,7 @@ $(srcdir)/package.m4: $(top_srcdir)/configure.ac | ... | @@ -50,6 +50,7 @@ $(srcdir)/package.m4: $(top_srcdir)/configure.ac |
50 | 50 | ||
51 | INCLUDES = @MU_LIB_COMMON_INCLUDES@ | 51 | INCLUDES = @MU_LIB_COMMON_INCLUDES@ |
52 | noinst_PROGRAMS = \ | 52 | noinst_PROGRAMS = \ |
53 | fldel\ | ||
53 | lstuid\ | 54 | lstuid\ |
54 | mbdel\ | 55 | mbdel\ |
55 | mimetest\ | 56 | mimetest\ | ... | ... |
testsuite/fldel.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2010, 2011 Free Software Foundation, Inc. | ||
3 | |||
4 | GNU Mailutils is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 3, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | GNU Mailutils is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ | ||
16 | |||
17 | #ifdef HAVE_CONFIG_H | ||
18 | # include <config.h> | ||
19 | #endif | ||
20 | #include <unistd.h> | ||
21 | #include <stdio.h> | ||
22 | #include <stdlib.h> | ||
23 | #include <mailutils/mailutils.h> | ||
24 | |||
25 | int | ||
26 | main (int argc, char **argv) | ||
27 | { | ||
28 | int rc; | ||
29 | mu_folder_t f; | ||
30 | |||
31 | if (argc != 3) | ||
32 | { | ||
33 | fprintf (stderr, "usage: %s URL NAME\n", argv[0]); | ||
34 | return 1; | ||
35 | } | ||
36 | |||
37 | mu_register_all_mbox_formats (); | ||
38 | |||
39 | MU_ASSERT (mu_folder_create (&f, argv[1])); | ||
40 | rc = mu_folder_delete (f, argv[2]); | ||
41 | if (rc) | ||
42 | { | ||
43 | if (rc == ENOTEMPTY) | ||
44 | { | ||
45 | printf ("mailbox removed, but has subfolders\n"); | ||
46 | rc = 0; | ||
47 | } | ||
48 | else | ||
49 | fprintf (stderr, "%s\n", mu_strerror (rc)); | ||
50 | } | ||
51 | mu_folder_destroy (&f); | ||
52 | |||
53 | return rc != 0; | ||
54 | } |
-
Please register or sign in to post a comment