By Jan Srzednicki diff -ruN dovecot-1.0.2.orig/src/lib-storage/index/maildir/maildir-list.c dovecot-1.0.2/src/lib-storage/index/maildir/maildir-list.c --- dovecot-1.0.2.orig/src/lib-storage/index/maildir/maildir-list.c Sat May 19 13:14:04 2007 +++ dovecot-1.0.2/src/lib-storage/index/maildir/maildir-list.c Sat Aug 4 11:43:17 2007 @@ -58,7 +58,8 @@ string_t *mailbox; enum imap_match_result match; struct mailbox_node *node; - bool stat_dirs, created, hide; + bool stat_dirs, created, hide, prefix_subfolders; + int prefix_subfolders_int; dirp = opendir(ctx->dir); if (dirp == NULL) { @@ -72,12 +73,18 @@ stat_dirs = getenv("MAILDIR_STAT_DIRS") != NULL; + prefix_subfolders = getenv("MAILDIR_PREFIX_SUBFOLDERS_WITH_SEPARATOR") != NULL; + if ( prefix_subfolders ) + prefix_subfolders_int = 1; + else + prefix_subfolders_int = 0; + t_push(); mailbox = t_str_new(PATH_MAX); while ((d = readdir(dirp)) != NULL) { const char *fname = d->d_name; - if (fname[0] != MAILDIR_FS_SEP) + if (prefix_subfolders && fname[0] != MAILDIR_FS_SEP) continue; /* skip . and .. */ @@ -106,8 +113,8 @@ continue; } - if (fname[1] == MAILDIR_FS_SEP && - strcmp(fname+1, MAILDIR_UNLINK_DIRNAME) == 0) { + if (fname[prefix_subfolders_int] == MAILDIR_FS_SEP && + strcmp(fname+prefix_subfolders_int, MAILDIR_UNLINK_DIRNAME) == 0) { /* this directory is in the middle of being deleted, or the process trying to delete it had died. delete it ourself if it's been there longer than @@ -120,7 +127,8 @@ t_pop(); continue; } - fname++; + if (prefix_subfolders) + fname++; /* make sure the mask matches */ str_truncate(mailbox, 0); @@ -143,6 +151,11 @@ if (imap_match(glob, mailbox_c) > 0) break; } + if (! prefix_subfolders && p == NULL && + (p = strrchr(mailbox_c, '/')) != NULL ) { + str_truncate(mailbox, (size_t) (p-mailbox_c)); + mailbox_c = str_c(mailbox); + } i_assert(p != NULL); created = FALSE; @@ -217,7 +230,9 @@ struct subsfile_list_context *subsfile_ctx; const char *path, *name, *p; struct mailbox_node *node; - bool created; + bool created, prefix_subfolders; + + prefix_subfolders = getenv("MAILDIR_PREFIX_SUBFOLDERS_WITH_SEPARATOR") != NULL; path = t_strconcat(storage->control_dir != NULL ? storage->control_dir : INDEX_STORAGE(storage)->dir, @@ -244,6 +259,10 @@ if (imap_match(glob, name) > 0) break; } + if (! prefix_subfolders && p == NULL && + (p = strrchr(name, '/')) != NULL ) + name = t_strdup_until(name, p); + i_assert(p != NULL); node = mailbox_tree_get(ctx->tree_ctx, name, &created); diff -ruN dovecot-1.0.2.orig/src/lib-storage/index/maildir/maildir-storage.c dovecot-1.0.2/src/lib-storage/index/maildir/maildir-storage.c --- dovecot-1.0.2.orig/src/lib-storage/index/maildir/maildir-storage.c Wed May 30 14:16:28 2007 +++ dovecot-1.0.2/src/lib-storage/index/maildir/maildir-storage.c Sat Aug 4 11:43:24 2007 @@ -26,6 +26,7 @@ #define MAILDIR_SUBFOLDER_FILENAME "maildirfolder" + struct rename_context { bool found; size_t oldnamelen; @@ -279,6 +280,17 @@ static const char *maildir_get_absolute_path(const char *name) { const char *p; + bool prefix_subfolders; + char *separator; + + prefix_subfolders = getenv("MAILDIR_PREFIX_SUBFOLDERS_WITH_SEPARATOR") != NULL; + + if (prefix_subfolders && unlink) + separator = MAILDIR_FS_SEP_S MAILDIR_FS_SEP_S; + else if (prefix_subfolders || unlink) + separator = MAILDIR_FS_SEP_S; + else + separator = ""; if (home_try_expand(&name) < 0) { /* fallback to using as ~name */ @@ -289,11 +301,15 @@ if (p == NULL) return name; return t_strconcat(t_strdup_until(name, p+1), - MAILDIR_FS_SEP_S, p+1, NULL); + separator, p+1, NULL); } const char *maildir_get_path(struct index_storage *storage, const char *name) { + bool prefix_subfolders; + + prefix_subfolders = getenv("MAILDIR_PREFIX_SUBFOLDERS_WITH_SEPARATOR") != NULL; + if ((storage->storage.flags & MAIL_STORAGE_FLAG_FULL_FS_ACCESS) != 0 && (*name == '/' || *name == '~')) return maildir_get_absolute_path(name); @@ -303,7 +319,8 @@ storage->inbox_path : storage->dir; } - return t_strconcat(storage->dir, "/"MAILDIR_FS_SEP_S, name, NULL); + return t_strconcat(storage->dir, prefix_subfolders ? "/"MAILDIR_FS_SEP_S : + "/", name, NULL); } static const char * @@ -319,6 +336,10 @@ static const char *maildir_get_index_path(struct index_storage *storage, const char *name) { + bool prefix_subfolders; + + prefix_subfolders = getenv("MAILDIR_PREFIX_SUBFOLDERS_WITH_SEPARATOR") != NULL; + if (storage->index_dir == NULL) return NULL; @@ -330,12 +351,17 @@ (*name == '/' || *name == '~')) return maildir_get_absolute_path(name); - return t_strconcat(storage->index_dir, "/"MAILDIR_FS_SEP_S, name, NULL); + return t_strconcat(storage->index_dir, + prefix_subfolders ? "/"MAILDIR_FS_SEP_S :"/", name, NULL); } static const char *maildir_get_control_path(struct maildir_storage *storage, const char *name) { + bool prefix_subfolders; + + prefix_subfolders = getenv("MAILDIR_PREFIX_SUBFOLDERS_WITH_SEPARATOR") != NULL; + if (storage->control_dir == NULL) return maildir_get_path(INDEX_STORAGE(storage), name); @@ -343,8 +369,9 @@ (*name == '/' || *name == '~')) return maildir_get_absolute_path(name); - return t_strconcat(storage->control_dir, "/"MAILDIR_FS_SEP_S, - name, NULL); + return t_strconcat(storage->control_dir, + prefix_subfolders ? "/"MAILDIR_FS_SEP_S :"/", + name, NULL); } static int mkdir_verify(struct index_storage *storage, @@ -412,8 +439,11 @@ static int create_index_dir(struct index_storage *storage, const char *name) { + bool prefix_subfolders; const char *dir; + prefix_subfolders = getenv("MAILDIR_PREFIX_SUBFOLDERS_WITH_SEPARATOR") != NULL; + if (storage->index_dir == NULL) return 0; @@ -422,7 +452,8 @@ strcmp(storage->index_dir, storage->inbox_path) == 0)) return 0; - dir = t_strconcat(storage->index_dir, "/"MAILDIR_FS_SEP_S, name, NULL); + dir = t_strconcat(storage->index_dir, + prefix_subfolders ? "/"MAILDIR_FS_SEP_S :"/", name, NULL); if (mkdir_parents(dir, CREATE_MODE) < 0 && errno != EEXIST) { if (!ENOSPACE(errno)) { mail_storage_set_critical(&storage->storage, @@ -437,11 +468,14 @@ static int create_control_dir(struct maildir_storage *storage, const char *name) { const char *dir; + bool prefix_subfolders; + + prefix_subfolders = getenv("MAILDIR_PREFIX_SUBFOLDERS_WITH_SEPARATOR") != NULL; if (storage->control_dir == NULL) return 0; - dir = t_strconcat(storage->control_dir, "/"MAILDIR_FS_SEP_S, + dir = t_strconcat(storage->control_dir, prefix_subfolders ? "/"MAILDIR_FS_SEP_S :"/", name, NULL); if (mkdir_parents(dir, CREATE_MODE) < 0 && errno != EEXIST) { mail_storage_set_critical(STORAGE(storage), @@ -733,6 +767,9 @@ struct stat st; const char *src, *dest, *index_dir, *control_dir; int count; + bool prefix_subfolders; + + prefix_subfolders = getenv("MAILDIR_PREFIX_SUBFOLDERS_WITH_SEPARATOR") != NULL; mail_storage_clear_error(_storage); @@ -766,7 +803,7 @@ if (storage->index_dir != NULL && dest != NULL && strcmp(storage->index_dir, storage->dir) != 0) { index_dir = t_strconcat(storage->index_dir, - "/"MAILDIR_FS_SEP_S, name, NULL); + prefix_subfolders ? "/"MAILDIR_FS_SEP_S :"/", name, NULL); if (unlink_directory(index_dir, TRUE) < 0 && errno != ENOTEMPTY) { mail_storage_set_critical(_storage, @@ -863,16 +900,21 @@ const char *oldname, const char *newname) { const char *oldpath, *newpath; + bool prefix_subfolders; + + prefix_subfolders = getenv("MAILDIR_PREFIX_SUBFOLDERS_WITH_SEPARATOR") != NULL; if (storage->index_dir == NULL || strcmp(storage->index_dir, storage->dir) == 0) return 0; /* Rename it's index. */ - oldpath = t_strconcat(storage->index_dir, "/"MAILDIR_FS_SEP_S, - oldname, NULL); - newpath = t_strconcat(storage->index_dir, "/"MAILDIR_FS_SEP_S, - newname, NULL); + oldpath = t_strconcat(storage->index_dir, + prefix_subfolders ? "/"MAILDIR_FS_SEP_S :"/", + oldname, NULL); + newpath = t_strconcat(storage->index_dir, + prefix_subfolders ? "/"MAILDIR_FS_SEP_S :"/", + newname, NULL); if (rename(oldpath, newpath) < 0 && errno != ENOENT) { mail_storage_set_critical(&storage->storage, diff -ruN dovecot-1.0.2.orig/src/master/mail-process.c dovecot-1.0.2/src/master/mail-process.c --- dovecot-1.0.2.orig/src/master/mail-process.c Tue Jun 12 19:14:08 2007 +++ dovecot-1.0.2/src/master/mail-process.c Sat Aug 4 11:22:11 2007 @@ -247,6 +247,8 @@ env_put("MAILDIR_STAT_DIRS=1"); if (set->maildir_copy_with_hardlinks) env_put("MAILDIR_COPY_WITH_HARDLINKS=1"); + if (set->maildir_prefix_subfolders_with_separator) + env_put("MAILDIR_PREFIX_SUBFOLDERS_WITH_SEPARATOR=1"); if (set->maildir_copy_preserve_filename) env_put("MAILDIR_COPY_PRESERVE_FILENAME=1"); if (set->mail_debug) diff -ruN dovecot-1.0.2.orig/src/master/master-settings-defs.c dovecot-1.0.2/src/master/master-settings-defs.c --- dovecot-1.0.2.orig/src/master/master-settings-defs.c Sat May 19 13:14:04 2007 +++ dovecot-1.0.2/src/master/master-settings-defs.c Sat Aug 4 12:01:08 2007 @@ -77,6 +77,7 @@ DEF(SET_STR, lock_method), DEF(SET_BOOL, maildir_stat_dirs), DEF(SET_BOOL, maildir_copy_with_hardlinks), + DEF(SET_BOOL, maildir_prefix_subfolders_with_separator), DEF(SET_BOOL, maildir_copy_preserve_filename), DEF(SET_STR, mbox_read_locks), DEF(SET_STR, mbox_write_locks), diff -ruN dovecot-1.0.2.orig/src/master/master-settings.c dovecot-1.0.2/src/master/master-settings.c --- dovecot-1.0.2.orig/src/master/master-settings.c Wed Jul 11 00:40:40 2007 +++ dovecot-1.0.2/src/master/master-settings.c Sat Aug 4 11:22:23 2007 @@ -230,6 +230,7 @@ MEMBER(lock_method) "fcntl", MEMBER(maildir_stat_dirs) FALSE, MEMBER(maildir_copy_with_hardlinks) FALSE, + MEMBER(maildir_prefix_subfolders_with_separator) TRUE, MEMBER(maildir_copy_preserve_filename) FALSE, MEMBER(mbox_read_locks) "fcntl", MEMBER(mbox_write_locks) "dotlock fcntl", diff -ruN dovecot-1.0.2.orig/src/master/master-settings.h dovecot-1.0.2/src/master/master-settings.h --- dovecot-1.0.2.orig/src/master/master-settings.h Tue Jun 12 18:42:52 2007 +++ dovecot-1.0.2/src/master/master-settings.h Sat Aug 4 11:48:49 2007 @@ -85,6 +85,7 @@ const char *lock_method; bool maildir_stat_dirs; bool maildir_copy_with_hardlinks; + bool maildir_prefix_subfolders_with_separator; bool maildir_copy_preserve_filename; const char *mbox_read_locks; const char *mbox_write_locks;