Mercurial > dovecot > core-2.2
changeset 9533:530bbade4e3f HEAD
Added support for creating/updating mailboxes with given metadata (guid, uid validity, etc).
line wrap: on
line diff
--- a/src/imap/cmd-create.c Thu Jun 25 14:33:37 2009 -0400 +++ b/src/imap/cmd-create.c Fri Jun 26 16:11:59 2009 -0400 @@ -7,8 +7,8 @@ bool cmd_create(struct client_command_context *cmd) { struct mail_namespace *ns; - struct mail_storage *storage; const char *mailbox, *full_mailbox; + struct mailbox *box; bool directory; size_t len; @@ -40,10 +40,11 @@ CLIENT_VERIFY_MAILBOX_SHOULD_NOT_EXIST)) return TRUE; - storage = mail_namespace_get_default_storage(ns); - if (mail_storage_mailbox_create(storage, ns, mailbox, directory) < 0) - client_send_storage_error(cmd, storage); + box = mailbox_alloc(ns->list, mailbox, NULL, 0); + if (mailbox_create(box, NULL, directory) < 0) + client_send_storage_error(cmd, mailbox_get_storage(box)); else client_send_tagline(cmd, "OK Create completed."); + mailbox_close(&box); return TRUE; }
--- a/src/lib-lda/mail-deliver.c Thu Jun 25 14:33:37 2009 -0400 +++ b/src/lib-lda/mail-deliver.c Fri Jun 26 16:11:59 2009 -0400 @@ -107,13 +107,15 @@ storage = mailbox_get_storage(box); *error_r = mail_storage_get_last_error(storage, &error); - mailbox_close(&box); - if (!ctx->set->lda_mailbox_autocreate || error != MAIL_ERROR_NOTFOUND) + if (!ctx->set->lda_mailbox_autocreate || error != MAIL_ERROR_NOTFOUND) { + mailbox_close(&box); return NULL; + } /* try creating it. */ - if (mail_storage_mailbox_create(storage, ns, name, FALSE) < 0) { + if (mailbox_create(box, NULL, FALSE) < 0) { *error_r = mail_storage_get_last_error(storage, &error); + mailbox_close(&box); return NULL; } if (ctx->set->lda_mailbox_autosubscribe) { @@ -122,8 +124,6 @@ } /* and try opening again */ - box = mailbox_alloc(ns->list, name, NULL, flags); - storage = mailbox_get_storage(box); if (mailbox_open(box) < 0 || mailbox_sync(box, 0, 0, NULL) < 0) { *error_r = mail_storage_get_last_error(storage, &error);
--- a/src/lib-storage/index/cydir/cydir-storage.c Thu Jun 25 14:33:37 2009 -0400 +++ b/src/lib-storage/index/cydir/cydir-storage.c Fri Jun 26 16:11:59 2009 -0400 @@ -128,21 +128,46 @@ } static int -cydir_mailbox_create(struct mail_storage *storage, struct mailbox_list *list, - const char *name, bool directory ATTR_UNUSED) +cydir_mailbox_update(struct mailbox *box, const struct mailbox_update *update) +{ + struct cydir_mailbox *mbox = (struct cydir_mailbox *)box; + struct mail_index_transaction *trans; + + trans = mail_index_transaction_begin(mbox->ibox.view, 0); + if (update->uid_validity != 0) { + mail_index_update_header(trans, + offsetof(struct mail_index_header, uid_validity), + &update->uid_validity, sizeof(update->uid_validity), + TRUE); + } + /* FIXME: update next_uid, highestmodseq. guid is also missing.. */ + if (mail_index_transaction_commit(&trans) < 0) { + mail_storage_set_internal_error(box->storage); + return -1; + } + return 0; +} + +static int +cydir_mailbox_create(struct mailbox *box, const struct mailbox_update *update, + bool directory) { const char *path; struct stat st; - path = mailbox_list_get_path(list, name, + path = mailbox_list_get_path(box->list, box->name, MAILBOX_LIST_PATH_TYPE_MAILBOX); if (stat(path, &st) == 0) { - mail_storage_set_error(storage, MAIL_ERROR_EXISTS, + mail_storage_set_error(box->storage, MAIL_ERROR_EXISTS, "Mailbox already exists"); return -1; } - return create_cydir(storage, list, path); + if (create_cydir(box->storage, box->list, path) < 0) + return -1; + + return directory || update == NULL ? 0 : + cydir_mailbox_update(box, update); } static int @@ -345,7 +370,6 @@ cydir_storage_get_list_settings, NULL, cydir_mailbox_alloc, - cydir_mailbox_create, NULL } }; @@ -361,6 +385,8 @@ index_storage_mailbox_enable, cydir_mailbox_open, index_storage_mailbox_close, + cydir_mailbox_create, + cydir_mailbox_update, index_storage_get_status, NULL, NULL,
--- a/src/lib-storage/index/dbox/dbox-save.c Thu Jun 25 14:33:37 2009 -0400 +++ b/src/lib-storage/index/dbox/dbox-save.c Fri Jun 26 16:11:59 2009 -0400 @@ -368,7 +368,7 @@ unsigned int i, count; uint32_t next_map_uid = first_map_uid; - dbox_update_header(ctx->mbox, ctx->trans); + dbox_update_header(ctx->mbox, ctx->trans, NULL); memset(&rec, 0, sizeof(rec)); rec.save_date = ioloop_time;
--- a/src/lib-storage/index/dbox/dbox-storage-rebuild.c Thu Jun 25 14:33:37 2009 -0400 +++ b/src/lib-storage/index/dbox/dbox-storage-rebuild.c Fri Jun 26 16:11:59 2009 -0400 @@ -543,17 +543,20 @@ break; (void)mail_storage_get_last_error(box->storage, &error); + if (error == MAIL_ERROR_NOTFOUND && !created) { + /* mailbox doesn't exist currently? see if creating + it helps. */ + created = TRUE; + (void)mailbox_create(box, NULL, FALSE); + mailbox_close(&box); + continue; + } + mailbox_close(&box); if (error == MAIL_ERROR_TEMP) return -1; - if (error == MAIL_ERROR_NOTFOUND && !created) { - /* mailbox doesn't exist currently? see if creating - it helps. */ - created = TRUE; - (void)mail_storage_mailbox_create(storage, - ctx->default_list->ns, mailbox, FALSE); - } else if (strcmp(mailbox, "INBOX") != 0) { + if (strcmp(mailbox, "INBOX") != 0) { /* see if we can save to INBOX instead. */ mailbox = "INBOX"; } else {
--- a/src/lib-storage/index/dbox/dbox-storage.c Thu Jun 25 14:33:37 2009 -0400 +++ b/src/lib-storage/index/dbox/dbox-storage.c Fri Jun 26 16:11:59 2009 -0400 @@ -191,24 +191,6 @@ return mailbox_uidvalidity_next(path); } -static bool -dbox_index_header_has_mailbox_guid(const struct dbox_index_header *hdr) -{ - unsigned int i; - - for (i = 0; i < sizeof(hdr->mailbox_guid); i++) { - if (hdr->mailbox_guid[i] != 0) - return TRUE; - } - return FALSE; -} - -void dbox_set_mailbox_guid(struct dbox_index_header *hdr) -{ - if (!dbox_index_header_has_mailbox_guid(hdr)) - mail_generate_guid_128(hdr->mailbox_guid); -} - int dbox_read_header(struct dbox_mailbox *mbox, struct dbox_index_header *hdr) { const void *data; @@ -229,7 +211,8 @@ } void dbox_update_header(struct dbox_mailbox *mbox, - struct mail_index_transaction *trans) + struct mail_index_transaction *trans, + const struct mailbox_update *update) { struct dbox_index_header hdr, new_hdr; @@ -237,7 +220,14 @@ memset(&hdr, 0, sizeof(hdr)); new_hdr = hdr; - dbox_set_mailbox_guid(&new_hdr); + + if (update != NULL && !mailbox_guid_is_empty(update->mailbox_guid)) { + memcpy(new_hdr.mailbox_guid, update->mailbox_guid, + sizeof(new_hdr.mailbox_guid)); + } else if (!mailbox_guid_is_empty(new_hdr.mailbox_guid)) { + mail_generate_guid_128(new_hdr.mailbox_guid); + } + new_hdr.map_uid_validity = dbox_map_get_uid_validity(mbox->storage->map); if (memcmp(&hdr, &new_hdr, sizeof(hdr)) != 0) { @@ -246,23 +236,39 @@ } } -static int dbox_write_index_header(struct mailbox *box) +static int dbox_write_index_header(struct mailbox *box, + const struct mailbox_update *update) { struct dbox_mailbox *mbox = (struct dbox_mailbox *)box; struct mail_index_transaction *trans; - uint32_t uid_validity; + const struct mail_index_header *hdr; + uint32_t uid_validity, uid_next; if (dbox_map_open(mbox->storage->map, TRUE) < 0) return -1; + hdr = mail_index_get_header(mbox->ibox.view); trans = mail_index_transaction_begin(mbox->ibox.view, 0); - dbox_update_header(mbox, trans); + dbox_update_header(mbox, trans, update); + + if (update != NULL && update->uid_validity != 0) + uid_validity = update->uid_validity; + else if (hdr->uid_validity == 0) { + /* set uidvalidity */ + uid_validity = dbox_get_uidvalidity_next(box->list); + } - /* set uidvalidity */ - uid_validity = dbox_get_uidvalidity_next(box->list); - mail_index_update_header(trans, - offsetof(struct mail_index_header, uid_validity), - &uid_validity, sizeof(uid_validity), TRUE); + if (hdr->uid_validity != uid_validity) { + mail_index_update_header(trans, + offsetof(struct mail_index_header, uid_validity), + &uid_validity, sizeof(uid_validity), TRUE); + } + if (update != NULL && hdr->next_uid < update->min_next_uid) { + uid_next = update->min_next_uid; + mail_index_update_header(trans, + offsetof(struct mail_index_header, next_uid), + &uid_next, sizeof(uid_next), TRUE); + } if (mail_index_transaction_commit(&trans) < 0) { mail_storage_set_internal_error(box->storage); @@ -272,7 +278,8 @@ return 0; } -static int create_dbox(struct mailbox *box) +static int dbox_mailbox_create_indexes(struct mailbox *box, + const struct mailbox_update *update) { struct dbox_mailbox *mbox = (struct dbox_mailbox *)box; mode_t mode; @@ -285,7 +292,7 @@ if (index_storage_mailbox_open(box) < 0) return -1; mbox->creating = TRUE; - ret = dbox_write_index_header(box); + ret = dbox_write_index_header(box, update); mbox->creating = FALSE; if (ret < 0) return -1; @@ -336,7 +343,7 @@ if (strcmp(box->name, "INBOX") == 0 && (box->list->ns->flags & NAMESPACE_FLAG_INBOX) != 0) { /* INBOX always exists, create it */ - if (create_dbox(box) < 0) + if (dbox_mailbox_create_indexes(box, NULL) < 0) return -1; return box->opened ? 0 : index_storage_mailbox_open(box); @@ -373,9 +380,9 @@ if (dbox_read_header(mbox, &hdr) < 0) memset(&hdr, 0, sizeof(hdr)); - if (!dbox_index_header_has_mailbox_guid(&hdr)) { + if (!mailbox_guid_is_empty(hdr.mailbox_guid)) { /* regenerate it */ - if (dbox_write_index_header(box) < 0 || + if (dbox_write_index_header(box, NULL) < 0 || dbox_read_header(mbox, &hdr) < 0) return; } @@ -394,19 +401,17 @@ } static int -dbox_mailbox_create(struct mail_storage *storage, struct mailbox_list *list, - const char *name, bool directory) +dbox_mailbox_create(struct mailbox *box, const struct mailbox_update *update, + bool directory) { const char *path, *alt_path; - struct mailbox *box; struct stat st; - int ret; - path = mailbox_list_get_path(list, name, + path = mailbox_list_get_path(box->list, box->name, directory ? MAILBOX_LIST_PATH_TYPE_DIR : MAILBOX_LIST_PATH_TYPE_MAILBOX); if (stat(path, &st) == 0) { - mail_storage_set_error(storage, MAIL_ERROR_EXISTS, + mail_storage_set_error(box->storage, MAIL_ERROR_EXISTS, "Mailbox already exists"); return -1; } @@ -415,14 +420,14 @@ mode_t mode; gid_t gid; - mailbox_list_get_dir_permissions(list, NULL, &mode, &gid); + mailbox_list_get_dir_permissions(box->list, NULL, &mode, &gid); if (mkdir_parents_chown(path, mode, (uid_t)-1, gid) == 0) return 0; else if (errno == EEXIST) { - mail_storage_set_error(storage, MAIL_ERROR_EXISTS, + mail_storage_set_error(box->storage, MAIL_ERROR_EXISTS, "Mailbox already exists"); - } else if (!mail_storage_set_error_from_errno(storage)) { - mail_storage_set_critical(storage, + } else if (!mail_storage_set_error_from_errno(box->storage)) { + mail_storage_set_critical(box->storage, "mkdir(%s) failed: %m", path); } return -1; @@ -432,18 +437,24 @@ race conditions with RENAME/DELETE), but if something crashed and left it lying around we don't want to start overwriting files in it. */ - alt_path = dbox_get_alt_path(list, path); + alt_path = dbox_get_alt_path(box->list, path); if (alt_path != NULL && stat(alt_path, &st) == 0) { - mail_storage_set_error(storage, MAIL_ERROR_EXISTS, + mail_storage_set_error(box->storage, MAIL_ERROR_EXISTS, "Mailbox already exists"); return -1; } - box = dbox_mailbox_alloc(storage, list, name, NULL, - MAILBOX_FLAG_KEEP_RECENT); - ret = create_dbox(box); - mailbox_close(&box); - return ret; + return dbox_mailbox_create_indexes(box, update); +} + +static int +dbox_mailbox_update(struct mailbox *box, const struct mailbox_update *update) +{ + if (!box->opened) { + if (index_storage_mailbox_open(box) < 0) + return -1; + } + return dbox_write_index_header(box, update); } static int @@ -848,7 +859,6 @@ dbox_storage_get_list_settings, NULL, dbox_mailbox_alloc, - dbox_mailbox_create, dbox_sync_purge } }; @@ -864,6 +874,8 @@ index_storage_mailbox_enable, dbox_mailbox_open, dbox_mailbox_close, + dbox_mailbox_create, + dbox_mailbox_update, dbox_storage_get_status, NULL, NULL,
--- a/src/lib-storage/index/dbox/dbox-storage.h Thu Jun 25 14:33:37 2009 -0400 +++ b/src/lib-storage/index/dbox/dbox-storage.h Fri Jun 26 16:11:59 2009 -0400 @@ -108,10 +108,10 @@ int dbox_mail_lookup(struct dbox_mailbox *mbox, struct mail_index_view *view, uint32_t seq, uint32_t *map_uid_r); uint32_t dbox_get_uidvalidity_next(struct mailbox_list *list); -void dbox_set_mailbox_guid(struct dbox_index_header *hdr); int dbox_read_header(struct dbox_mailbox *mbox, struct dbox_index_header *hdr); void dbox_update_header(struct dbox_mailbox *mbox, - struct mail_index_transaction *trans); + struct mail_index_transaction *trans, + const struct mailbox_update *update); struct mail_save_context * dbox_save_alloc(struct mailbox_transaction_context *_t);
--- a/src/lib-storage/index/dbox/dbox-sync-rebuild.c Thu Jun 25 14:33:37 2009 -0400 +++ b/src/lib-storage/index/dbox/dbox-sync-rebuild.c Fri Jun 26 16:11:59 2009 -0400 @@ -352,7 +352,8 @@ if (dbox_read_header(ctx->mbox, &hdr) < 0) memset(&hdr, 0, sizeof(hdr)); - dbox_set_mailbox_guid(&hdr); + if (!mailbox_guid_is_empty(hdr.mailbox_guid)) + mail_generate_guid_128(hdr.mailbox_guid); if (hdr.highest_maildir_uid < ctx->mbox->highest_maildir_uid) hdr.highest_maildir_uid = ctx->mbox->highest_maildir_uid; hdr.map_uid_validity = !ctx->storage_rebuild ? 0 :
--- a/src/lib-storage/index/index-storage.c Thu Jun 25 14:33:37 2009 -0400 +++ b/src/lib-storage/index/index-storage.c Fri Jun 26 16:11:59 2009 -0400 @@ -377,23 +377,10 @@ enum mail_index_open_flags index_flags; const char *index_dir; struct stat st; - gid_t dir_gid; int ret; i_assert(!box->opened); - if (box->file_create_mode == 0) { - mailbox_list_get_permissions(box->list, box->name, - &box->file_create_mode, - &box->file_create_gid); - mailbox_list_get_dir_permissions(box->list, box->name, - &box->dir_create_mode, - &dir_gid); - mail_index_set_permissions(ibox->index, - box->file_create_mode, - box->file_create_gid); - } - index_flags = mail_storage_settings_to_index_flags(box->storage->set); if (!ibox->move_to_memory) index_flags |= MAIL_INDEX_OPEN_FLAG_CREATE; @@ -461,6 +448,7 @@ { struct mailbox *box = &ibox->box; const char *path; + gid_t dir_gid; if (name != NULL) box->name = p_strdup(box->pool, name); @@ -492,6 +480,18 @@ ibox->index = index_storage_alloc(box->list, name, flags, index_prefix); ibox->md5hdr_ext_idx = mail_index_ext_register(ibox->index, "header-md5", 0, 16, 1); + + if (box->file_create_mode == 0) { + mailbox_list_get_permissions(box->list, name, + &box->file_create_mode, + &box->file_create_gid); + mailbox_list_get_dir_permissions(box->list, name, + &box->dir_create_mode, + &dir_gid); + mail_index_set_permissions(ibox->index, + box->file_create_mode, + box->file_create_gid); + } } int index_storage_mailbox_enable(struct mailbox *box,
--- a/src/lib-storage/index/maildir/maildir-storage.c Thu Jun 25 14:33:37 2009 -0400 +++ b/src/lib-storage/index/maildir/maildir-storage.c Fri Jun 26 16:11:59 2009 -0400 @@ -475,30 +475,55 @@ } static int -maildir_mailbox_create(struct mail_storage *storage, struct mailbox_list *list, - const char *name, bool directory ATTR_UNUSED) +maildir_mailbox_update(struct mailbox *box, const struct mailbox_update *update) +{ + struct maildir_mailbox *mbox = (struct maildir_mailbox *)box; + struct maildir_uidlist *uidlist = mbox->uidlist; + int ret; + + if (maildir_uidlist_lock(uidlist) <= 0) + return -1; + + if (!mailbox_guid_is_empty(update->mailbox_guid)) + maildir_uidlist_set_mailbox_guid(uidlist, update->mailbox_guid); + if (update->uid_validity != 0) + maildir_uidlist_set_uid_validity(uidlist, update->uid_validity); + if (update->min_next_uid != 0) { + maildir_uidlist_set_next_uid(uidlist, update->min_next_uid, + FALSE); + } + /* FIXME: update highestmodseq */ + + ret = maildir_uidlist_update(uidlist); + maildir_uidlist_unlock(uidlist); + return ret; +} + +static int +maildir_mailbox_create(struct mailbox *box, const struct mailbox_update *update, + bool directory) { struct stat st; const char *path, *root_dir, *shared_path; mode_t old_mask; int fd; - path = mailbox_list_get_path(list, name, + path = mailbox_list_get_path(box->list, box->name, MAILBOX_LIST_PATH_TYPE_MAILBOX); - root_dir = mailbox_list_get_path(list, NULL, + root_dir = mailbox_list_get_path(box->list, NULL, MAILBOX_LIST_PATH_TYPE_MAILBOX); /* if dovecot-shared exists in the root dir, create the mailbox using its permissions and gid, and copy the dovecot-shared inside it. */ shared_path = t_strconcat(root_dir, "/dovecot-shared", NULL); if (stat(shared_path, &st) == 0) { - if (maildir_create_shared(storage, list->ns, path, + if (maildir_create_shared(box->storage, box->list->ns, path, st.st_mode & 0666, st.st_gid) < 0) return -1; } else { - mailbox_list_get_dir_permissions(list, NULL, + mailbox_list_get_dir_permissions(box->list, NULL, &st.st_mode, &st.st_gid); - if (create_maildir(storage, list->ns, path, + if (create_maildir(box->storage, box->list->ns, path, st.st_mode, st.st_gid, FALSE) < 0) return -1; } @@ -513,19 +538,20 @@ /* if dovecot-shared exists, use the same group */ if (st.st_gid != (gid_t)-1 && fchown(fd, (uid_t)-1, st.st_gid) < 0) { - mail_storage_set_critical(storage, + mail_storage_set_critical(box->storage, "fchown(%s) failed: %m", path); } (void)close(fd); } else if (errno == ENOENT) { - mail_storage_set_error(storage, MAIL_ERROR_NOTFOUND, + mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND, "Mailbox was deleted while it was being created"); return -1; } else { - mail_storage_set_critical(storage, + mail_storage_set_critical(box->storage, "open(%s, O_CREAT) failed: %m", path); } - return 0; + return directory || update == NULL ? 0 : + maildir_mailbox_update(box, update); } static void @@ -1026,7 +1052,6 @@ maildir_storage_get_list_settings, maildir_storage_autodetect, maildir_mailbox_alloc, - maildir_mailbox_create, NULL } }; @@ -1042,6 +1067,8 @@ index_storage_mailbox_enable, maildir_mailbox_open, maildir_mailbox_close, + maildir_mailbox_create, + maildir_mailbox_update, maildir_storage_get_status, maildir_list_index_has_changed, maildir_list_index_update_sync,
--- a/src/lib-storage/index/maildir/maildir-uidlist.c Thu Jun 25 14:33:37 2009 -0400 +++ b/src/lib-storage/index/maildir/maildir-uidlist.c Fri Jun 26 16:11:59 2009 -0400 @@ -1080,19 +1080,35 @@ return 0; } +void maildir_uidlist_set_mailbox_guid(struct maildir_uidlist *uidlist, + const uint8_t mailbox_guid[MAILBOX_GUID_SIZE]) +{ + if (memcmp(uidlist->mailbox_guid, mailbox_guid, + sizeof(uidlist->mailbox_guid)) != 0) { + memcpy(uidlist->mailbox_guid, mailbox_guid, + sizeof(uidlist->mailbox_guid)); + uidlist->recreate = TRUE; + } +} + void maildir_uidlist_set_uid_validity(struct maildir_uidlist *uidlist, uint32_t uid_validity) { i_assert(uid_validity != 0); - uidlist->uid_validity = uid_validity; + if (uid_validity != uidlist->uid_validity) { + uidlist->uid_validity = uid_validity; + uidlist->recreate = TRUE; + } } void maildir_uidlist_set_next_uid(struct maildir_uidlist *uidlist, uint32_t next_uid, bool force) { - if (uidlist->next_uid < next_uid || force) + if (uidlist->next_uid < next_uid || force) { uidlist->next_uid = next_uid; + uidlist->recreate = TRUE; + } } static void @@ -1163,8 +1179,14 @@ { const struct mail_index_header *hdr; - hdr = mail_index_get_header(uidlist->ibox->view); - uidlist->uid_validity = hdr->uid_validity != 0 ? hdr->uid_validity : + if (uidlist->ibox->box.opened) { + hdr = mail_index_get_header(uidlist->ibox->view); + if (hdr->uid_validity != 0) { + uidlist->uid_validity = hdr->uid_validity; + return; + } + } + uidlist->uid_validity = maildir_get_uidvalidity_next(uidlist->ibox->box.list); }
--- a/src/lib-storage/index/maildir/maildir-uidlist.h Thu Jun 25 14:33:37 2009 -0400 +++ b/src/lib-storage/index/maildir/maildir-uidlist.h Fri Jun 26 16:11:59 2009 -0400 @@ -84,6 +84,8 @@ uint32_t maildir_uidlist_get_next_uid(struct maildir_uidlist *uidlist); int maildir_uidlist_get_mailbox_guid(struct maildir_uidlist *uidlist, uint8_t mailbox_guid[MAILBOX_GUID_SIZE]); +void maildir_uidlist_set_mailbox_guid(struct maildir_uidlist *uidlist, + const uint8_t mailbox_guid[MAILBOX_GUID_SIZE]); void maildir_uidlist_set_uid_validity(struct maildir_uidlist *uidlist, uint32_t uid_validity);
--- a/src/lib-storage/index/mbox/mbox-storage.c Thu Jun 25 14:33:37 2009 -0400 +++ b/src/lib-storage/index/mbox/mbox-storage.c Fri Jun 26 16:11:59 2009 -0400 @@ -487,9 +487,28 @@ } static int -mbox_mailbox_create(struct mail_storage *_storage, struct mailbox_list *list, - const char *name, bool directory) +mbox_mailbox_update(struct mailbox *box, const struct mailbox_update *update) { + struct mbox_mailbox *mbox = (struct mbox_mailbox *)box; + int ret; + + if (!box->opened) { + if (mailbox_open(box) < 0) + return -1; + } + + mbox->sync_hdr_update = update; + ret = mbox_sync(mbox, MBOX_SYNC_HEADER | MBOX_SYNC_FORCE_SYNC | + MBOX_SYNC_REWRITE); + mbox->sync_hdr_update = NULL; + return ret; +} + +static int +mbox_mailbox_create(struct mailbox *box, const struct mailbox_update *update, + bool directory) +{ + struct mail_storage *storage = box->storage; const char *path, *p; struct stat st; mode_t mode; @@ -497,20 +516,20 @@ int fd; /* make sure it doesn't exist already */ - path = mailbox_list_get_path(list, name, + path = mailbox_list_get_path(box->list, box->name, MAILBOX_LIST_PATH_TYPE_MAILBOX); if (stat(path, &st) == 0) { - mail_storage_set_error(_storage, MAIL_ERROR_EXISTS, + mail_storage_set_error(storage, MAIL_ERROR_EXISTS, "Mailbox already exists"); return -1; } if (errno != ENOENT) { if (errno == ENOTDIR) { - mail_storage_set_error(_storage, MAIL_ERROR_NOTPOSSIBLE, + mail_storage_set_error(storage, MAIL_ERROR_NOTPOSSIBLE, "Mailbox doesn't allow inferior mailboxes"); - } else if (!mail_storage_set_error_from_errno(_storage)) { - mail_storage_set_critical(_storage, + } else if (!mail_storage_set_error_from_errno(storage)) { + mail_storage_set_critical(storage, "stat() failed for mbox file %s: %m", path); } return -1; @@ -520,11 +539,11 @@ p = directory ? path + strlen(path) : strrchr(path, '/'); if (p != NULL) { p = t_strdup_until(path, p); - mailbox_list_get_dir_permissions(list, NULL, &mode, &gid); + mailbox_list_get_dir_permissions(box->list, NULL, &mode, &gid); if (mkdir_parents_chown(p, mode, (uid_t)-1, gid) < 0 && errno != EEXIST) { - if (!mail_storage_set_error_from_errno(_storage)) { - mail_storage_set_critical(_storage, + if (!mail_storage_set_error_from_errno(storage)) { + mail_storage_set_critical(storage, "mkdir_parents(%s) failed: %m", p); } return -1; @@ -540,16 +559,16 @@ fd = open(path, O_RDWR | O_CREAT | O_EXCL, 0660); if (fd != -1) { (void)close(fd); - return 0; + return update == NULL ? 0 : mbox_mailbox_update(box, update); } if (errno == EEXIST) { /* mailbox was just created between stat() and open() call.. */ - mail_storage_set_error(_storage, MAIL_ERROR_EXISTS, + mail_storage_set_error(storage, MAIL_ERROR_EXISTS, "Mailbox already exists"); - } else if (!mail_storage_set_error_from_errno(_storage)) { - mail_storage_set_critical(_storage, - "Can't create mailbox %s: %m", name); + } else if (!mail_storage_set_error_from_errno(storage)) { + mail_storage_set_critical(storage, + "Can't create mailbox %s: %m", box->name); } return -1; } @@ -842,7 +861,6 @@ mbox_storage_get_list_settings, mbox_storage_autodetect, mbox_mailbox_alloc, - mbox_mailbox_create, NULL } }; @@ -858,6 +876,8 @@ index_storage_mailbox_enable, mbox_mailbox_open, mbox_mailbox_close, + mbox_mailbox_create, + mbox_mailbox_update, mbox_storage_get_status, NULL, NULL,
--- a/src/lib-storage/index/mbox/mbox-storage.h Thu Jun 25 14:33:37 2009 -0400 +++ b/src/lib-storage/index/mbox/mbox-storage.h Fri Jun 26 16:11:59 2009 -0400 @@ -48,6 +48,7 @@ uint32_t mbox_ext_idx; struct mbox_index_header mbox_hdr; + const struct mailbox_update *sync_hdr_update; unsigned int no_mbox_file:1; unsigned int invalid_mbox_file:1;
--- a/src/lib-storage/index/mbox/mbox-sync.c Thu Jun 25 14:33:37 2009 -0400 +++ b/src/lib-storage/index/mbox/mbox-sync.c Fri Jun 26 16:11:59 2009 -0400 @@ -957,7 +957,26 @@ return ret; } -static bool mbox_sync_uidvalidity_changed(struct mbox_sync_context *sync_ctx) +static void mbox_sync_hdr_update(struct mbox_sync_context *sync_ctx, + struct mbox_sync_mail_context *mail_ctx) +{ + const struct mailbox_update *update = sync_ctx->mbox->sync_hdr_update; + + if (update->uid_validity != 0) { + sync_ctx->base_uid_validity = update->uid_validity; + mail_ctx->imapbase_rewrite = TRUE; + mail_ctx->need_rewrite = TRUE; + } + if (update->min_next_uid != 0 && + sync_ctx->base_uid_last <= update->min_next_uid) { + sync_ctx->base_uid_last = update->min_next_uid-1; + mail_ctx->imapbase_rewrite = TRUE; + mail_ctx->need_rewrite = TRUE; + } +} + +static bool mbox_sync_imapbase(struct mbox_sync_context *sync_ctx, + struct mbox_sync_mail_context *mail_ctx) { if (sync_ctx->base_uid_validity != 0 && sync_ctx->hdr->uid_validity != 0 && @@ -969,6 +988,8 @@ sync_ctx->index_reset = TRUE; return TRUE; } + if (sync_ctx->mbox->sync_hdr_update != NULL) + mbox_sync_hdr_update(sync_ctx, mail_ctx); return FALSE; } @@ -1004,7 +1025,7 @@ uid = mail_ctx->mail.uid; if (mail_ctx->seq == 1) { - if (mbox_sync_uidvalidity_changed(sync_ctx)) { + if (mbox_sync_imapbase(sync_ctx, mail_ctx)) { sync_ctx->mbox->mbox_hdr.dirty_flag = TRUE; return 0; } @@ -1332,26 +1353,20 @@ return 0; } -static bool mbox_has_mailbox_guid(struct mbox_mailbox *mbox) -{ - unsigned int i; - - for (i = 0; i < sizeof(mbox->mbox_hdr.mailbox_guid); i++) { - if (mbox->mbox_hdr.mailbox_guid[i] != 0) - return TRUE; - } - return FALSE; -} - static void mbox_sync_index_update_ext_header(struct mbox_sync_context *sync_ctx) { + const struct mailbox_update *update = sync_ctx->mbox->sync_hdr_update; struct mbox_mailbox *mbox = sync_ctx->mbox; const void *data; size_t data_size; - if (!mbox_has_mailbox_guid(mbox)) + if (update != NULL && !mailbox_guid_is_empty(update->mailbox_guid)) { + memcpy(mbox->mbox_hdr.mailbox_guid, update->mailbox_guid, + sizeof(mbox->mbox_hdr.mailbox_guid)); + } else if (mailbox_guid_is_empty(mbox->mbox_hdr.mailbox_guid)) { mail_generate_guid_128(mbox->mbox_hdr.mailbox_guid); + } mail_index_get_header_ext(mbox->ibox.view, mbox->mbox_ext_idx, &data, &data_size); @@ -1655,7 +1670,7 @@ if (mbox_sync_header_refresh(mbox) < 0) return -1; - if (!mbox_has_mailbox_guid(mbox)) { + if (mailbox_guid_is_empty(mbox->mbox_hdr.mailbox_guid)) { /* need to assign mailbox GUID */ return 1; }
--- a/src/lib-storage/index/raw/raw-storage.c Thu Jun 25 14:33:37 2009 -0400 +++ b/src/lib-storage/index/raw/raw-storage.c Fri Jun 26 16:11:59 2009 -0400 @@ -90,15 +90,24 @@ } static int -raw_mailbox_create(struct mail_storage *storage, - struct mailbox_list *list ATTR_UNUSED, - const char *name ATTR_UNUSED, bool directory ATTR_UNUSED) +raw_mailbox_create(struct mailbox *box, + const struct mailbox_update *update ATTR_UNUSED, + bool directory ATTR_UNUSED) { - mail_storage_set_error(storage, MAIL_ERROR_NOTPOSSIBLE, + mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE, "Raw mailbox creation isn't supported"); return -1; } +static int +raw_mailbox_update(struct mailbox *box, + const struct mailbox_update *update ATTR_UNUSED) +{ + mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE, + "Raw mailbox update isn't supported"); + return -1; +} + static int raw_list_delete_mailbox(struct mailbox_list *list, const char *name ATTR_UNUSED) { @@ -185,7 +194,6 @@ raw_storage_get_list_settings, NULL, raw_mailbox_alloc, - raw_mailbox_create, NULL } }; @@ -201,6 +209,8 @@ index_storage_mailbox_enable, raw_mailbox_open, index_storage_mailbox_close, + raw_mailbox_create, + raw_mailbox_update, index_storage_get_status, NULL, NULL,
--- a/src/lib-storage/index/shared/shared-storage.c Thu Jun 25 14:33:37 2009 -0400 +++ b/src/lib-storage/index/shared/shared-storage.c Fri Jun 26 16:11:59 2009 -0400 @@ -282,35 +282,6 @@ return 0; } -static int -shared_mailbox_create(struct mail_storage *storage, struct mailbox_list *list, - const char *name, bool directory) -{ - struct mail_namespace *ns = list->ns; - struct mailbox_list *new_list; - struct mail_storage *new_storage; - const char *str; - enum mail_error error; - int ret; - - if (shared_storage_get_namespace(&ns, &name) < 0) { - str = mailbox_list_get_last_error(list, &error); - mail_storage_set_error(storage, error, str); - return -1; - } - - new_list = ns->list; - if (mailbox_list_get_storage(&new_list, &name, &new_storage) < 0) - return -1; - - ret = mail_storage_mailbox_create(new_storage, ns, name, directory); - if (ret < 0) { - str = mail_storage_get_last_error(new_storage, &error); - mail_storage_set_error(storage, error, str); - } - return ret; -} - struct mail_storage shared_storage = { MEMBER(name) SHARED_STORAGE_NAME, MEMBER(class_flags) 0, /* unknown at this point */ @@ -326,7 +297,6 @@ shared_storage_get_list_settings, NULL, NULL, - shared_mailbox_create, NULL } };
--- a/src/lib-storage/mail-storage-private.h Thu Jun 25 14:33:37 2009 -0400 +++ b/src/lib-storage/mail-storage-private.h Fri Jun 26 16:11:59 2009 -0400 @@ -48,10 +48,6 @@ const char *name, struct istream *input, enum mailbox_flags flags); - - int (*mailbox_create)(struct mail_storage *storage, - struct mailbox_list *list, const char *name, - bool directory); int (*purge)(struct mail_storage *storage); }; @@ -104,6 +100,10 @@ int (*open)(struct mailbox *box); void (*close)(struct mailbox *box); + int (*create)(struct mailbox *box, const struct mailbox_update *update, + bool directory); + int (*update)(struct mailbox *box, const struct mailbox_update *update); + void (*get_status)(struct mailbox *box, enum mailbox_status_items items, struct mailbox_status *status_r); @@ -427,6 +427,6 @@ int mail_set_aborted(struct mail *mail); void mail_set_expunged(struct mail *mail); void mailbox_set_deleted(struct mailbox *box); - +bool mailbox_guid_is_empty(const uint8_t guid[MAILBOX_GUID_SIZE]); #endif
--- a/src/lib-storage/mail-storage.c Thu Jun 25 14:33:37 2009 -0400 +++ b/src/lib-storage/mail-storage.c Fri Jun 26 16:11:59 2009 -0400 @@ -391,21 +391,6 @@ storage->callback_context = context; } -int mail_storage_mailbox_create(struct mail_storage *storage, - struct mail_namespace *ns, const char *name, - bool directory) -{ - mail_storage_clear_error(storage); - - if (!mailbox_list_is_valid_create_name(ns->list, name)) { - mail_storage_set_error(storage, MAIL_ERROR_PARAMS, - "Invalid mailbox name"); - return -1; - } - - return storage->v.mailbox_create(storage, ns->list, name, directory); -} - int mail_storage_purge(struct mail_storage *storage) { mail_storage_clear_error(storage); @@ -531,6 +516,27 @@ box->v.close(box); } +int mailbox_create(struct mailbox *box, const struct mailbox_update *update, + bool directory) +{ + mail_storage_clear_error(box->storage); + + if (!mailbox_list_is_valid_create_name(box->list, box->name)) { + mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS, + "Invalid mailbox name"); + return -1; + } + + return box->v.create(box, update, directory); +} + +int mailbox_update(struct mailbox *box, const struct mailbox_update *update) +{ + mail_storage_clear_error(box->storage); + + return box->v.update(box, update); +} + struct mail_storage *mailbox_get_storage(const struct mailbox *box) { return box->storage; @@ -1035,3 +1041,14 @@ "Mailbox was deleted under us"); box->mailbox_deleted = TRUE; } + +bool mailbox_guid_is_empty(const uint8_t guid[MAILBOX_GUID_SIZE]) +{ + unsigned int i; + + for (i = 0; i < MAILBOX_GUID_SIZE; i++) { + if (guid[i] != 0) + return FALSE; + } + return TRUE; +}
--- a/src/lib-storage/mail-storage.h Thu Jun 25 14:33:37 2009 -0400 +++ b/src/lib-storage/mail-storage.h Fri Jun 26 16:11:59 2009 -0400 @@ -191,6 +191,14 @@ unsigned int nonpermanent_modseqs:1; }; +struct mailbox_update { + /* All non-zero fields are changed. */ + uint8_t mailbox_guid[MAILBOX_GUID_SIZE]; + uint32_t uid_validity; + uint32_t min_next_uid; + uint64_t min_highest_modseq; +}; + struct mailbox_sync_rec { uint32_t seq1, seq2; enum mailbox_sync_type type; @@ -271,13 +279,6 @@ struct mail_storage_callbacks *callbacks, void *context); -/* name is allowed to contain multiple new hierarchy levels. - If directory is TRUE, the mailbox should be created so that it - can contain children. The mailbox itself doesn't have to be - created as long as it shows in LIST. */ -int mail_storage_mailbox_create(struct mail_storage *storage, - struct mail_namespace *ns, const char *name, - bool directory); /* Purge storage's mailboxes (freeing disk space from expunged mails), if supported by the storage. Otherwise just a no-op. */ int mail_storage_purge(struct mail_storage *storage); @@ -296,14 +297,24 @@ Note that append and copy may open the selected mailbox again with possibly different readonly-state. */ struct mailbox *mailbox_alloc(struct mailbox_list *list, const char *name, - struct istream *input, - enum mailbox_flags flags); + struct istream *input, enum mailbox_flags flags); /* Open the mailbox. If this function isn't called explicitly, it's also called internally by lib-storage when necessary. */ int mailbox_open(struct mailbox *box); /* Close the box. */ void mailbox_close(struct mailbox **box); +/* Create a mailbox. Returns failure if it already exists. Mailbox name is + allowed to contain multiple new non-existing hierarchy levels. If directory + is TRUE, the mailbox should be created so that it can contain children. The + mailbox itself doesn't have to be created as long as it shows up in LIST. + If update is non-NULL, its contents are used to set initial mailbox + metadata. */ +int mailbox_create(struct mailbox *box, const struct mailbox_update *update, + bool directory); +/* Update existing mailbox's metadata. */ +int mailbox_update(struct mailbox *box, const struct mailbox_update *update); + /* Enable the given feature for the mailbox. */ int mailbox_enable(struct mailbox *box, enum mailbox_feature features); /* Returns all enabled features. */
--- a/src/lib-storage/test-mail-storage.c Thu Jun 25 14:33:37 2009 -0400 +++ b/src/lib-storage/test-mail-storage.c Fri Jun 26 16:11:59 2009 -0400 @@ -30,17 +30,6 @@ set->subscription_fname = "subscriptions"; } -static int -test_mailbox_create(struct mail_storage *storage, - struct mailbox_list *list ATTR_UNUSED, - const char *name ATTR_UNUSED, - bool directory ATTR_UNUSED) -{ - mail_storage_set_error(storage, MAIL_ERROR_NOTPOSSIBLE, - "Test mailbox creation isn't supported"); - return -1; -} - struct mail_storage test_storage = { MEMBER(name) "test", MEMBER(class_flags) 0, @@ -56,7 +45,6 @@ test_storage_get_list_settings, NULL, test_mailbox_alloc, - test_mailbox_create, NULL } };
--- a/src/lib-storage/test-mailbox.c Thu Jun 25 14:33:37 2009 -0400 +++ b/src/lib-storage/test-mailbox.c Fri Jun 26 16:11:59 2009 -0400 @@ -33,6 +33,25 @@ { } +static int +test_mailbox_create(struct mailbox *box, + const struct mailbox_update *update ATTR_UNUSED, + bool directory ATTR_UNUSED) +{ + mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE, + "Test mailbox creation isn't supported"); + return -1; +} + +static int +test_mailbox_update(struct mailbox *box, + const struct mailbox_update *update ATTR_UNUSED) +{ + mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE, + "Test mailbox update isn't supported"); + return -1; +} + static void test_mailbox_get_status(struct mailbox *box ATTR_UNUSED, enum mailbox_status_items items ATTR_UNUSED, struct mailbox_status *status_r) @@ -294,6 +313,8 @@ test_mailbox_enable, test_mailbox_open, test_mailbox_close, + test_mailbox_create, + test_mailbox_update, test_mailbox_get_status, NULL, NULL,
--- a/src/plugins/acl/acl-mailbox.c Thu Jun 25 14:33:37 2009 -0400 +++ b/src/plugins/acl/acl-mailbox.c Fri Jun 26 16:11:59 2009 -0400 @@ -104,6 +104,41 @@ } static int +acl_mailbox_create(struct mailbox *box, const struct mailbox_update *update, + bool directory) +{ + struct acl_mailbox *abox = ACL_CONTEXT(box); + int ret; + + /* we're looking up CREATE permission from our parent's rights */ + ret = acl_mailbox_list_have_right(box->list, box->name, TRUE, + ACL_STORAGE_RIGHT_CREATE, NULL); + if (ret <= 0) { + if (ret < 0) + return -1; + /* Note that if user didn't have LOOKUP permission to parent + mailbox, this may reveal the mailbox's existence to user. + Can't help it. */ + mail_storage_set_error(box->storage, MAIL_ERROR_PERM, + MAIL_ERRSTR_NO_PERMISSION); + return -1; + } + return abox->module_ctx.super.create(box, update, directory); +} + +static int +acl_mailbox_update(struct mailbox *box, const struct mailbox_update *update) +{ + struct acl_mailbox *abox = ACL_CONTEXT(box); + int ret; + + ret = acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_ADMIN); + if (ret <= 0) + return -1; + return abox->module_ctx.super.update(box, update); +} + +static int acl_get_write_rights(struct mailbox *box, bool *flags_r, bool *flag_seen_r, bool *flag_del_r) { @@ -409,6 +444,8 @@ box->v.allow_new_keywords = acl_allow_new_keywords; box->v.open = acl_mailbox_open; box->v.close = acl_mailbox_close; + box->v.create = acl_mailbox_create; + box->v.update = acl_mailbox_update; box->v.mail_alloc = acl_mail_alloc; box->v.save_begin = acl_save_begin; box->v.keywords_create = acl_keywords_create;
--- a/src/plugins/acl/acl-storage.c Thu Jun 25 14:33:37 2009 -0400 +++ b/src/plugins/acl/acl-storage.c Fri Jun 26 16:11:59 2009 -0400 @@ -16,37 +16,6 @@ struct acl_user_module acl_user_module = MODULE_CONTEXT_INIT(&mail_user_module_register); -static int -acl_mailbox_create(struct mail_storage *storage, struct mailbox_list *list, - const char *name, bool directory) -{ - union mail_storage_module_context *astorage = ACL_CONTEXT(storage); - int ret; - - if ((list->ns->flags & NAMESPACE_FLAG_NOACL) != 0) - ret = 1; - else T_BEGIN { - ret = acl_mailbox_list_have_right(list, name, TRUE, - ACL_STORAGE_RIGHT_CREATE, - NULL); - } T_END; - - if (ret <= 0) { - if (ret == 0) { - /* Note that if the mailbox didn't have LOOKUP - permission, this not reveals to user the mailbox's - existence. Can't help it. */ - mail_storage_set_error(storage, MAIL_ERROR_PERM, - MAIL_ERRSTR_NO_PERMISSION); - } else { - mail_storage_set_internal_error(storage); - } - return -1; - } - - return astorage->super.mailbox_create(storage, list, name, directory); -} - void acl_mail_storage_created(struct mail_storage *storage) { struct acl_user *auser = ACL_USER_CONTEXT(storage->user); @@ -59,7 +28,6 @@ union mail_storage_module_context, 1); astorage->super = storage->v; storage->v.mailbox_alloc = acl_mailbox_alloc; - storage->v.mailbox_create = acl_mailbox_create; MODULE_CONTEXT_SET_SELF(storage, acl_storage_module, astorage); } @@ -112,4 +80,3 @@ if (acl_next_hook_mail_user_created != NULL) acl_next_hook_mail_user_created(user); } -
--- a/src/plugins/autocreate/autocreate-plugin.c Thu Jun 25 14:33:37 2009 -0400 +++ b/src/plugins/autocreate/autocreate-plugin.c Fri Jun 26 16:11:59 2009 -0400 @@ -16,7 +16,7 @@ autocreate_mailbox(struct mail_namespace *namespaces, const char *name) { struct mail_namespace *ns; - struct mail_storage *storage; + struct mailbox *box; const char *str; enum mail_error error; @@ -27,14 +27,16 @@ return; } - storage = mail_namespace_get_default_storage(ns); - if (mail_storage_mailbox_create(storage, ns, name, FALSE) < 0) { - str = mail_storage_get_last_error(storage, &error); + box = mailbox_alloc(ns->list, name, NULL, 0); + if (mailbox_create(box, NULL, FALSE) < 0) { + str = mail_storage_get_last_error(mailbox_get_storage(box), + &error); if (error != MAIL_ERROR_EXISTS && ns->mail_set->mail_debug) { i_info("autocreate: Failed to create mailbox %s: %s", name, str); } } + mailbox_close(&box); } static void autocreate_mailboxes(struct mail_namespace *namespaces)
--- a/src/plugins/convert/convert-storage.c Thu Jun 25 14:33:37 2009 -0400 +++ b/src/plugins/convert/convert-storage.c Fri Jun 26 16:11:59 2009 -0400 @@ -135,9 +135,9 @@ "dovecot.index.log", "dovecot.index.cache" }; - struct mail_storage *dest_storage; string_t *src, *dest; DIR *dir; + struct mailbox *destbox; struct dirent *dp; const char *src_path, *dest_path, *new_path, *cur_path; unsigned int i, src_dir_len, dest_dir_len; @@ -145,14 +145,15 @@ /* create as non-selectable mailbox so the dbox-Mails directory isn't created yet */ - dest_storage = mail_namespace_get_default_storage(dest_ns); - if (mail_storage_mailbox_create(dest_storage, dest_ns, - dest_name, TRUE) < 0) { + destbox = mailbox_alloc(dest_ns->list, dest_name, NULL, 0); + if (mailbox_create(destbox, NULL, TRUE) < 0) { i_error("Mailbox conversion: " "Couldn't create mailbox %s: %s", - dest_name, storage_error(dest_storage)); + dest_name, storage_error(mailbox_get_storage(destbox))); + mailbox_close(&destbox); return -1; } + mailbox_close(&destbox); src_path = mailbox_list_get_path(source_ns->list, src_name, MAILBOX_LIST_PATH_TYPE_MAILBOX); @@ -237,19 +238,21 @@ } static int mailbox_convert_list_item(struct mail_namespace *source_ns, - struct mail_namespace *dest_ns, + struct mailbox *destbox, const struct mailbox_info *info, struct dotlock *dotlock, const struct convert_plugin_settings *set) { + struct mail_namespace *dest_ns; struct mail_storage *dest_storage; const char *name, *dest_name, *error; - struct mailbox *srcbox, *destbox; + struct mailbox *srcbox; int ret = 0; if ((info->flags & MAILBOX_NONEXISTENT) != 0) return 0; + dest_ns = mailbox_get_namespace(destbox); name = strcasecmp(info->name, "INBOX") == 0 ? "INBOX" : info->name; dest_name = mailbox_name_convert(dest_ns, source_ns, set, name); dest_storage = mail_namespace_get_default_storage(dest_ns); @@ -259,8 +262,7 @@ if (*info->name == '.' && set->skip_dotdirs) return 0; - if (mail_storage_mailbox_create(dest_storage, dest_ns, - dest_name, TRUE) < 0) { + if (mailbox_create(destbox, NULL, TRUE) < 0) { i_error("Mailbox conversion: Couldn't create mailbox " "directory %s: %s", dest_name, storage_error(dest_storage)); @@ -298,8 +300,7 @@ /* Create and open the destination mailbox. */ if (strcmp(dest_name, "INBOX") != 0) { - if (mail_storage_mailbox_create(dest_storage, dest_ns, - dest_name, FALSE) < 0) { + if (mailbox_create(destbox, NULL, FALSE) < 0) { i_error("Mailbox conversion: " "Couldn't create mailbox %s: %s", dest_name, storage_error(dest_storage)); @@ -308,13 +309,10 @@ } } - destbox = mailbox_alloc(dest_ns->list, dest_name, NULL, - MAILBOX_FLAG_KEEP_RECENT); if (mailbox_open(destbox) < 0) { i_error("Mailbox conversion: Couldn't open dest mailbox %s: %s", dest_name, storage_error(mailbox_get_storage(destbox))); mailbox_close(&srcbox); - mailbox_close(&destbox); return -1; } @@ -324,7 +322,6 @@ } mailbox_close(&srcbox); - mailbox_close(&destbox); return ret; } @@ -335,6 +332,7 @@ { struct mailbox_list_iterate_context *iter; struct mail_namespace *dest_ns; + struct mailbox *destbox; const struct mailbox_info *info; int ret = 0; @@ -343,8 +341,11 @@ "*", MAILBOX_LIST_ITER_RETURN_NO_FLAGS); while ((info = mailbox_list_iter_next(iter)) != NULL) { T_BEGIN { - ret = mailbox_convert_list_item(source_ns, dest_ns, + destbox = mailbox_alloc(dest_ns->list, info->name, NULL, + MAILBOX_FLAG_KEEP_RECENT); + ret = mailbox_convert_list_item(source_ns, destbox, info, dotlock, set); + mailbox_close(&destbox); } T_END; if (ret < 0) break;
--- a/src/plugins/lazy-expunge/lazy-expunge-plugin.c Thu Jun 25 14:33:37 2009 -0400 +++ b/src/plugins/lazy-expunge/lazy-expunge-plugin.c Fri Jun 26 16:11:59 2009 -0400 @@ -92,22 +92,17 @@ *error_r = mail_storage_get_last_error(mailbox_get_storage(box), &error); - mailbox_close(&box); - if (error != MAIL_ERROR_NOTFOUND) - return NULL; - - /* try creating it. */ - storage = mail_namespace_get_default_storage(list->ns); - if (mail_storage_mailbox_create(storage, list->ns, name, FALSE) < 0) { - *error_r = mail_storage_get_last_error(storage, &error); + if (error != MAIL_ERROR_NOTFOUND) { + mailbox_close(&box); return NULL; } - /* and try opening again */ - box = mailbox_alloc(list, name, NULL, MAILBOX_FLAG_KEEP_RECENT); - if (mailbox_open(box) < 0) { + /* try creating and re-opening it. */ + storage = mail_namespace_get_default_storage(list->ns); + if (mailbox_create(box, NULL, FALSE) < 0 || + mailbox_open(box) < 0) { *error_r = mail_storage_get_last_error(mailbox_get_storage(box), - &error); + NULL); mailbox_close(&box); return NULL; }
--- a/src/plugins/listescape/listescape-plugin.c Thu Jun 25 14:33:37 2009 -0400 +++ b/src/plugins/listescape/listescape-plugin.c Fri Jun 26 16:11:59 2009 -0400 @@ -178,20 +178,6 @@ } static int -listescape_mailbox_create(struct mail_storage *storage, - struct mailbox_list *list, - const char *name, bool directory) -{ - struct listescape_mail_storage *mstorage = - LIST_ESCAPE_CONTEXT(storage); - - if (list->hierarchy_sep != list->ns->sep) - name = list_escape(list->ns, name, TRUE); - return mstorage->module_ctx.super. - mailbox_create(storage, list, name, directory); -} - -static int listescape_delete_mailbox(struct mailbox_list *list, const char *name) { struct listescape_mailbox_list *mlist = LIST_ESCAPE_LIST_CONTEXT(list); @@ -268,7 +254,6 @@ mstorage = p_new(storage->pool, struct listescape_mail_storage, 1); mstorage->module_ctx.super = storage->v; storage->v.mailbox_alloc = listescape_mailbox_alloc; - storage->v.mailbox_create = listescape_mailbox_create; MODULE_CONTEXT_SET(storage, listescape_storage_module, mstorage); }
--- a/src/plugins/virtual/virtual-storage.c Thu Jun 25 14:33:37 2009 -0400 +++ b/src/plugins/virtual/virtual-storage.c Fri Jun 26 16:11:59 2009 -0400 @@ -271,17 +271,26 @@ index_storage_mailbox_close(box); } -static int virtual_mailbox_create(struct mail_storage *_storage, - struct mailbox_list *list ATTR_UNUSED, - const char *name ATTR_UNUSED, - bool directory ATTR_UNUSED) +static int +virtual_mailbox_create(struct mailbox *box, + const struct mailbox_update *update ATTR_UNUSED, + bool directory ATTR_UNUSED) { - mail_storage_set_error(_storage, MAIL_ERROR_NOTPOSSIBLE, + mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE, "Can't create virtual mailboxes"); return -1; } static int +virtual_mailbox_update(struct mailbox *box, + const struct mailbox_update *update ATTR_UNUSED) +{ + mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE, + "Can't update virtual mailboxes"); + return -1; +} + +static int virtual_delete_nonrecursive(struct mailbox_list *list, const char *path, const char *name) { @@ -558,7 +567,6 @@ virtual_storage_get_list_settings, NULL, virtual_mailbox_alloc, - virtual_mailbox_create, NULL } }; @@ -574,6 +582,8 @@ index_storage_mailbox_enable, virtual_mailbox_open, virtual_mailbox_close, + virtual_mailbox_create, + virtual_mailbox_update, index_storage_get_status, NULL, NULL,