From: Timo Sirainen Date: Sat, 17 May 2003 13:09:54 +0000 (+0300) Subject: Maildir: CONTROL= in MAIL environment now specifies where to save X-Git-Tag: 1.1.alpha1~4627 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=934d42dec29def3fc2b070932f2a7247ec2eea8a;p=thirdparty%2Fdovecot%2Fcore.git Maildir: CONTROL= in MAIL environment now specifies where to save .customflags and dovecot-uidlist files. This can be useful if the main mail directory is under hard quota. --HG-- branch : HEAD --- diff --git a/src/lib-index/mail-custom-flags.c b/src/lib-index/mail-custom-flags.c index e89dbf5e2d..9b2b52328f 100644 --- a/src/lib-index/mail-custom-flags.c +++ b/src/lib-index/mail-custom-flags.c @@ -238,7 +238,7 @@ int mail_custom_flags_open_or_create(struct mail_index *index) const char *path; int fd; - path = t_strconcat(index->custom_flags_dir, "/", + path = t_strconcat(index->control_dir, "/", CUSTOM_FLAGS_FILE_NAME, NULL); if (path == NULL) fd = -1; diff --git a/src/lib-index/mail-index.c b/src/lib-index/mail-index.c index 32430fd72e..60059e6730 100644 --- a/src/lib-index/mail-index.c +++ b/src/lib-index/mail-index.c @@ -170,9 +170,9 @@ void mail_index_close(struct mail_index *index) index->custom_flags = NULL; } - if (index->custom_flags_dir != NULL) { - i_free(index->custom_flags_dir); - index->custom_flags_dir = NULL; + if (index->control_dir != NULL) { + i_free(index->control_dir); + index->control_dir = NULL; } if (index->error != NULL) { diff --git a/src/lib-index/mail-index.h b/src/lib-index/mail-index.h index 21cb3b7df0..21ef3efc43 100644 --- a/src/lib-index/mail-index.h +++ b/src/lib-index/mail-index.h @@ -370,7 +370,7 @@ struct mail_index { char *dir; /* directory where to place the index files */ char *filepath; /* index file path */ char *mailbox_path; /* file/directory for mailbox location */ - char *custom_flags_dir; /* destination for .customflags file */ + char *control_dir; /* destination for control files */ enum mail_data_field default_cache_fields, never_cache_fields; unsigned int indexid; unsigned int sync_id; diff --git a/src/lib-index/maildir/maildir-index.c b/src/lib-index/maildir/maildir-index.c index 876062959f..cf39f3e708 100644 --- a/src/lib-index/maildir/maildir-index.c +++ b/src/lib-index/maildir/maildir-index.c @@ -205,7 +205,9 @@ const char *maildir_filename_set_flags(const char *fname, enum mail_flags flags) return str_c(flags_str); } -struct mail_index *maildir_index_alloc(const char *dir, const char *maildir) +struct mail_index * +maildir_index_alloc(const char *maildir, const char *index_dir, + const char *control_dir) { struct mail_index *index; @@ -216,7 +218,8 @@ struct mail_index *maildir_index_alloc(const char *dir, const char *maildir) index->maildir_lock_fd = -1; index->mailbox_path = i_strdup(maildir); - mail_index_init(index, dir); + index->control_dir = i_strdup(control_dir); + mail_index_init(index, index_dir); return index; } diff --git a/src/lib-index/maildir/maildir-index.h b/src/lib-index/maildir/maildir-index.h index a5b02da499..cce7b7127f 100644 --- a/src/lib-index/maildir/maildir-index.h +++ b/src/lib-index/maildir/maildir-index.h @@ -8,7 +8,9 @@ /* ":2,DFRST" - leave the 2 extra for other clients' additions */ #define MAILDIR_LOCATION_EXTRA_SPACE 10 -struct mail_index *maildir_index_alloc(const char *dir, const char *maildir); +struct mail_index * +maildir_index_alloc(const char *maildir, const char *index_dir, + const char *control_dir); /* Return new filename base to save into tmp/ */ const char *maildir_generate_tmp_filename(const struct timeval *tv); diff --git a/src/lib-index/maildir/maildir-uidlist.c b/src/lib-index/maildir/maildir-uidlist.c index 2bb8547a9a..29a66db512 100644 --- a/src/lib-index/maildir/maildir-uidlist.c +++ b/src/lib-index/maildir/maildir-uidlist.c @@ -25,7 +25,7 @@ int maildir_uidlist_try_lock(struct mail_index *index) i_assert(!INDEX_IS_UIDLIST_LOCKED(index)); - path = t_strconcat(index->mailbox_path, + path = t_strconcat(index->control_dir, "/" MAILDIR_UIDLIST_NAME ".lock", NULL); for (i = 0; i < 2; i++) { fd = open(path, O_WRONLY | O_CREAT | O_EXCL, 0644); @@ -70,7 +70,7 @@ void maildir_uidlist_unlock(struct mail_index *index) if (!INDEX_IS_UIDLIST_LOCKED(index)) return; - path = t_strconcat(index->mailbox_path, + path = t_strconcat(index->control_dir, "/" MAILDIR_UIDLIST_NAME ".lock", NULL); if (unlink(path) < 0 && errno != ENOENT) index_file_set_syscall_error(index, path, "unlink()"); @@ -87,7 +87,7 @@ struct maildir_uidlist *maildir_uidlist_open(struct mail_index *index) unsigned int version; int fd; - path = t_strconcat(index->mailbox_path, "/" MAILDIR_UIDLIST_NAME, NULL); + path = t_strconcat(index->control_dir, "/" MAILDIR_UIDLIST_NAME, NULL); fd = open(path, O_RDONLY); if (fd == -1) { if (errno != ENOENT) @@ -243,7 +243,7 @@ int maildir_uidlist_rewrite(struct mail_index *index, time_t *mtime) return FALSE; } - temp_path = t_strconcat(index->mailbox_path, + temp_path = t_strconcat(index->control_dir, "/" MAILDIR_UIDLIST_NAME ".lock", NULL); failed = !maildir_uidlist_rewrite_fd(index, temp_path, mtime); @@ -254,7 +254,7 @@ int maildir_uidlist_rewrite(struct mail_index *index, time_t *mtime) index->maildir_lock_fd = -1; if (!failed) { - db_path = t_strconcat(index->mailbox_path, + db_path = t_strconcat(index->control_dir, "/" MAILDIR_UIDLIST_NAME, NULL); if (rename(temp_path, db_path) < 0) { diff --git a/src/lib-index/mbox/mbox-index.c b/src/lib-index/mbox/mbox-index.c index 0184a68eee..e6b8b8f0b8 100644 --- a/src/lib-index/mbox/mbox-index.c +++ b/src/lib-index/mbox/mbox-index.c @@ -744,7 +744,9 @@ int mbox_mail_get_location(struct mail_index *index, return TRUE; } -struct mail_index *mbox_index_alloc(const char *dir, const char *mbox_path) +struct mail_index * +mbox_index_alloc(const char *mbox_path, const char *index_dir, + const char *control_dir) { struct mail_index *index; @@ -758,7 +760,8 @@ struct mail_index *mbox_index_alloc(const char *dir, const char *mbox_path) index->mailbox_readonly = access(mbox_path, W_OK) < 0; index->mailbox_path = i_strdup(mbox_path); - mail_index_init(index, dir); + index->control_dir = i_strdup(control_dir); + mail_index_init(index, index_dir); return index; } diff --git a/src/lib-index/mbox/mbox-index.h b/src/lib-index/mbox/mbox-index.h index 8be223dc33..4d9b44bc85 100644 --- a/src/lib-index/mbox/mbox-index.h +++ b/src/lib-index/mbox/mbox-index.h @@ -52,7 +52,9 @@ int mbox_mail_get_location(struct mail_index *index, struct mail_index_record *rec, uoff_t *offset, uoff_t *hdr_size, uoff_t *body_size); -struct mail_index *mbox_index_alloc(const char *dir, const char *mbox_path); +struct mail_index * +mbox_index_alloc(const char *mbox_path, const char *index_dir, + const char *control_dir); int mbox_index_rebuild(struct mail_index *index); int mbox_index_sync(struct mail_index *index, enum mail_lock_type lock_type, int *changes); diff --git a/src/lib-storage/index/maildir/maildir-storage.c b/src/lib-storage/index/maildir/maildir-storage.c index 8d1ab894ba..957ced5d99 100644 --- a/src/lib-storage/index/maildir/maildir-storage.c +++ b/src/lib-storage/index/maildir/maildir-storage.c @@ -28,9 +28,9 @@ static const char *maildirs[] = { "cur", "new", "tmp", NULL }; static struct mail_storage *maildir_create(const char *data, const char *user) { struct mail_storage *storage; - const char *home, *path, *root_dir, *index_dir, *p; + const char *home, *path, *root_dir, *index_dir, *control_dir, *p; - root_dir = index_dir = NULL; + root_dir = index_dir = control_dir = NULL; if (data == NULL || *data == '\0') { /* we'll need to figure out the maildir location ourself. @@ -47,16 +47,21 @@ static struct mail_storage *maildir_create(const char *data, const char *user) } } } else { - /* [:INDEX=] */ + /* [:INDEX=] [:CONTROL=] */ p = strchr(data, ':'); if (p == NULL) root_dir = data; else { root_dir = t_strdup_until(data, p); - p++; - if (strncmp(p, "INDEX=", 6) == 0) - index_dir = t_strcut(p+6, ':'); + do { + p++; + if (strncmp(p, "INDEX=", 6) == 0) + index_dir = t_strcut(p+6, ':'); + else if (strncmp(p, "CONTROL=", 8) == 0) + control_dir = t_strcut(p+8, ':'); + p = strchr(p, ':'); + } while (p != NULL); } } @@ -73,6 +78,7 @@ static struct mail_storage *maildir_create(const char *data, const char *user) storage->dir = i_strdup(root_dir); storage->index_dir = i_strdup(index_dir); + storage->control_dir = i_strdup(control_dir); storage->user = i_strdup(user); storage->callbacks = i_new(struct mail_storage_callbacks, 1); return storage; @@ -82,6 +88,7 @@ static void maildir_free(struct mail_storage *storage) { i_free(storage->dir); i_free(storage->index_dir); + i_free(storage->control_dir); i_free(storage->user); i_free(storage->error); i_free(storage->callbacks); @@ -160,20 +167,43 @@ static const char *maildir_get_index_path(struct mail_storage *storage, return t_strconcat(storage->index_dir, "/.", name, NULL); } +static const char *maildir_get_control_path(struct mail_storage *storage, + const char *name) +{ + if (storage->control_dir == NULL) + return maildir_get_path(storage, name); + + if (full_filesystem_access && (*name == '/' || *name == '~')) + return maildir_get_absolute_path(name); + + return t_strconcat(storage->control_dir, "/.", name, NULL); +} + /* create or fix maildir, ignore if it already exists */ -static int create_maildir(const char *dir, int verify) +static int create_maildir(struct mail_storage *storage, + const char *dir, int verify) { const char **tmp, *path; - if (mkdir(dir, CREATE_MODE) == -1 && (errno != EEXIST || !verify)) + if (mkdir(dir, CREATE_MODE) < 0 && (errno != EEXIST || !verify)) { + if (errno != EEXIST) { + mail_storage_set_critical(storage, + "mkdir(%s) failed: %m", dir); + } return FALSE; + } for (tmp = maildirs; *tmp != NULL; tmp++) { path = t_strconcat(dir, "/", *tmp, NULL); - if (mkdir(path, CREATE_MODE) == -1 && - (errno != EEXIST || !verify)) + if (mkdir(path, CREATE_MODE) < 0 && + (errno != EEXIST || !verify)) { + if (errno != EEXIST) { + mail_storage_set_critical(storage, + "mkdir(%s) failed: %m", dir); + } return FALSE; + } } return TRUE; @@ -191,8 +221,23 @@ static int create_index_dir(struct mail_storage *storage, const char *name) dir = t_strconcat(storage->index_dir, "/.", name, NULL); if (mkdir(dir, CREATE_MODE) == -1 && errno != EEXIST) { - mail_storage_set_critical(storage, - "Can't create directory %s: %m", dir); + mail_storage_set_critical(storage, "mkdir(%s) failed: %m", dir); + return FALSE; + } + + return TRUE; +} + +static int create_control_dir(struct mail_storage *storage, const char *name) +{ + const char *dir; + + if (storage->control_dir == NULL) + return TRUE; + + dir = t_strconcat(storage->control_dir, "/.", name, NULL); + if (mkdir(dir, CREATE_MODE) < 0 && errno != EEXIST) { + mail_storage_set_critical(storage, "mkdir(%s) failed: %m", dir); return FALSE; } @@ -204,18 +249,20 @@ static int verify_inbox(struct mail_storage *storage) const char *inbox; /* first make sure the cur/ new/ and tmp/ dirs exist in root dir */ - (void)create_maildir(storage->dir, TRUE); + if (!create_maildir(storage, storage->dir, TRUE)) + return FALSE; /* create the .INBOX directory */ inbox = t_strconcat(storage->dir, "/.INBOX", NULL); - if (mkdir(inbox, CREATE_MODE) == -1 && errno != EEXIST) { - mail_storage_set_critical(storage, "Can't create directory " - "%s: %m", inbox); + if (mkdir(inbox, CREATE_MODE) < 0 && errno != EEXIST) { + mail_storage_set_critical(storage, "mkdir(%s) failed: %m", + inbox); return FALSE; } /* make sure the index directories exist */ - return create_index_dir(storage, "INBOX"); + return create_index_dir(storage, "INBOX") && + create_control_dir(storage, "INBOX"); } static struct mailbox * @@ -224,15 +271,15 @@ maildir_open(struct mail_storage *storage, const char *name, { struct index_mailbox *ibox; struct mail_index *index; - const char *path, *index_dir; + const char *path, *index_dir, *control_dir; path = maildir_get_path(storage, name); index_dir = maildir_get_index_path(storage, name); + control_dir = maildir_get_control_path(storage, name); index = index_storage_lookup_ref(index_dir); if (index == NULL) { - index = maildir_index_alloc(index_dir, path); - index->custom_flags_dir = i_strdup(path); + index = maildir_index_alloc(path, index_dir, control_dir); index_storage_add(index); } @@ -280,10 +327,10 @@ maildir_open_mailbox(struct mail_storage *storage, path = maildir_get_path(storage, name); if (stat(path, &st) == 0) { /* exists - make sure the required directories are also there */ - (void)create_maildir(path, TRUE); - - /* make sure the index directories exist */ - (void)create_index_dir(storage, name); + if (!create_maildir(storage, path, TRUE) || + !create_index_dir(storage, name) || + !create_control_dir(storage, name)) + return FALSE; return maildir_open(storage, name, readonly, fast); } else if (errno == ENOENT) { @@ -291,8 +338,7 @@ maildir_open_mailbox(struct mail_storage *storage, name); return NULL; } else { - mail_storage_set_critical(storage, "Can't open mailbox %s: %m", - name); + mail_storage_set_critical(storage, "stat(%s) failed: %m", path); return NULL; } } @@ -316,16 +362,15 @@ static int maildir_create_mailbox(struct mail_storage *storage, } path = maildir_get_path(storage, name); - if (create_maildir(path, FALSE)) - return TRUE; - else if (errno == EEXIST) { - mail_storage_set_error(storage, "Mailbox already exists"); - return FALSE; - } else { - mail_storage_set_critical(storage, "Can't create mailbox " - "%s: %m", name); + if (!create_maildir(storage, path, FALSE)) { + if (errno == EEXIST) { + mail_storage_set_error(storage, + "Mailbox already exists"); + } return FALSE; } + + return TRUE; } static int maildir_delete_mailbox(struct mail_storage *storage, @@ -458,7 +503,8 @@ static int rename_subfolders(struct mail_storage *storage, errno == EEXIST || errno == ENOTEMPTY) ret = 1; else { - mail_storage_set_critical(storage, "rename(%s, %s) failed: %m", + mail_storage_set_critical(storage, + "rename(%s, %s) failed: %m", oldpath, newpath); ret = -1; t_pop(); @@ -502,8 +548,7 @@ static int maildir_rename_mailbox(struct mail_storage *storage, ret = rename(oldpath, newpath); if (ret == 0 || errno == ENOENT) { - if (!rename_indexes(storage, oldname, newname)) - return FALSE; + (void)rename_indexes(storage, oldname, newname); found = ret == 0; ret = rename_subfolders(storage, oldname, newname); @@ -559,8 +604,7 @@ static int maildir_get_mailbox_name_status(struct mail_storage *storage, *status = MAILBOX_NAME_VALID; return TRUE; } else { - mail_storage_set_critical(storage, "mailbox name status: " - "stat(%s) failed: %m", path); + mail_storage_set_critical(storage, "stat(%s) failed: %m", path); return FALSE; } } @@ -609,7 +653,7 @@ struct mail_storage maildir_storage = { NULL, NULL, NULL, - NULL, NULL, + NULL, NULL, NULL, 0 }; diff --git a/src/lib-storage/index/mbox/mbox-storage.c b/src/lib-storage/index/mbox/mbox-storage.c index c5939a7d91..81cd577de0 100644 --- a/src/lib-storage/index/mbox/mbox-storage.c +++ b/src/lib-storage/index/mbox/mbox-storage.c @@ -358,8 +358,7 @@ static struct mailbox *mbox_open(struct mail_storage *storage, const char *name, index = index_storage_lookup_ref(index_dir); if (index == NULL) { - index = mbox_index_alloc(index_dir, path); - index->custom_flags_dir = i_strdup(index_dir); + index = mbox_index_alloc(path, index_dir, index_dir); index_storage_add(index); } @@ -724,7 +723,7 @@ struct mail_storage mbox_storage = { NULL, NULL, NULL, - NULL, NULL, + NULL, NULL, NULL, 0 }; diff --git a/src/lib-storage/mail-storage.h b/src/lib-storage/mail-storage.h index e82596e2a7..b816d53987 100644 --- a/src/lib-storage/mail-storage.h +++ b/src/lib-storage/mail-storage.h @@ -201,6 +201,7 @@ struct mail_storage { char *dir; /* root directory */ char *inbox_file; /* INBOX file for mbox */ char *index_dir; + char *control_dir; char *user; /* name of user accessing the storage */ char *error;