[dovecot-cvs]
dovecot/src/lib-storage/index/maildir maildir-list.c,1.22,1.23
maildir-storage.c,1.50,1.51 maildir-storage.h,1.17,1.18
cras at procontrol.fi
cras at procontrol.fi
Sun Jul 27 03:53:07 EEST 2003
- Previous message: [dovecot-cvs] dovecot/src/lib-storage mailbox-tree.c,NONE,1.1
mailbox-tree.h,NONE,1.1 Makefile.am,1.8,1.9
mail-storage.h,1.52,1.53 proxy-mail-storage.c,1.1,1.2
- Next message: [dovecot-cvs]
dovecot/src/lib-storage/index/mbox mbox-list.c,1.20,1.21
mbox-storage.h,1.16,1.17
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /home/cvs/dovecot/src/lib-storage/index/maildir
In directory danu:/tmp/cvs-serv8554/lib-storage/index/maildir
Modified Files:
maildir-list.c maildir-storage.c maildir-storage.h
Log Message:
API change: Mailbox list sorting must now always done by storage itself if
it's needed.
Maildir listing rewritten.
Index: maildir-list.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/maildir/maildir-list.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- maildir-list.c 1 Jul 2003 18:14:18 -0000 1.22
+++ maildir-list.c 26 Jul 2003 23:53:05 -0000 1.23
@@ -1,62 +1,229 @@
/* Copyright (C) 2002 Timo Sirainen */
#include "lib.h"
-#include "hostpid.h"
+#include "ioloop.h"
+#include "str.h"
#include "home-expand.h"
#include "unlink-directory.h"
#include "imap-match.h"
#include "subscription-file/subscription-file.h"
-#include "maildir-index.h"
#include "maildir-storage.h"
+#include "mailbox-tree.h"
#include <dirent.h>
#include <sys/stat.h>
+#define MAILBOX_FLAG_MATCHED 0x40000000
+
struct mailbox_list_context {
- pool_t pool, list_pool;
+ pool_t pool;
struct mail_storage *storage;
const char *dir, *prefix;
enum mailbox_list_flags flags;
- DIR *dirp;
- struct imap_match_glob *glob;
- struct subsfile_list_context *subsfile_ctx;
-
- struct mailbox_list *(*next)(struct mailbox_list_context *ctx);
+ struct mailbox_tree_context *tree_ctx;
+ string_t *node_path;
+ size_t parent_pos;
+ struct mailbox_node *root, *next_node;
struct mailbox_list list;
int failed;
};
-static struct mailbox_list *maildir_list_subs(struct mailbox_list_context *ctx);
-static struct mailbox_list *maildir_list_next(struct mailbox_list_context *ctx);
+static void maildir_nodes_fix(struct mailbox_node *node, int is_subs)
+{
+ while (node != NULL) {
+ if (node->children != NULL) {
+ node->flags |= MAILBOX_CHILDREN;
+ maildir_nodes_fix(node->children, is_subs);
+ } else if ((node->flags & MAILBOX_PLACEHOLDER) != 0) {
+ if (!is_subs) {
+ node->flags &= ~MAILBOX_PLACEHOLDER;
+ node->flags |= MAILBOX_NOSELECT;
+ }
+ } else {
+ if ((node->flags & MAILBOX_CHILDREN) == 0)
+ node->flags |= MAILBOX_NOCHILDREN;
+ }
+ node = node->next;
+ }
+}
-static enum mailbox_flags maildir_get_marked_flags(const char *dir)
+static int maildir_fill_readdir(struct mailbox_list_context *ctx,
+ struct imap_match_glob *glob, int update_only)
{
- struct stat st_new, st_cur;
+ DIR *dirp;
+ struct dirent *d;
+ const char *path, *p;
+ string_t *mailbox;
+ enum imap_match_result match;
+ struct mailbox_node *node;
+ int created;
- /* assume marked if new/ has been modified later than cur/ */
- if (stat(t_strconcat(dir, "/new", NULL), &st_new) < 0)
- return MAILBOX_UNMARKED;
+ dirp = opendir(ctx->dir);
+ if (dirp == NULL) {
+ if (errno != ENOENT) {
+ mail_storage_set_critical(ctx->storage,
+ "opendir(%s) failed: %m", ctx->dir);
+ return FALSE;
+ }
+ }
- if (stat(t_strconcat(dir, "/cur", NULL), &st_cur) < 0)
- return MAILBOX_UNMARKED;
+ /* INBOX exists always */
+ if (imap_match(glob, "INBOX") > 0 && !update_only) {
+ node = mailbox_tree_get(ctx->tree_ctx, "INBOX", NULL);
+ node->flags |= MAILBOX_FLAG_MATCHED;
+ node->flags &= ~(MAILBOX_PLACEHOLDER | MAILBOX_NONEXISTENT);
+ }
+
+ mailbox = t_str_new(PATH_MAX);
+ while ((d = readdir(dirp)) != NULL) {
+ const char *fname = d->d_name;
+
+ if (fname[0] != '.')
+ continue;
+
+ /* skip . and .. */
+ if (fname[1] == '\0' || (fname[1] == '.' && fname[2] == '\0'))
+ continue;
+
+ /* FIXME: kludges. these files must be renamed later */
+ if (strcmp(fname, ".customflags") == 0 ||
+ strcmp(fname, ".subscriptions") == 0)
+ continue;
+
+ fname++;
+ if (*fname == '.') {
+ /* this mailbox 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
+ one hour. don't touch it if it's outside our
+ mail root dir. */
+ struct stat st;
+
+ if (*ctx->prefix == '\0')
+ continue;
+
+ t_push();
+ path = t_strdup_printf("%s/%s", ctx->dir, fname);
+ if (stat(path, &st) == 0 &&
+ st.st_mtime < ioloop_time - 3600)
+ (void)unlink_directory(path, TRUE);
+ t_pop();
+ continue;
+ }
+
+ /* make sure the mask matches */
+ str_truncate(mailbox, 0);
+ str_append(mailbox, ctx->prefix);
+ str_append(mailbox, fname);
+
+ match = imap_match(glob, str_c(mailbox));
+
+ if (match != IMAP_MATCH_YES &&
+ (match != IMAP_MATCH_PARENT || update_only))
+ continue;
+
+ if (strcasecmp(str_c(mailbox), "INBOX") == 0)
+ continue; /* ignore inboxes */
+
+ if (match == IMAP_MATCH_PARENT) {
+ t_push();
+ while ((p = strrchr(fname, '.')) != NULL) {
+ fname = t_strdup_until(fname, p);
+ p = t_strconcat(ctx->prefix, fname, NULL);
+ if (imap_match(glob, p) > 0)
+ break;
+ }
+ i_assert(p != NULL);
+
+ node = mailbox_tree_get(ctx->tree_ctx, p, &created);
+ if (created)
+ node->flags = MAILBOX_PLACEHOLDER;
+ node->flags |= MAILBOX_CHILDREN | MAILBOX_FLAG_MATCHED;
+
+ t_pop();
+ } else {
+ p = str_c(mailbox);
+ if (update_only)
+ node = mailbox_tree_update(ctx->tree_ctx, p);
+ else
+ node = mailbox_tree_get(ctx->tree_ctx, p, NULL);
+
+ if (node != NULL) {
+ node->flags &= ~(MAILBOX_PLACEHOLDER |
+ MAILBOX_NONEXISTENT);
+ node->flags |= MAILBOX_FLAG_MATCHED;
+ }
+ }
+ }
+
+ if (closedir(dirp) < 0) {
+ mail_storage_set_critical(ctx->storage,
+ "readdir(%s) failed: %m", ctx->dir);
+ return FALSE;
+ }
+
+ maildir_nodes_fix(mailbox_tree_get(ctx->tree_ctx, NULL, NULL),
+ (ctx->flags & MAILBOX_LIST_SUBSCRIBED) != 0);
+ return TRUE;
+}
+
+static int maildir_fill_subscribed(struct mailbox_list_context *ctx,
+ struct imap_match_glob *glob,
+ int nonexistent)
+{
+ struct subsfile_list_context *subsfile_ctx;
+ const char *name, *p;
+ struct mailbox_node *node;
+ int created;
+
+ subsfile_ctx = subsfile_list_init(ctx->storage);
+ if (subsfile_ctx == NULL)
+ return FALSE;
+
+ while ((name = subsfile_list_next(subsfile_ctx)) != NULL) {
+ switch (imap_match(glob, name)) {
+ case IMAP_MATCH_YES:
+ node = mailbox_tree_get(ctx->tree_ctx, name, NULL);
+ node->flags = MAILBOX_FLAG_MATCHED;
+ if (nonexistent && strcasecmp(name, "INBOX") != 0)
+ node->flags |= MAILBOX_NONEXISTENT;
+ break;
+ case IMAP_MATCH_PARENT:
+ /* placeholder */
+ while ((p = strrchr(name, '.')) != NULL) {
+ name = t_strdup_until(name, p);
+ if (imap_match(glob, name) > 0)
+ break;
+ }
+ i_assert(p != NULL);
+
+ node = mailbox_tree_get(ctx->tree_ctx, name, &created);
+ if (created) node->flags = MAILBOX_PLACEHOLDER;
+ node->flags |= MAILBOX_FLAG_MATCHED;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return subsfile_list_deinit(subsfile_ctx);
- return st_new.st_mtime <= st_cur.st_mtime ?
- MAILBOX_UNMARKED : MAILBOX_MARKED;
}
struct mailbox_list_context *
maildir_list_mailbox_init(struct mail_storage *storage,
- const char *mask, enum mailbox_list_flags flags,
- int *sorted)
+ const char *mask, enum mailbox_list_flags flags)
{
struct mailbox_list_context *ctx;
- pool_t pool;
+ struct imap_match_glob *glob;
const char *dir, *p;
+ int nonexistent;
+ pool_t pool;
- *sorted = FALSE;
mail_storage_clear_error(storage);
pool = pool_alloconly_create("maildir_list", 1024);
@@ -64,219 +231,115 @@
ctx->pool = pool;
ctx->storage = storage;
ctx->flags = flags;
+ ctx->tree_ctx = mailbox_tree_init('.');
+
+ glob = imap_match_init(pool, mask, TRUE, '.');
if ((flags & MAILBOX_LIST_SUBSCRIBED) != 0) {
- ctx->glob = imap_match_init(pool, mask, TRUE, '.');
- ctx->subsfile_ctx = subsfile_list_init(storage);
- ctx->next = maildir_list_subs;
- if (ctx->subsfile_ctx == NULL) {
+ ctx->dir = storage->dir;
+ ctx->prefix = "";
+
+ nonexistent = (flags & MAILBOX_LIST_FAST_FLAGS) == 0;
+ if (!maildir_fill_subscribed(ctx, glob, nonexistent)) {
+ mailbox_tree_deinit(ctx->tree_ctx);
pool_unref(pool);
return NULL;
}
- return ctx;
- }
-
- if (!full_filesystem_access || (p = strrchr(mask, '/')) == NULL) {
- ctx->dir = storage->dir;
- ctx->prefix = "";
} else {
- dir = t_strdup_until(mask, p);
- ctx->prefix = t_strdup_until(mask, p+1);
+ if (!full_filesystem_access ||
+ (p = strrchr(mask, '/')) == NULL) {
+ ctx->dir = storage->dir;
+ ctx->prefix = "";
+ } else {
+ dir = t_strdup_until(mask, p);
+ ctx->prefix = t_strdup_until(mask, p+1);
- if (*mask != '/' && *mask != '~')
- dir = t_strconcat(storage->dir, "/", dir, NULL);
- ctx->dir = p_strdup(pool, home_expand(dir));
+ if (*mask != '/' && *mask != '~')
+ dir = t_strconcat(storage->dir, "/", dir, NULL);
+ ctx->dir = p_strdup(pool, home_expand(dir));
+ }
}
- ctx->dirp = opendir(ctx->dir);
- if (ctx->dirp == NULL && errno != ENOENT) {
- mail_storage_set_critical(storage, "opendir(%s) failed: %m",
- ctx->dir);
- pool_unref(pool);
- return NULL;
+ if ((flags & MAILBOX_LIST_SUBSCRIBED) == 0 ||
+ (ctx->flags & MAILBOX_LIST_FAST_FLAGS) == 0) {
+ int update_only = (flags & MAILBOX_LIST_SUBSCRIBED) != 0;
+ if (!maildir_fill_readdir(ctx, glob, update_only)) {
+ mailbox_tree_deinit(ctx->tree_ctx);
+ pool_unref(pool);
+ return NULL;
+ }
}
- ctx->list_pool = pool_alloconly_create("maildir_list.list", 4096);
- ctx->glob = imap_match_init(pool, mask, TRUE, '.');
- ctx->next = maildir_list_next;
+ ctx->node_path = str_new(pool, 256);
+ ctx->root = mailbox_tree_get(ctx->tree_ctx, NULL, NULL);
return ctx;
}
int maildir_list_mailbox_deinit(struct mailbox_list_context *ctx)
{
- int failed;
-
- if (ctx->subsfile_ctx != NULL)
- failed = !subsfile_list_deinit(ctx->subsfile_ctx);
- else
- failed = ctx->failed;
-
- if (ctx->dirp != NULL)
- (void)closedir(ctx->dirp);
- if (ctx->list_pool != NULL)
- pool_unref(ctx->list_pool);
- imap_match_deinit(ctx->glob);
+ mailbox_tree_deinit(ctx->tree_ctx);
pool_unref(ctx->pool);
-
- return !failed;
+ return TRUE;
}
-static struct mailbox_list *maildir_list_subs(struct mailbox_list_context *ctx)
+static struct mailbox_node *find_next(struct mailbox_node **node,
+ string_t *path)
{
- struct stat st;
- const char *name, *path, *p;
- enum imap_match_result match = IMAP_MATCH_NO;
+ struct mailbox_node *child;
+ size_t len;
- while ((name = subsfile_list_next(ctx->subsfile_ctx)) != NULL) {
- match = imap_match(ctx->glob, name);
- if (match == IMAP_MATCH_YES || match == IMAP_MATCH_PARENT)
- break;
- }
+ while (*node != NULL) {
+ if (((*node)->flags & MAILBOX_FLAG_MATCHED) != 0)
+ return *node;
- if (name == NULL)
- return NULL;
+ if ((*node)->children != NULL) {
+ len = str_len(path);
+ if (len != 0)
+ str_append_c(path, '.');
+ str_append(path, (*node)->name);
- ctx->list.flags = 0;
- ctx->list.name = name;
+ child = find_next(&(*node)->children, path);
+ if (child != NULL)
+ return child;
- if (match == IMAP_MATCH_PARENT) {
- /* placeholder */
- ctx->list.flags = MAILBOX_PLACEHOLDER;
- while ((p = strrchr(name, '.')) != NULL) {
- name = t_strdup_until(name, p);
- if (imap_match(ctx->glob, name) > 0) {
- ctx->list.name = name;
- return &ctx->list;
- }
+ str_truncate(path, len);
}
- i_unreached();
- }
- if ((ctx->flags & MAILBOX_LIST_FAST_FLAGS) != 0)
- return &ctx->list;
-
- t_push();
- path = maildir_get_path(ctx->storage, ctx->list.name);
- if (stat(path, &st) == 0 && S_ISDIR(st.st_mode))
- ctx->list.flags = maildir_get_marked_flags(path);
- else {
- if (strcasecmp(ctx->list.name, "INBOX") == 0)
- ctx->list.flags = 0;
- else
- ctx->list.flags = MAILBOX_NONEXISTENT;
+ *node = (*node)->next;
}
- t_pop();
- return &ctx->list;
+
+ return NULL;
}
-static struct mailbox_list *maildir_list_next(struct mailbox_list_context *ctx)
+struct mailbox_list *
+maildir_list_mailbox_next(struct mailbox_list_context *ctx)
{
- struct dirent *d;
- struct stat st;
- const char *fname, *p;
- char path[PATH_MAX];
- enum imap_match_result match;
-
- if (ctx->dirp == NULL)
- return NULL;
-
- while ((d = readdir(ctx->dirp)) != NULL) {
- fname = d->d_name;
-
- if (fname[0] != '.')
- continue;
-
- /* skip . and .. */
- if (fname[1] == '\0' || (fname[1] == '.' && fname[2] == '\0'))
- continue;
-
- /* make sure the mask matches - dirs beginning with ".."
- should be deleted and we always want to check those. */
- t_push();
- match = imap_match(ctx->glob,
- t_strconcat(ctx->prefix, fname+1, NULL));
- t_pop();
- if (fname[1] != '.' && match != IMAP_MATCH_YES &&
- match != IMAP_MATCH_PARENT)
- continue;
+ struct mailbox_node *node;
- if (str_path(path, sizeof(path), ctx->dir, fname) < 0)
- continue;
+ for (node = ctx->next_node; node != NULL; node = node->next) {
+ if ((node->flags & MAILBOX_FLAG_MATCHED) != 0)
+ break;
+ }
- /* make sure it's a directory */
- if (stat(path, &st) < 0) {
- if (errno == ENOENT)
- continue; /* just deleted, ignore */
+ if (node == NULL) {
+ str_truncate(ctx->node_path, 0);
+ node = find_next(&ctx->root, ctx->node_path);
+ ctx->parent_pos = str_len(ctx->node_path);
- mail_storage_set_critical(ctx->storage,
- "stat(%s) failed: %m", path);
- ctx->failed = TRUE;
+ if (node == NULL)
return NULL;
- }
-
- if (!S_ISDIR(st.st_mode))
- continue;
-
- fname++;
- if (*fname == '.') {
- /* this mailbox 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
- one hour. don't touch it if it's outside our
- mail root dir. */
- if (st.st_mtime < 3600 && *ctx->prefix == '\0')
- (void)unlink_directory(path, TRUE);
- continue;
- }
-
- if (strcasecmp(fname, "INBOX") == 0)
- continue; /* ignore inboxes */
-
- if (match == IMAP_MATCH_PARENT) {
- ctx->list.flags =
- MAILBOX_PLACEHOLDER | MAILBOX_CHILDREN;
- while ((p = strrchr(fname, '.')) != NULL) {
- fname = t_strdup_until(fname, p);
- p = t_strconcat(ctx->prefix, fname, NULL);
- if (imap_match(ctx->glob, p) > 0) {
- ctx->list.name = p;
- return &ctx->list;
- }
- }
- i_unreached();
- }
-
- p_clear(ctx->list_pool);
- ctx->list.flags = (ctx->flags & MAILBOX_LIST_FAST_FLAGS) == 0 ?
- maildir_get_marked_flags(path) : 0;
- ctx->list.name = p_strconcat(ctx->list_pool,
- ctx->prefix, fname, NULL);
- return &ctx->list;
}
+ ctx->next_node = node->next;
- if (closedir(ctx->dirp) < 0) {
- mail_storage_set_critical(ctx->storage,
- "closedir(%s) failed: %m", ctx->dir);
- ctx->failed = TRUE;
- }
- ctx->dirp = NULL;
-
- if (imap_match(ctx->glob, "INBOX") > 0) {
- const char *path = maildir_get_path(ctx->storage, "INBOX");
-
- ctx->list.flags = (ctx->flags & MAILBOX_LIST_FAST_FLAGS) == 0 ?
- maildir_get_marked_flags(path) : 0;
- ctx->list.name = "INBOX";
- return &ctx->list;
- }
+ i_assert((node->flags & MAILBOX_FLAG_MATCHED) != 0);
+ node->flags &= ~MAILBOX_FLAG_MATCHED;
- /* we're finished */
- return NULL;
-}
+ str_truncate(ctx->node_path, ctx->parent_pos);
+ if (ctx->parent_pos != 0)
+ str_append_c(ctx->node_path, '.');
+ str_append(ctx->node_path, node->name);
-struct mailbox_list *
-maildir_list_mailbox_next(struct mailbox_list_context *ctx)
-{
- return ctx->next(ctx);
+ ctx->list.name = str_c(ctx->node_path);
+ ctx->list.flags = node->flags;
+ return &ctx->list;
}
Index: maildir-storage.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/maildir/maildir-storage.c,v
retrieving revision 1.50
retrieving revision 1.51
diff -u -d -r1.50 -r1.51
--- maildir-storage.c 26 Jul 2003 16:55:11 -0000 1.50
+++ maildir-storage.c 26 Jul 2003 23:53:05 -0000 1.51
@@ -536,14 +536,14 @@
struct mailbox_list *list;
const char *oldpath, *newpath, *new_listname;
size_t oldnamelen;
- int sorted, ret;
+ int ret;
ret = 0;
oldnamelen = strlen(oldname);
ctx = storage->list_mailbox_init(storage,
t_strconcat(oldname, ".*", NULL),
- MAILBOX_LIST_FAST_FLAGS, &sorted);
+ MAILBOX_LIST_FAST_FLAGS);
while ((list = maildir_list_mailbox_next(ctx)) != NULL) {
i_assert(oldnamelen <= strlen(list->name));
Index: maildir-storage.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/maildir/maildir-storage.h,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- maildir-storage.h 26 Jul 2003 16:33:22 -0000 1.17
+++ maildir-storage.h 26 Jul 2003 23:53:05 -0000 1.18
@@ -17,8 +17,7 @@
struct mailbox_list_context *
maildir_list_mailbox_init(struct mail_storage *storage,
- const char *mask, enum mailbox_list_flags flags,
- int *sorted);
+ const char *mask, enum mailbox_list_flags flags);
int maildir_list_mailbox_deinit(struct mailbox_list_context *ctx);
struct mailbox_list *
maildir_list_mailbox_next(struct mailbox_list_context *ctx);
- Previous message: [dovecot-cvs] dovecot/src/lib-storage mailbox-tree.c,NONE,1.1
mailbox-tree.h,NONE,1.1 Makefile.am,1.8,1.9
mail-storage.h,1.52,1.53 proxy-mail-storage.c,1.1,1.2
- Next message: [dovecot-cvs]
dovecot/src/lib-storage/index/mbox mbox-list.c,1.20,1.21
mbox-storage.h,1.16,1.17
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the dovecot-cvs
mailing list