Mercurial > dovecot > core-2.2
changeset 15134:eff1d11ce14b
lib-storage: MAILBOX_LIST_ITER_SKIP_ALIASES now skips also "alias symlinks"
An "alias symlink" is a symlink that points to the same directory. These can
safely be skipped when iterating through all mails in all mailboxes (unlike
other symlinks that may point to external storages).
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Tue, 18 Sep 2012 18:40:17 +0300 |
parents | 8cec3b4c43ca |
children | 1937b38f50f0 |
files | src/lib-storage/list/mailbox-list-fs-iter.c src/lib-storage/list/mailbox-list-maildir-iter.c src/lib-storage/mailbox-guid-cache.c src/lib-storage/mailbox-list-private.h src/lib-storage/mailbox-list.c src/lib-storage/mailbox-list.h |
diffstat | 6 files changed, 51 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-storage/list/mailbox-list-fs-iter.c Fri Sep 14 20:51:02 2012 +0300 +++ b/src/lib-storage/list/mailbox-list-fs-iter.c Tue Sep 18 18:40:17 2012 +0300 @@ -183,6 +183,12 @@ /* mailbox doesn't match any patterns, we don't care about it */ return 0; } + if ((ctx->ctx.flags & MAILBOX_LIST_ITER_SKIP_ALIASES) != 0) { + ret = mailbox_list_dirent_is_alias_symlink(ctx->ctx.list, + dir_path, d); + if (ret != 0) + return ret < 0 ? -1 : 0; + } ret = ctx->ctx.list->v. get_mailbox_flags(ctx->ctx.list, dir_path, d->d_name, mailbox_list_get_file_type(d), &info_flags);
--- a/src/lib-storage/list/mailbox-list-maildir-iter.c Fri Sep 14 20:51:02 2012 +0300 +++ b/src/lib-storage/list/mailbox-list-maildir-iter.c Tue Sep 18 18:40:17 2012 +0300 @@ -323,6 +323,11 @@ if (maildir_delete_trash_dir(ctx, fname)) return 0; + if ((ctx->ctx.flags & MAILBOX_LIST_ITER_SKIP_ALIASES) != 0) { + ret = mailbox_list_dirent_is_alias_symlink(list, ctx->dir, d); + if (ret != 0) + return ret < 0 ? -1 : 0; + } T_BEGIN { ret = list->v.get_mailbox_flags(list, ctx->dir, fname, mailbox_list_get_file_type(d), &flags);
--- a/src/lib-storage/mailbox-guid-cache.c Fri Sep 14 20:51:02 2012 +0300 +++ b/src/lib-storage/mailbox-guid-cache.c Tue Sep 18 18:40:17 2012 +0300 @@ -56,6 +56,7 @@ list->guid_cache_errors = FALSE; ctx = mailbox_list_iter_init(list, "*", + MAILBOX_LIST_ITER_SKIP_ALIASES | MAILBOX_LIST_ITER_NO_AUTO_BOXES); while ((info = mailbox_list_iter_next(ctx)) != NULL) { if ((info->flags &
--- a/src/lib-storage/mailbox-list-private.h Fri Sep 14 20:51:02 2012 +0300 +++ b/src/lib-storage/mailbox-list-private.h Tue Sep 18 18:40:17 2012 +0300 @@ -192,6 +192,9 @@ bool mailbox_list_name_is_too_large(const char *name, char sep); enum mailbox_list_file_type mailbox_list_get_file_type(const struct dirent *d); +int mailbox_list_dirent_is_alias_symlink(struct mailbox_list *list, + const char *dir_path, + const struct dirent *d); bool mailbox_list_try_get_absolute_path(struct mailbox_list *list, const char **name); int mailbox_list_create_missing_index_dir(struct mailbox_list *list,
--- a/src/lib-storage/mailbox-list.c Fri Sep 14 20:51:02 2012 +0300 +++ b/src/lib-storage/mailbox-list.c Tue Sep 18 18:40:17 2012 +0300 @@ -1282,6 +1282,39 @@ return type; } +int mailbox_list_dirent_is_alias_symlink(struct mailbox_list *list, + const char *dir_path, + const struct dirent *d) +{ + struct stat st; + int ret; + + if (mailbox_list_get_file_type(d) == MAILBOX_LIST_FILE_TYPE_SYMLINK) + return 1; + + T_BEGIN { + const char *path, *readlink; + + path = t_strconcat(dir_path, "/", d->d_name, NULL); + if (lstat(path, &st) < 0) { + mailbox_list_set_critical(list, + "lstat(%s) failed: %m", path); + ret = -1; + } else if (!S_ISLNK(st.st_mode)) { + ret = 0; + } else if (t_readlink(path, &linkpath) < 0) { + i_error("readlink(%s) failed: %m", path); + ret = -1; + } else { + /* it's an alias only if it points to the same + directory */ + ret = strchr(linkpath, '/') == NULL ? 1 : 0; + } + } T_END; + return ret; +} + + static bool mailbox_list_try_get_home_path(struct mailbox_list *list, const char **name) {
--- a/src/lib-storage/mailbox-list.h Fri Sep 14 20:51:02 2012 +0300 +++ b/src/lib-storage/mailbox-list.h Tue Sep 18 18:40:17 2012 +0300 @@ -64,7 +64,9 @@ physically exist */ MAILBOX_LIST_ITER_NO_AUTO_BOXES = 0x000004, - /* For mailbox_list_iter_init_namespaces(): Skip namespaces that + /* Skip all kinds of mailbox aliases. This typically includes symlinks + that point to the same directory. Also when iterating with + mailbox_list_iter_init_namespaces() skip namespaces that have alias_for set. */ MAILBOX_LIST_ITER_SKIP_ALIASES = 0x000008, /* For mailbox_list_iter_init_namespaces(): '*' in a pattern doesn't