[dovecot-cvs] dovecot/src/lib-storage/index/maildir maildir-storage.c, 1.153, 1.154 maildir-storage.h, 1.64, 1.65
tss at dovecot.org
tss at dovecot.org
Thu Mar 29 10:59:23 EEST 2007
- Previous message: [dovecot-cvs] dovecot/src/lib-storage/index/dbox dbox-file.c, 1.13, 1.14 dbox-storage.c, 1.38, 1.39 dbox-storage.h, 1.17, 1.18 dbox-sync-expunge.c, 1.22, 1.23 dbox-sync-full.c, 1.10, 1.11 dbox-uidlist.c, 1.46, 1.47
- Next message: [dovecot-cvs] dovecot/src/lib-storage/index/mbox mbox-storage.c, 1.170, 1.171
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /var/lib/cvs/dovecot/src/lib-storage/index/maildir
In directory talvi:/tmp/cvs-serv11000/lib-storage/index/maildir
Modified Files:
maildir-storage.c maildir-storage.h
Log Message:
Moved delete/rename operations to mailbox_list API. Fixed mbox/maildir to
work with either fs/maildir++ directory layout. They can be changed by
appending :LAYOUT=fs|maildir++ to mail_location.
Index: maildir-storage.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/maildir/maildir-storage.c,v
retrieving revision 1.153
retrieving revision 1.154
diff -u -d -r1.153 -r1.154
--- maildir-storage.c 27 Mar 2007 19:59:28 -0000 1.153
+++ maildir-storage.c 29 Mar 2007 07:59:19 -0000 1.154
@@ -4,6 +4,7 @@
#include "ioloop.h"
#include "array.h"
#include "hostpid.h"
+#include "str.h"
#include "home-expand.h"
#include "mkdir-parents.h"
#include "unlink-directory.h"
@@ -15,6 +16,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include <dirent.h>
#include <unistd.h>
#include <sys/stat.h>
@@ -23,6 +25,10 @@
#define MAILDIR_PLUSPLUS_DRIVER_NAME "maildir++"
#define MAILDIR_SUBFOLDER_FILENAME "maildirfolder"
+#define MAILDIR_LIST_CONTEXT(obj) \
+ *((void **)array_idx_modifiable(&(obj)->module_contexts, \
+ maildir_mailbox_list_module_id))
+
struct rename_context {
bool found;
size_t oldnamelen;
@@ -32,8 +38,26 @@
extern struct mail_storage maildir_storage;
extern struct mailbox maildir_mailbox;
+static unsigned int maildir_mailbox_list_module_id = 0;
+
static int verify_inbox(struct mail_storage *storage,
enum mailbox_open_flags *flags);
+static int
+maildir_list_delete_mailbox(struct mailbox_list *list, const char *name);
+static int
+maildir_list_rename_mailbox(struct mailbox_list *list,
+ const char *oldname, const char *newname);
+static int
+maildir_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx
+ __attr_unused__,
+ const char *dir, const char *fname,
+ enum mailbox_list_file_type type,
+ enum mailbox_info_flags *flags_r);
+static int
+maildirplusplus_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
+ const char *dir, const char *fname,
+ enum mailbox_list_file_type type,
+ enum mailbox_info_flags *flags_r);
static const char *strip_tail_slash(const char *path)
{
@@ -52,11 +76,14 @@
static int
maildir_get_list_settings(struct mailbox_list_settings *list_set,
- const char *data, enum mail_storage_flags flags)
+ const char *data, enum mail_storage_flags flags,
+ const char **layout_r)
{
bool debug = (flags & MAIL_STORAGE_FLAG_DEBUG) != 0;
const char *home, *path, *p;
+ *layout_r = MAILDIR_PLUSPLUS_DRIVER_NAME;
+
memset(list_set, 0, sizeof(*list_set));
list_set->subscription_fname = MAILDIR_SUBSCRIPTION_FILE_NAME;
list_set->maildir_name = "";
@@ -114,6 +141,9 @@
} else if (strncmp(p, "CONTROL=", 8) == 0) {
list_set->control_dir =
strip_tail_slash_and_cut(p+8);
+ } else if (strncmp(p, "LAYOUT=", 7) == 0) {
+ *layout_r =
+ strip_tail_slash_and_cut(p+7);
}
p = strchr(p, ':');
} while (p != NULL);
@@ -126,6 +156,8 @@
return -1;
}
list_set->root_dir = strip_tail_slash(list_set->root_dir);
+ if (list_set->inbox_path == NULL)
+ list_set->inbox_path = list_set->root_dir;
if (list_set->index_dir != NULL &&
strcmp(list_set->index_dir, "MEMORY") == 0)
@@ -133,6 +165,51 @@
return 0;
}
+static bool maildir_is_internal_name(const char *name)
+{
+ return strcmp(name, "cur") == 0 ||
+ strcmp(name, "new") == 0 ||
+ strcmp(name, "tmp") == 0;
+}
+
+static bool maildir_storage_is_valid_existing_name(struct mailbox_list *list,
+ const char *name)
+{
+ struct maildir_storage *storage = MAILDIR_LIST_CONTEXT(list);
+ const char *p;
+
+ if (!storage->list_super.is_valid_existing_name(list, name))
+ return FALSE;
+
+ /* Don't allow the mailbox name to end in cur/new/tmp */
+ p = strrchr(name, '/');
+ if (p != NULL)
+ name = p + 1;
+ return !maildir_is_internal_name(name);
+}
+
+static bool maildir_storage_is_valid_create_name(struct mailbox_list *list,
+ const char *name)
+{
+ struct maildir_storage *storage = MAILDIR_LIST_CONTEXT(list);
+ const char *const *tmp;
+ bool ret = TRUE;
+
+ if (!storage->list_super.is_valid_create_name(list, name))
+ return FALSE;
+
+ /* Don't allow creating mailboxes under cur/new/tmp */
+ t_push();
+ for (tmp = t_strsplit(name, "/"); *tmp != NULL; tmp++) {
+ if (maildir_is_internal_name(*tmp)) {
+ ret = FALSE;
+ break;
+ }
+ }
+ t_pop();
+ return ret;
+}
+
static struct mail_storage *
maildir_create(const char *data, const char *user,
enum mail_storage_flags flags,
@@ -143,11 +220,11 @@
struct mailbox_list_settings list_set;
struct mailbox_list *list;
enum mailbox_open_flags open_flags;
- const char *error;
+ const char *layout, *error;
struct stat st;
pool_t pool;
- if (maildir_get_list_settings(&list_set, data, flags) < 0)
+ if (maildir_get_list_settings(&list_set, data, flags, &layout) < 0)
return NULL;
list_set.mail_storage_flags = &flags;
list_set.lock_method = &lock_method;
@@ -166,14 +243,28 @@
pool = pool_alloconly_create("storage", 512+256);
storage = p_new(pool, struct maildir_storage, 1);
- if (mailbox_list_init("maildir++", &list_set,
+ if (mailbox_list_init(layout, &list_set,
mail_storage_get_list_flags(flags),
- mailbox_storage_list_is_mailbox, storage,
&list, &error) < 0) {
- i_error("maildir++: %s", error);
+ i_error("maildir %s: %s", layout, error);
pool_unref(pool);
return NULL;
}
+ storage->list_super = list->v;
+ if (strcmp(layout, MAILDIR_PLUSPLUS_DRIVER_NAME) == 0) {
+ list->v.iter_is_mailbox = maildirplusplus_iter_is_mailbox;
+ } else {
+ list->v.is_valid_existing_name =
+ maildir_storage_is_valid_existing_name;
+ list->v.is_valid_create_name =
+ maildir_storage_is_valid_create_name;
+ list->v.iter_is_mailbox = maildir_list_iter_is_mailbox;
+ }
+ list->v.delete_mailbox = maildir_list_delete_mailbox;
+ list->v.rename_mailbox = maildir_list_rename_mailbox;
+
+ array_idx_set(&list->module_contexts,
+ maildir_mailbox_list_module_id, &storage);
storage->copy_with_hardlinks =
getenv("MAILDIR_COPY_WITH_HARDLINKS") != NULL;
@@ -231,27 +322,6 @@
return TRUE;
}
-static const char *
-maildir_get_unlink_dest(struct mail_storage *storage, const char *name)
-{
- const char *root_dir;
-
- if ((storage->flags & MAIL_STORAGE_FLAG_FULL_FS_ACCESS) != 0 &&
- (*name == '/' || *name == '~'))
- return NULL;
-
- if (strcmp(mailbox_list_get_driver_name(storage->list),
- MAILDIR_PLUSPLUS_DRIVER_NAME) != 0) {
- /* Not maildir++ driver. Don't use this trick. */
- return NULL;
- }
-
- root_dir = mailbox_list_get_path(storage->list, NULL,
- MAILBOX_LIST_PATH_TYPE_DIR);
- return t_strdup_printf("%s/%c"MAILDIR_UNLINK_DIRNAME, root_dir,
- mailbox_list_get_hierarchy_sep(storage->list));
-}
-
static int mkdir_verify(struct mail_storage *storage,
const char *dir, bool verify)
{
@@ -510,7 +580,7 @@
return maildir_open(storage, name, flags);
} else if (errno == ENOENT) {
mail_storage_set_error(_storage,
- MAIL_STORAGE_ERR_MAILBOX_NOT_FOUND, name);
+ MAILBOX_LIST_ERR_MAILBOX_NOT_FOUND, name);
return NULL;
} else {
mail_storage_set_critical(_storage, "stat(%s) failed: %m",
@@ -608,275 +678,202 @@
return 0;
}
-static int maildir_mailbox_delete(struct mail_storage *_storage,
- const char *name)
+static const char *
+maildir_get_unlink_dest(struct mailbox_list *list, const char *name)
{
- struct stat st;
- const char *src, *dest, *index_dir, *control_dir;
- int count;
-
- mail_storage_clear_error(_storage);
-
- if (strcmp(name, "INBOX") == 0) {
- mail_storage_set_error(_storage, "INBOX can't be deleted.");
- return -1;
- }
+ const char *root_dir;
- if (!mailbox_list_is_valid_existing_name(_storage->list, name)) {
- mail_storage_set_error(_storage, "Invalid mailbox name");
- return -1;
- }
+ if ((list->flags & MAILBOX_LIST_FLAG_FULL_FS_ACCESS) != 0 &&
+ (*name == '/' || *name == '~'))
+ return NULL;
- /* check if the mailbox actually exists */
- src = mailbox_list_get_path(_storage->list, name,
- MAILBOX_LIST_PATH_TYPE_MAILBOX);
- if (stat(src, &st) != 0 && errno == ENOENT) {
- mail_storage_set_error(_storage,
- MAIL_STORAGE_ERR_MAILBOX_NOT_FOUND, name);
- return -1;
+ if (strcmp(mailbox_list_get_driver_name(list),
+ MAILDIR_PLUSPLUS_DRIVER_NAME) != 0) {
+ /* Not maildir++ driver. Don't use this trick. */
+ return NULL;
}
- /* Make sure the indexes are closed before trying to delete the
- directory that contains them. It can still fail with some NFS
- implementations if indexes are opened by another session, but
- that can't really be helped. */
- index_storage_destroy_unrefed();
+ root_dir = mailbox_list_get_path(list, NULL,
+ MAILBOX_LIST_PATH_TYPE_DIR);
+ return t_strdup_printf("%s/%c"MAILDIR_UNLINK_DIRNAME, root_dir,
+ mailbox_list_get_hierarchy_sep(list));
+}
- /* if there's a separate index directory, delete it before the actual
- maildir. this way we never see partially deleted mailboxes. */
- index_dir = mailbox_list_get_path(_storage->list, name,
- MAILBOX_LIST_PATH_TYPE_INDEX);
- if (strcmp(index_dir, src) != 0) {
- i_assert(*name != '/' && *name != '~');
+static int
+maildir_delete_nonrecursive(struct mailbox_list *list, const char *path,
+ const char *name)
+{
+ DIR *dir;
+ struct dirent *d;
+ string_t *full_path;
+ unsigned int dir_len;
+ bool unlinked_something = FALSE;
- if (unlink_directory(index_dir, TRUE) < 0 &&
- errno != ENOTEMPTY) {
- mail_storage_set_critical(_storage,
- "unlink_directory(%s) failed: %m", index_dir);
- return -1;
+ dir = opendir(path);
+ if (dir == NULL) {
+ if (errno == ENOENT) {
+ mailbox_list_set_error(list, t_strdup_printf(
+ MAILBOX_LIST_ERR_MAILBOX_NOT_FOUND, name));
+ } else {
+ mailbox_list_set_critical(list,
+ "opendir(%s) failed: %m", path);
}
+ return -1;
}
- control_dir = mailbox_list_get_path(_storage->list, name,
- MAILBOX_LIST_PATH_TYPE_CONTROL);
- if (strcmp(control_dir, src) != 0 &&
- strcmp(control_dir, index_dir) != 0) {
- i_assert(*name != '/' && *name != '~');
- if (unlink_directory(control_dir, TRUE) < 0 &&
- errno != ENOTEMPTY) {
- mail_storage_set_critical(_storage,
- "unlink_directory(%s) failed: %m", control_dir);
- return -1;
+ full_path = t_str_new(256);
+ str_append(full_path, path);
+ str_append_c(full_path, '/');
+ dir_len = str_len(full_path);
+
+ errno = 0;
+ while ((d = readdir(dir)) != NULL) {
+ if (d->d_name[0] == '.') {
+ /* skip . and .. */
+ if (d->d_name[1] == '\0')
+ continue;
+ if (d->d_name[1] == '.' && d->d_name[2] == '\0')
+ continue;
}
- }
- dest = maildir_get_unlink_dest(_storage, name);
- if (dest == NULL) {
- /* absolute maildir path, delete the directory directly
- without any renaming */
- dest = src;
- } else {
- /* rename the .maildir into ..DOVECOT-TRASH which atomically
- marks it as being deleted. If we die before deleting the
- ..DOVECOT-TRASH directory, it gets deleted the next time
- mailbox listing sees it. */
- count = 0;
- while (rename(src, dest) < 0 && count < 2) {
- if (errno == ENOENT) {
- /* it was just deleted under us by
- another process */
- mail_storage_set_error(_storage,
- MAIL_STORAGE_ERR_MAILBOX_NOT_FOUND,
- name);
- return -1;
- }
- if (!EDESTDIREXISTS(errno)) {
- mail_storage_set_critical(_storage,
- "rename(%s, %s) failed: %m", src, dest);
- return -1;
- }
+ str_truncate(full_path, dir_len);
+ str_append(full_path, d->d_name);
- /* already existed, delete it and try again */
- if (unlink_directory(dest, TRUE) < 0) {
- mail_storage_set_critical(_storage,
+ if (maildir_is_internal_name(d->d_name)) {
+ if (unlink_directory(str_c(full_path), TRUE) < 0) {
+ mailbox_list_set_critical(list,
"unlink_directory(%s) failed: %m",
- dest);
- return -1;
+ str_c(full_path));
+ } else {
+ unlinked_something = TRUE;
}
- count++;
+ continue;
}
- }
- if (unlink_directory(dest, TRUE) < 0 && errno != ENOTEMPTY) {
- mail_storage_set_critical(_storage,
- "unlink_directory(%s) failed: %m", dest);
-
- /* it's already renamed to ..dir, which means it's deleted
- as far as the client is concerned. Report success. */
+ /* trying to unlink() a directory gives either EPERM or EISDIR
+ (non-POSIX). it doesn't really work anywhere in practise,
+ so don't bother stat()ing the file first */
+ if (unlink(str_c(full_path)) == 0)
+ unlinked_something = TRUE;
+ else if (errno != ENOENT && errno != EISDIR && errno != EPERM) {
+ mailbox_list_set_critical(list,
+ "unlink_directory(%s) failed: %m",
+ str_c(full_path));
+ }
}
- return 0;
-}
-
-static int rename_dir(struct mail_storage *storage,
- enum mailbox_list_path_type type,
- const char *oldname, const char *newname)
-{
- const char *oldpath, *newpath;
-
- oldpath = mailbox_list_get_path(storage->list, oldname, type);
- newpath = mailbox_list_get_path(storage->list, newname, type);
- if (strcmp(oldpath, newpath) == 0)
- return 0;
+ if (closedir(dir) < 0) {
+ mailbox_list_set_critical(list, "closedir(%s) failed: %m",
+ path);
+ }
- if (rename(oldpath, newpath) < 0 && errno != ENOENT) {
- mail_storage_set_critical(storage, "rename(%s, %s) failed: %m",
- oldpath, newpath);
+ if (rmdir(path) == 0)
+ unlinked_something = TRUE;
+ else if (errno != ENOENT && errno != ENOTEMPTY) {
+ mailbox_list_set_critical(list, "rmdir(%s) failed: %m", path);
return -1;
}
+ if (!unlinked_something) {
+ mailbox_list_set_error(list, t_strdup_printf(
+ "Directory %s isn't empty, can't delete it.", name));
+ return -1;
+ }
return 0;
}
-static int rename_subfolders(struct mail_storage *storage,
- const char *oldname, const char *newname)
+static int
+maildir_list_delete_mailbox(struct mailbox_list *list, const char *name)
{
- struct mailbox_list_iterate_context *iter;
- struct mailbox_info *info;
- ARRAY_DEFINE(names_arr, const char *);
- const char *mask, *oldpath, *newpath, *old_listname, *new_listname;
- const char *const *names;
- unsigned int i, count;
- size_t oldnamelen;
- pool_t pool;
- int ret;
-
- ret = 0;
- oldnamelen = strlen(oldname);
-
- /* first get a list of the subfolders and save them to memory, because
- we can't rely on readdir() not skipping files while the directory
- is being modified. this doesn't protect against modifications by
- other processes though. */
- pool = pool_alloconly_create("Maildir subfolders list", 1024);
- i_array_init(&names_arr, 64);
+ struct maildir_storage *storage = MAILDIR_LIST_CONTEXT(list);
+ struct stat st;
+ const char *src, *dest;
+ int count;
- mask = t_strdup_printf("%s%c*", oldname,
- mailbox_list_get_hierarchy_sep(storage->list));
- iter = mailbox_list_iter_init(storage->list, mask,
- MAILBOX_LIST_ITER_FAST_FLAGS);
- while ((info = mailbox_list_iter_next(iter)) != NULL) {
- const char *name;
+ /* Make sure the indexes are closed before trying to delete the
+ directory that contains them. It can still fail with some NFS
+ implementations if indexes are opened by another session, but
+ that can't really be helped. */
+ index_storage_destroy_unrefed();
- i_assert(oldnamelen <= strlen(info->name));
+ /* delete the index and control directories */
+ if (storage->list_super.delete_mailbox(list, name) < 0)
+ return -1;
- name = p_strdup(pool, info->name + oldnamelen);
- array_append(&names_arr, &name, 1);
- }
- if (mailbox_list_iter_deinit(&iter) < 0) {
- ret = -1;
- names = NULL; count = 0;
- } else {
- names = array_get(&names_arr, &count);
+ /* check if the mailbox actually exists */
+ src = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_MAILBOX);
+ if (stat(src, &st) != 0 && errno == ENOENT) {
+ mailbox_list_set_error(list, t_strdup_printf(
+ MAILBOX_LIST_ERR_MAILBOX_NOT_FOUND, name));
+ return -1;
}
- for (i = 0; i < count; i++) {
- t_push();
-
- old_listname = t_strconcat(oldname, names[i], NULL);
- new_listname = t_strconcat(newname, names[i], NULL);
- oldpath = mailbox_list_get_path(storage->list, old_listname,
- MAILBOX_LIST_PATH_TYPE_MAILBOX);
- newpath = mailbox_list_get_path(storage->list, new_listname,
- MAILBOX_LIST_PATH_TYPE_MAILBOX);
-
- /* FIXME: it's possible to merge two folders if either one of
- them doesn't have existing root folder. We could check this
- but I'm not sure if it's worth it. It could be even
- considered as a feature.
+ dest = maildir_get_unlink_dest(list, name);
+ if (dest == NULL) {
+ /* delete the directory directly without any renaming */
+ return maildir_delete_nonrecursive(list, src, name);
+ }
- Anyway, the bug with merging is that if both folders have
- identically named subfolder they conflict. Just ignore those
- and leave them under the old folder. */
- if (rename(oldpath, newpath) == 0 || EDESTDIREXISTS(errno))
- ret = 1;
- else {
- mail_storage_set_critical(storage,
- "rename(%s, %s) failed: %m", oldpath, newpath);
- ret = -1;
- t_pop();
- break;
+ /* rename the .maildir into ..DOVECOT-TRASH which atomically
+ marks it as being deleted. If we die before deleting the
+ ..DOVECOT-TRASH directory, it gets deleted the next time
+ mailbox listing sees it. */
+ count = 0;
+ while (rename(src, dest) < 0 && count < 2) {
+ if (errno == ENOENT) {
+ /* it was just deleted under us by
+ another process */
+ mailbox_list_set_error(list, t_strdup_printf(
+ MAILBOX_LIST_ERR_MAILBOX_NOT_FOUND, name));
+ return -1;
+ }
+ if (!EDESTDIREXISTS(errno)) {
+ mailbox_list_set_critical(list,
+ "rename(%s, %s) failed: %m", src, dest);
+ return -1;
}
- (void)rename_dir(storage, MAILBOX_LIST_PATH_TYPE_CONTROL,
- old_listname, new_listname);
- (void)rename_dir(storage, MAILBOX_LIST_PATH_TYPE_INDEX,
- old_listname, new_listname);
- t_pop();
+ /* already existed, delete it and try again */
+ if (unlink_directory(dest, TRUE) < 0) {
+ mailbox_list_set_critical(list,
+ "unlink_directory(%s) failed: %m", dest);
+ return -1;
+ }
+ count++;
}
- array_free(&names_arr);
- pool_unref(pool);
- return ret;
+ if (unlink_directory(dest, TRUE) < 0 && errno != ENOTEMPTY) {
+ mailbox_list_set_critical(list,
+ "unlink_directory(%s) failed: %m", dest);
+
+ /* it's already renamed to ..dir, which means it's
+ deleted as far as the client is concerned. Report
+ success. */
+ }
+ return 0;
}
-static int maildir_mailbox_rename(struct mail_storage *_storage,
- const char *oldname, const char *newname)
+static int maildir_list_rename_mailbox(struct mailbox_list *list,
+ const char *oldname, const char *newname)
{
- const char *oldpath, *newpath;
- int ret;
- bool found;
-
- mail_storage_clear_error(_storage);
-
- if (!mailbox_list_is_valid_existing_name(_storage->list, oldname) ||
- !mailbox_list_is_valid_create_name(_storage->list, newname)) {
- mail_storage_set_error(_storage, "Invalid mailbox name");
- return -1;
- }
+ struct maildir_storage *storage = MAILDIR_LIST_CONTEXT(list);
+ const char *path1, *path2;
if (strcmp(oldname, "INBOX") == 0) {
- mail_storage_set_error(_storage,
- "Renaming INBOX isn't supported.");
- return -1;
- }
-
- /* NOTE: it's possible to rename a nonexisting folder which has
- subfolders. In that case we should ignore the rename() error. */
- oldpath = mailbox_list_get_path(_storage->list, oldname,
- MAILBOX_LIST_PATH_TYPE_MAILBOX);
- newpath = mailbox_list_get_path(_storage->list, newname,
- MAILBOX_LIST_PATH_TYPE_MAILBOX);
-
- ret = rename(oldpath, newpath);
- if (ret == 0 || errno == ENOENT) {
- (void)rename_dir(_storage, MAILBOX_LIST_PATH_TYPE_CONTROL,
- oldname, newname);
- (void)rename_dir(_storage, MAILBOX_LIST_PATH_TYPE_INDEX,
- oldname, newname);
-
- found = ret == 0;
- ret = rename_subfolders(_storage, oldname, newname);
- if (ret < 0)
- return -1;
- if (!found && ret == 0) {
- mail_storage_set_error(_storage,
- MAIL_STORAGE_ERR_MAILBOX_NOT_FOUND, oldname);
+ /* INBOX often exists as the root ~/Maildir.
+ We can't rename it then. */
+ path1 = mailbox_list_get_path(list, oldname,
+ MAILBOX_LIST_PATH_TYPE_MAILBOX);
+ path2 = mailbox_list_get_path(list, NULL,
+ MAILBOX_LIST_PATH_TYPE_MAILBOX);
+ if (strcmp(path1, path2) == 0) {
+ mailbox_list_set_error(list,
+ "Renaming INBOX isn't supported.");
return -1;
}
-
- return 0;
}
- if (EDESTDIREXISTS(errno)) {
- mail_storage_set_error(_storage,
- "Target mailbox already exists");
- return -1;
- } else {
- mail_storage_set_critical(_storage, "rename(%s, %s) failed: %m",
- oldpath, newpath);
- return -1;
- }
+ return storage->list_super.rename_mailbox(list, oldname, newname);
}
static int maildir_storage_close(struct mailbox *box)
@@ -922,20 +919,71 @@
}
static int
-maildir_storage_is_mailbox(struct mail_storage *_storage,
- const char *dir, const char *fname,
- enum mailbox_list_iter_flags iter_flags
- __attr_unused__,
- enum mailbox_info_flags *flags,
- enum mailbox_list_file_type type)
+maildir_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx
+ __attr_unused__,
+ const char *dir, const char *fname,
+ enum mailbox_list_file_type type,
+ enum mailbox_info_flags *flags_r)
{
- struct maildir_storage *storage = (struct maildir_storage *)_storage;
+ struct stat st;
+ const char *path;
+ int ret;
+
+ if (maildir_is_internal_name(fname)) {
+ *flags_r = MAILBOX_NONEXISTENT;
+ return 0;
+ }
+
+ switch (type) {
+ case MAILBOX_LIST_FILE_TYPE_FILE:
+ case MAILBOX_LIST_FILE_TYPE_OTHER:
+ /* non-directories are not */
+ *flags_r = MAILBOX_NOSELECT;
+ return 0;
+
+ case MAILBOX_LIST_FILE_TYPE_DIR:
+ case MAILBOX_LIST_FILE_TYPE_UNKNOWN:
+ case MAILBOX_LIST_FILE_TYPE_SYMLINK:
+ break;
+ }
+
+ t_push();
+ path = t_strdup_printf("%s/%s", dir, fname);
+ if (stat(path, &st) == 0) {
+ if (S_ISDIR(st.st_mode))
+ ret = 1;
+ else if (strncmp(fname, ".nfs", 4) == 0) {
+ /* temporary NFS file */
+ *flags_r = MAILBOX_NONEXISTENT;
+ ret = 0;
+ } else {
+ *flags_r = MAILBOX_NOSELECT;
+ ret = 0;
+ }
+ } else if (errno == ENOENT) {
+ /* this was a directory. maybe it has children. */
+ *flags_r = MAILBOX_NOSELECT;
+ ret = 1;
+ } else {
+ *flags_r = MAILBOX_NOSELECT;
+ ret = 0;
+ }
+ t_pop();
+ return ret;
+}
+
+static int
+maildirplusplus_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
+ const char *dir, const char *fname,
+ enum mailbox_list_file_type type,
+ enum mailbox_info_flags *flags_r)
+{
+ struct maildir_storage *storage = MAILDIR_LIST_CONTEXT(ctx->list);
+ struct mail_storage *_storage = &storage->storage.storage;
int ret;
if (fname[1] == mailbox_list_get_hierarchy_sep(_storage->list) &&
- strcmp(fname+2, MAILDIR_UNLINK_DIRNAME) == 0 &&
- strcmp(mailbox_list_get_driver_name(_storage->list),
- MAILDIR_PLUSPLUS_DRIVER_NAME) == 0) {
+ strcmp(fname+2, MAILDIR_UNLINK_DIRNAME) == 0) {
const char *path;
struct stat st;
@@ -950,7 +998,7 @@
(void)unlink_directory(path, TRUE);
t_pop();
- *flags = MAILBOX_NONEXISTENT;
+ *flags_r = MAILBOX_NONEXISTENT;
return 0;
}
@@ -962,7 +1010,7 @@
case MAILBOX_LIST_FILE_TYPE_FILE:
case MAILBOX_LIST_FILE_TYPE_OTHER:
/* non-directories are not */
- *flags = MAILBOX_NOSELECT;
+ *flags_r = MAILBOX_NOSELECT;
return 0;
case MAILBOX_LIST_FILE_TYPE_UNKNOWN:
@@ -979,11 +1027,25 @@
t_push();
path = t_strdup_printf("%s/%s", dir, fname);
- ret = (stat(path, &st) < 0 || !S_ISDIR(st.st_mode)) ? 0 : 1;
+ if (stat(path, &st) == 0) {
+ if (S_ISDIR(st.st_mode))
+ ret = 1;
+ else {
+ if (strncmp(fname, ".nfs", 4) == 0)
+ *flags_r = MAILBOX_NONEXISTENT;
+ else
+ *flags_r = MAILBOX_NOSELECT;
+ ret = 0;
+ }
+ } else if (errno == ENOENT) {
+ /* just deleted? */
+ *flags_r = MAILBOX_NONEXISTENT;
+ ret = 0;
+ } else {
+ *flags_r = MAILBOX_NOSELECT;
+ ret = 0;
+ }
t_pop();
-
- if (ret == 0)
- *flags = MAILBOX_NONEXISTENT;
} else {
ret = 1;
}
@@ -992,6 +1054,7 @@
static void maildir_class_init(void)
{
+ maildir_mailbox_list_module_id = mailbox_list_module_id++;
maildir_transaction_class_init();
}
@@ -1013,9 +1076,6 @@
index_storage_set_callbacks,
maildir_mailbox_open,
maildir_mailbox_create,
- maildir_mailbox_delete,
- maildir_mailbox_rename,
- maildir_storage_is_mailbox,
index_storage_get_last_error
}
};
Index: maildir-storage.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/maildir/maildir-storage.h,v
retrieving revision 1.64
retrieving revision 1.65
diff -u -d -r1.64 -r1.65
--- maildir-storage.h 6 Mar 2007 15:39:04 -0000 1.64
+++ maildir-storage.h 29 Mar 2007 07:59:19 -0000 1.65
@@ -43,6 +43,7 @@
#define MAILDIR_SAVE_FLAG_DELETED 0x20000000
#include "index-storage.h"
+#include "mailbox-list-private.h"
#define STORAGE(maildir_storage) \
(&(maildir_storage)->storage.storage)
@@ -56,6 +57,7 @@
struct maildir_storage {
struct index_storage storage;
+ struct mailbox_list_vfuncs list_super;
const char *temp_prefix;
unsigned int copy_with_hardlinks:1;
- Previous message: [dovecot-cvs] dovecot/src/lib-storage/index/dbox dbox-file.c, 1.13, 1.14 dbox-storage.c, 1.38, 1.39 dbox-storage.h, 1.17, 1.18 dbox-sync-expunge.c, 1.22, 1.23 dbox-sync-full.c, 1.10, 1.11 dbox-uidlist.c, 1.46, 1.47
- Next message: [dovecot-cvs] dovecot/src/lib-storage/index/mbox mbox-storage.c, 1.170, 1.171
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the dovecot-cvs
mailing list