Commit 33a5d852 33a5d85239028bc3e34eec59909253d12d5434f4 by Sergey Poznyakoff

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.
1 parent a8374536
...@@ -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
......
...@@ -25,6 +25,7 @@ libmailbox_la_SOURCES = \ ...@@ -25,6 +25,7 @@ libmailbox_la_SOURCES = \
25 body.c\ 25 body.c\
26 envelope.c\ 26 envelope.c\
27 folder.c\ 27 folder.c\
28 fsfolder.c\
28 hdrfirst.c\ 29 hdrfirst.c\
29 hdritr.c\ 30 hdritr.c\
30 header.c\ 31 header.c\
......
...@@ -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 }
......
...@@ -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
......
...@@ -12,6 +12,7 @@ decode2047 ...@@ -12,6 +12,7 @@ decode2047
12 encode2047 12 encode2047
13 fltst 13 fltst
14 fsaf 14 fsaf
15 fsfolder
15 imapio 16 imapio
16 listop 17 listop
17 mailcap 18 mailcap
......
...@@ -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\
......
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 }
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
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
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. */
......
...@@ -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. */
......
1 atconfig 1 atconfig
2 atlocal 2 atlocal
3 fldel
3 package.m4 4 package.m4
4 testsuite 5 testsuite
5 testsuite.dir 6 testsuite.dir
......
...@@ -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\
......
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 }