[Dovecot] maildir rename_subfolders() and listescape interaction
I'd like to flag a problem we are observing that looks like it is caused by the listescape-plugin.c. I realize that this plugin is not part of the standard Dovecot 1.0 distribution but I would appreciate any insights or suggestions for fixes that anyone is kind enough to offer.
The problem concerns subfolder renames when used in conjunction with Maildir folders (I've not tested this against any other folder type).
Without listescape plugin:
mail_location: maildir:%h/Maildir:INDEX=%h/index:CONTROL=%h/control
mail_plugins(default): quota imap_quota
mail_plugins(imap): quota imap_quota
namespace:
type: private
separator: /
inbox: yes
01 LIST "" *
- LIST (\HasNoChildren) "/" "INBOX" 01 OK List completed. 02 CREATE a 02 OK Create completed. 03 CREATE a/b 03 OK Create completed. 04 LIST "" *
- LIST (\HasChildren) "/" "a"
- LIST (\HasNoChildren) "/" "INBOX"
- LIST (\HasNoChildren) "/" "a/b" 04 OK List completed. 05 RENAME a c 05 OK Rename completed. 06 LIST "" *
- LIST (\HasChildren) "/" "c"
- LIST (\HasNoChildren) "/" "INBOX"
- LIST (\HasNoChildren) "/" "c/b" 06 OK List completed. 07 LOGOUT
- BYE Logging out 07 OK Logout completed.
With listescape plugin:
mail_location: maildir:%h/Maildir:INDEX=%h/index:CONTROL=%h/control
mail_plugins(default): quota imap_quota listescape
mail_plugins(imap): quota imap_quota listescape
namespace:
type: private
separator: /
inbox: yes
01 LIST "" *
- LIST (\HasNoChildren) "/" "INBOX" 01 OK List completed. 02 CREATE a 02 OK Create completed. 03 CREATE a/b 03 OK Create completed. 04 LIST "" *
- LIST (\HasChildren) "/" "a"
- LIST (\HasNoChildren) "/" "INBOX"
- LIST (\HasNoChildren) "/" "a/b" 04 OK List completed. 05 RENAME a c 05 NO Internal error occurred. Refer to server log for more information. [2007-08-30 19:33:41] 06 LIST "" *
- LIST (\HasNoChildren) "/" "a/b"
- LIST (\HasNoChildren) "/" "c"
- LIST (\HasNoChildren) "/" "INBOX" 06 OK List completed. 07 LOGOUT
- BYE Logging out 07 OK Logout completed.
Seemingly the only relevant log entry is
@4000000046d70d8f1f72b66c dovecot: Error: IMAP(pod): rename(/srv/mail/home/test0/pod/Maildir/.a/b, /srv/mail/home/test0/pod/Maildir/.c/b) failed: No such file or directory
Note the response to tag 05 in each case. The 06 list response in the listescape case is not unexpected given the nature of the failure.
My initial reading of rename_subfolders() from maildir-storage.c suggests that the calls through maildir_mailbox_list_init() and maildir_mailbox_list_next() are returning "external" style names (i.e. ones that present "/" as the hierarchy separator) to rename_subfolders(), which is an "internal" helper function. This is supported by the logged error message.
I am afraid I am yet to get my head around the actual code path and the escaping and unescaping that is going on so am not able to suggest a fix as yet.
"pod" == pod <pod@herald.ox.ac.uk> writes:
pod> I'd like to flag a problem we are observing that looks like it is pod> caused by the listescape-plugin.c. I realize that this plugin is pod> not part of the standard Dovecot 1.0 distribution but I would pod> appreciate any insights or suggestions for fixes that anyone is pod> kind enough to offer. [...] Update: my original analysis of this was incorrect. The 'internal' functions are correctly using 'internal' names, however maildir_mailbox_list_next() references storage->hierarchy_sep to obtain a char with which to join together path elements. Under listescape however storage->hierarchy_sep == '/' so non-existent pathnames are generated. I've come up with the following workaround but I can't help feeling it is maybe a little fragile. Timo: please consider applying this to <http://dovecot.org/patches/1.0/listescape-plugin.c> diff -r 70cc4b8884ef src/plugins/listescape/listescape-plugin.c --- a/src/plugins/listescape/listescape-plugin.c Tue Jul 31 19:42:03 2007 +0100 +++ b/src/plugins/listescape/listescape-plugin.c Fri Aug 31 19:21:05 2007 +0100 @@ -160,10 +160,16 @@ listescape_mailbox_rename(struct mail_st { struct listescape_mail_storage *mstorage = LIST_ESCAPE_CONTEXT(storage); + char saved_hierarchy_sep; + int ret; oldname = list_escape(oldname); newname = list_escape(newname); - return mstorage->super.mailbox_rename(storage, oldname, newname); + saved_hierarchy_sep = storage->hierarchy_sep; + storage->hierarchy_sep = REAL_SEP; + ret = mstorage->super.mailbox_rename(storage, oldname, newname); + storage->hierarchy_sep = saved_hierarchy_sep; + return ret; } static int listescape_set_subscribed(struct mail_storage *storage,
On Mon, 2007-09-03 at 15:19 +0100, pod wrote:
Update: my original analysis of this was incorrect. The 'internal' functions are correctly using 'internal' names, however maildir_mailbox_list_next() references storage->hierarchy_sep to obtain a char with which to join together path elements. Under listescape however storage->hierarchy_sep == '/' so non-existent pathnames are generated.
I've come up with the following workaround but I can't help feeling it is maybe a little fragile.
Well, I think it's better to change Dovecot itself: http://hg.dovecot.org/dovecot-1.0/rev/5c798e920045
participants (2)
-
pod
-
Timo Sirainen