mail-storage.c (dovecot-2.3.16) | : | mail-storage.c (dovecot-2.3.17) | ||
---|---|---|---|---|
/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */ | /* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */ | |||
#include "lib.h" | #include "lib.h" | |||
#include "ioloop.h" | #include "ioloop.h" | |||
#include "array.h" | #include "array.h" | |||
#include "llist.h" | #include "llist.h" | |||
#include "mail-storage.h" | ||||
#include "str.h" | #include "str.h" | |||
#include "str-sanitize.h" | #include "str-sanitize.h" | |||
#include "sha1.h" | #include "sha1.h" | |||
#include "unichar.h" | #include "unichar.h" | |||
#include "hex-binary.h" | #include "hex-binary.h" | |||
#include "fs-api.h" | ||||
#include "iostream-ssl.h" | ||||
#include "file-dotlock.h" | #include "file-dotlock.h" | |||
#include "file-create-locked.h" | #include "file-create-locked.h" | |||
#include "istream.h" | #include "istream.h" | |||
#include "eacces-error.h" | #include "eacces-error.h" | |||
#include "mkdir-parents.h" | #include "mkdir-parents.h" | |||
#include "time-util.h" | #include "time-util.h" | |||
#include "var-expand.h" | #include "var-expand.h" | |||
#include "dsasl-client.h" | #include "dsasl-client.h" | |||
#include "imap-date.h" | #include "imap-date.h" | |||
#include "settings-parser.h" | #include "settings-parser.h" | |||
skipping to change at line 420 | skipping to change at line 423 | |||
storage = mail_storage_find(ns->user, storage_class, &list_set); | storage = mail_storage_find(ns->user, storage_class, &list_set); | |||
if (storage != NULL) { | if (storage != NULL) { | |||
/* using an existing storage */ | /* using an existing storage */ | |||
storage->refcount++; | storage->refcount++; | |||
mail_namespace_add_storage(ns, storage); | mail_namespace_add_storage(ns, storage); | |||
*storage_r = storage; | *storage_r = storage; | |||
return 0; | return 0; | |||
} | } | |||
storage = storage_class->v.alloc(); | storage = storage_class->v.alloc(); | |||
if (storage->lost_mailbox_prefix == NULL) | ||||
storage->lost_mailbox_prefix = MAIL_STORAGE_LOST_MAILBOX_PREFIX; | ||||
storage->refcount = 1; | storage->refcount = 1; | |||
storage->storage_class = storage_class; | storage->storage_class = storage_class; | |||
storage->user = ns->user; | storage->user = ns->user; | |||
storage->set = ns->mail_set; | storage->set = ns->mail_set; | |||
storage->flags = flags; | storage->flags = flags; | |||
storage->event = event_create(ns->user->event); | storage->event = event_create(ns->user->event); | |||
if (storage_class->event_category != NULL) | if (storage_class->event_category != NULL) | |||
event_add_category(storage->event, storage_class->event_category) ; | event_add_category(storage->event, storage_class->event_category) ; | |||
p_array_init(&storage->module_contexts, storage->pool, 5); | p_array_init(&storage->module_contexts, storage->pool, 5); | |||
if (storage->v.create != NULL && | if (storage->v.create != NULL && | |||
storage->v.create(storage, ns, error_r) < 0) { | storage->v.create(storage, ns, error_r) < 0) { | |||
*error_r = t_strdup_printf("%s: %s", storage->name, *error_r); | *error_r = t_strdup_printf("%s: %s", storage->name, *error_r); | |||
event_unref(&storage->event); | event_unref(&storage->event); | |||
pool_unref(&storage->pool); | pool_unref(&storage->pool); | |||
return -1; | return -1; | |||
} | } | |||
/* If storage supports list index rebuild, | ||||
provide default mailboxes_fs unless storage | ||||
wants to use its own. */ | ||||
if (storage->v.list_index_rebuild != NULL && | ||||
storage->mailboxes_fs == NULL) { | ||||
struct fs_settings fs_set; | ||||
struct ssl_iostream_settings ssl_set; | ||||
const char *error; | ||||
i_zero(&fs_set); | ||||
mail_user_init_fs_settings(storage->user, &fs_set, &ssl_set); | ||||
if (fs_init("posix", "", &fs_set, &storage->mailboxes_fs, | ||||
&error) < 0) { | ||||
*error_r = t_strdup_printf("fs_init(posix) failed: %s", e | ||||
rror); | ||||
storage->v.destroy(storage); | ||||
return -1; | ||||
} | ||||
} | ||||
T_BEGIN { | T_BEGIN { | |||
hook_mail_storage_created(storage); | hook_mail_storage_created(storage); | |||
} T_END; | } T_END; | |||
i_assert(storage->unique_root_dir != NULL || | i_assert(storage->unique_root_dir != NULL || | |||
(storage->class_flags & MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT) == 0); | (storage->class_flags & MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT) == 0); | |||
DLLIST_PREPEND(&ns->user->storages, storage); | DLLIST_PREPEND(&ns->user->storages, storage); | |||
mail_namespace_add_storage(ns, storage); | mail_namespace_add_storage(ns, storage); | |||
*storage_r = storage; | *storage_r = storage; | |||
return 0; | return 0; | |||
skipping to change at line 488 | skipping to change at line 512 | |||
DLLIST_REMOVE(&storage->user->storages, storage); | DLLIST_REMOVE(&storage->user->storages, storage); | |||
storage->v.destroy(storage); | storage->v.destroy(storage); | |||
i_free(storage->last_internal_error); | i_free(storage->last_internal_error); | |||
i_free(storage->error_string); | i_free(storage->error_string); | |||
if (array_is_created(&storage->error_stack)) { | if (array_is_created(&storage->error_stack)) { | |||
i_assert(array_count(&storage->error_stack) == 0); | i_assert(array_count(&storage->error_stack) == 0); | |||
array_free(&storage->error_stack); | array_free(&storage->error_stack); | |||
} | } | |||
fs_unref(&storage->mailboxes_fs); | ||||
event_unref(&storage->event); | event_unref(&storage->event); | |||
*_storage = NULL; | *_storage = NULL; | |||
pool_unref(&storage->pool); | pool_unref(&storage->pool); | |||
mail_index_alloc_cache_destroy_unrefed(); | mail_index_alloc_cache_destroy_unrefed(); | |||
} | } | |||
void mail_storage_obj_ref(struct mail_storage *storage) | void mail_storage_obj_ref(struct mail_storage *storage) | |||
{ | { | |||
skipping to change at line 923 | skipping to change at line 948 | |||
static bool | static bool | |||
str_contains_special_use(const char *str, const char *special_use) | str_contains_special_use(const char *str, const char *special_use) | |||
{ | { | |||
const char *const *uses; | const char *const *uses; | |||
i_assert(special_use != NULL); | i_assert(special_use != NULL); | |||
if (*special_use != '\\') | if (*special_use != '\\') | |||
return FALSE; | return FALSE; | |||
uses = t_strsplit_spaces(str, " "); | bool ret; | |||
return str_array_icase_find(uses, special_use); | T_BEGIN { | |||
uses = t_strsplit_spaces(str, " "); | ||||
ret = str_array_icase_find(uses, special_use); | ||||
} T_END; | ||||
return ret; | ||||
} | } | |||
static int | static int | |||
namespace_find_special_use(struct mail_namespace *ns, const char *special_use, | namespace_find_special_use(struct mail_namespace *ns, const char *special_use, | |||
const char **vname_r, enum mail_error *error_code_r) | const char **vname_r, enum mail_error *error_code_r) | |||
{ | { | |||
struct mailbox_list *list = ns->list; | struct mailbox_list *list = ns->list; | |||
struct mailbox_list_iterate_context *ctx; | struct mailbox_list_iterate_context *ctx; | |||
const struct mailbox_info *info; | const struct mailbox_info *info; | |||
int ret = 0; | int ret = 0; | |||
skipping to change at line 1207 | skipping to change at line 1236 | |||
if (vname[0] == '\0') { | if (vname[0] == '\0') { | |||
/* "namespace/" isn't a valid mailbox name. */ | /* "namespace/" isn't a valid mailbox name. */ | |||
*error_r = "Ends with hierarchy separator"; | *error_r = "Ends with hierarchy separator"; | |||
return FALSE; | return FALSE; | |||
} | } | |||
} | } | |||
*vnamep = vname; | *vnamep = vname; | |||
return TRUE; | return TRUE; | |||
} | } | |||
int mailbox_verify_name(struct mailbox *box) | static int mailbox_verify_name_int(struct mailbox *box) | |||
{ | { | |||
struct mail_namespace *ns = box->list->ns; | struct mail_namespace *ns = box->list->ns; | |||
const char *error, *vname = box->vname; | const char *error, *vname = box->vname; | |||
char list_sep, ns_sep; | char list_sep, ns_sep; | |||
if (box->inbox_user) { | if (box->inbox_user) { | |||
/* this is INBOX - don't bother with further checks */ | /* this is INBOX - don't bother with further checks */ | |||
return 0; | return 0; | |||
} | } | |||
skipping to change at line 1263 | skipping to change at line 1292 | |||
if (!mailbox_name_verify_extra_separators(vname, ns_sep, &error) || | if (!mailbox_name_verify_extra_separators(vname, ns_sep, &error) || | |||
!mailbox_list_is_valid_name(box->list, box->name, &error)) { | !mailbox_list_is_valid_name(box->list, box->name, &error)) { | |||
mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS, | mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS, | |||
t_strdup_printf("Invalid mailbox name: %s", error)); | t_strdup_printf("Invalid mailbox name: %s", error)); | |||
return -1; | return -1; | |||
} | } | |||
return 0; | return 0; | |||
} | } | |||
static int mailbox_verify_existing_name(struct mailbox *box) | int mailbox_verify_name(struct mailbox *box) | |||
{ | ||||
int ret; | ||||
T_BEGIN { | ||||
ret = mailbox_verify_name_int(box); | ||||
} T_END; | ||||
return ret; | ||||
} | ||||
static int mailbox_verify_existing_name_int(struct mailbox *box) | ||||
{ | { | |||
const char *path; | const char *path; | |||
if (box->opened) | if (box->opened) | |||
return 0; | return 0; | |||
if (mailbox_verify_name(box) < 0) | if (mailbox_verify_name(box) < 0) | |||
return -1; | return -1; | |||
/* Make sure box->_path is set, so mailbox_get_path() works from | /* Make sure box->_path is set, so mailbox_get_path() works from | |||
skipping to change at line 1291 | skipping to change at line 1329 | |||
if (mailbox_autocreate(box) < 0) | if (mailbox_autocreate(box) < 0) | |||
return -1; | return -1; | |||
mailbox_close(box); | mailbox_close(box); | |||
if (mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_MAILBOX, | if (mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_MAILBOX, | |||
&path) < 0) | &path) < 0) | |||
return -1; | return -1; | |||
} | } | |||
return 0; | return 0; | |||
} | } | |||
static int mailbox_verify_existing_name(struct mailbox *box) | ||||
{ | ||||
int ret; | ||||
T_BEGIN { | ||||
ret = mailbox_verify_existing_name_int(box); | ||||
} T_END; | ||||
return ret; | ||||
} | ||||
static bool mailbox_name_has_control_chars(const char *name) | static bool mailbox_name_has_control_chars(const char *name) | |||
{ | { | |||
const char *p; | const char *p; | |||
for (p = name; *p != '\0'; p++) { | for (p = name; *p != '\0'; p++) { | |||
if ((unsigned char)*p < ' ') | if ((unsigned char)*p < ' ') | |||
return TRUE; | return TRUE; | |||
} | } | |||
return FALSE; | return FALSE; | |||
} | } | |||
skipping to change at line 1709 | skipping to change at line 1756 | |||
/* Avoid race conditions by keeping mailbox list locked during changes. | /* Avoid race conditions by keeping mailbox list locked during changes. | |||
This especially fixes a race during INBOX creation with LAYOUT=index | This especially fixes a race during INBOX creation with LAYOUT=index | |||
because it scans for missing mailboxes if INBOX doesn't exist. The | because it scans for missing mailboxes if INBOX doesn't exist. The | |||
second process's scan can find a half-created INBOX and add it, | second process's scan can find a half-created INBOX and add it, | |||
causing the first process to become confused. */ | causing the first process to become confused. */ | |||
if (mailbox_list_lock(box->list) < 0) { | if (mailbox_list_lock(box->list) < 0) { | |||
mail_storage_copy_list_error(box->storage, box->list); | mail_storage_copy_list_error(box->storage, box->list); | |||
return -1; | return -1; | |||
} | } | |||
box->creating = TRUE; | box->creating = TRUE; | |||
ret = box->v.create_box(box, update, directory); | T_BEGIN { | |||
ret = box->v.create_box(box, update, directory); | ||||
} T_END; | ||||
box->creating = FALSE; | box->creating = FALSE; | |||
mailbox_list_unlock(box->list); | mailbox_list_unlock(box->list); | |||
if (ret == 0) { | if (ret == 0) { | |||
box->list->guid_cache_updated = TRUE; | box->list->guid_cache_updated = TRUE; | |||
if (!box->inbox_any) | if (!box->inbox_any) T_BEGIN { | |||
mailbox_copy_cache_decisions_from_inbox(box); | mailbox_copy_cache_decisions_from_inbox(box); | |||
} T_END; | ||||
} else if (box->opened) { | } else if (box->opened) { | |||
/* Creation failed after (partially) opening the mailbox. | /* Creation failed after (partially) opening the mailbox. | |||
It may not be in a valid state, so close it. */ | It may not be in a valid state, so close it. */ | |||
mail_storage_last_error_push(box->storage); | mail_storage_last_error_push(box->storage); | |||
mailbox_close(box); | mailbox_close(box); | |||
mail_storage_last_error_pop(box->storage); | mail_storage_last_error_pop(box->storage); | |||
} | } | |||
return ret; | return ret; | |||
} | } | |||
skipping to change at line 1750 | skipping to change at line 1800 | |||
return ret; | return ret; | |||
} | } | |||
int mailbox_mark_index_deleted(struct mailbox *box, bool del) | int mailbox_mark_index_deleted(struct mailbox *box, bool del) | |||
{ | { | |||
struct mail_index_transaction *trans; | struct mail_index_transaction *trans; | |||
enum mail_index_transaction_flags trans_flags = 0; | enum mail_index_transaction_flags trans_flags = 0; | |||
enum mailbox_flags old_flag; | enum mailbox_flags old_flag; | |||
int ret; | int ret; | |||
e_debug(box->event, "Attempting to %s mailbox", del ? | ||||
"delete" : "undelete"); | ||||
if (box->marked_deleted && del) { | if (box->marked_deleted && del) { | |||
/* we already marked it deleted. this allows plugins to | /* we already marked it deleted. this allows plugins to | |||
"lock" the deletion earlier. */ | "lock" the deletion earlier. */ | |||
return 0; | return 0; | |||
} | } | |||
old_flag = box->flags & MAILBOX_FLAG_OPEN_DELETED; | old_flag = box->flags & MAILBOX_FLAG_OPEN_DELETED; | |||
box->flags |= MAILBOX_FLAG_OPEN_DELETED; | box->flags |= MAILBOX_FLAG_OPEN_DELETED; | |||
ret = mailbox_open(box); | ret = mailbox_open(box); | |||
box->flags = (box->flags & ENUM_NEGATE(MAILBOX_FLAG_OPEN_DELETED)) | old_ flag; | box->flags = (box->flags & ENUM_NEGATE(MAILBOX_FLAG_OPEN_DELETED)) | old_ flag; | |||
skipping to change at line 1797 | skipping to change at line 1850 | |||
return 0; | return 0; | |||
} | } | |||
static void mailbox_close_reset_path(struct mailbox *box) | static void mailbox_close_reset_path(struct mailbox *box) | |||
{ | { | |||
i_zero(&box->_perm); | i_zero(&box->_perm); | |||
box->_path = NULL; | box->_path = NULL; | |||
box->_index_path = NULL; | box->_index_path = NULL; | |||
} | } | |||
int mailbox_delete(struct mailbox *box) | static int mailbox_delete_real(struct mailbox *box) | |||
{ | { | |||
bool list_locked; | bool list_locked; | |||
int ret; | int ret; | |||
if (*box->name == '\0') { | if (*box->name == '\0') { | |||
mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS, | mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS, | |||
"Storage root can't be deleted"); | "Storage root can't be deleted"); | |||
return -1; | return -1; | |||
} | } | |||
skipping to change at line 1842 | skipping to change at line 1895 | |||
box->deleting = FALSE; | box->deleting = FALSE; | |||
mailbox_close(box); | mailbox_close(box); | |||
/* if mailbox is reopened, its path may be different with | /* if mailbox is reopened, its path may be different with | |||
LAYOUT=index */ | LAYOUT=index */ | |||
mailbox_close_reset_path(box); | mailbox_close_reset_path(box); | |||
return ret; | return ret; | |||
} | } | |||
int mailbox_delete(struct mailbox *box) | ||||
{ | ||||
int ret; | ||||
T_BEGIN { | ||||
ret = mailbox_delete_real(box); | ||||
} T_END; | ||||
return ret; | ||||
} | ||||
int mailbox_delete_empty(struct mailbox *box) | int mailbox_delete_empty(struct mailbox *box) | |||
{ | { | |||
int ret; | int ret; | |||
/* FIXME: should be a parameter to delete(), but since it changes API | /* FIXME: should be a parameter to delete(), but since it changes API | |||
don't do it for now */ | don't do it for now */ | |||
box->deleting_must_be_empty = TRUE; | box->deleting_must_be_empty = TRUE; | |||
ret = mailbox_delete(box); | ret = mailbox_delete(box); | |||
box->deleting_must_be_empty = FALSE; | box->deleting_must_be_empty = FALSE; | |||
return ret; | return ret; | |||
skipping to change at line 1946 | skipping to change at line 2008 | |||
} | } | |||
/* something went bad */ | /* something went bad */ | |||
if (mailbox_list_iter_deinit(&iter) < 0) { | if (mailbox_list_iter_deinit(&iter) < 0) { | |||
mail_storage_copy_list_error(src->storage, src->list); | mail_storage_copy_list_error(src->storage, src->list); | |||
ret = -1; | ret = -1; | |||
} | } | |||
return ret; | return ret; | |||
} | } | |||
int mailbox_rename(struct mailbox *src, struct mailbox *dest) | static int mailbox_rename_real(struct mailbox *src, struct mailbox *dest) | |||
{ | { | |||
const char *error = NULL; | const char *error = NULL; | |||
/* Check only name validity, \Noselect don't necessarily exist. */ | /* Check only name validity, \Noselect don't necessarily exist. */ | |||
if (mailbox_verify_name(src) < 0) | if (mailbox_verify_name(src) < 0) | |||
return -1; | return -1; | |||
if (*src->name == '\0') { | if (*src->name == '\0') { | |||
mail_storage_set_error(src->storage, MAIL_ERROR_PARAMS, | mail_storage_set_error(src->storage, MAIL_ERROR_PARAMS, | |||
"Can't rename mailbox root"); | "Can't rename mailbox root"); | |||
return -1; | return -1; | |||
skipping to change at line 2006 | skipping to change at line 2068 | |||
} | } | |||
int ret = src->v.rename_box(src, dest); | int ret = src->v.rename_box(src, dest); | |||
mailbox_list_unlock(dest->list); | mailbox_list_unlock(dest->list); | |||
if (ret < 0) | if (ret < 0) | |||
return -1; | return -1; | |||
src->list->guid_cache_invalidated = TRUE; | src->list->guid_cache_invalidated = TRUE; | |||
dest->list->guid_cache_invalidated = TRUE; | dest->list->guid_cache_invalidated = TRUE; | |||
return 0; | return 0; | |||
} | } | |||
int mailbox_rename(struct mailbox *src, struct mailbox *dest) | ||||
{ | ||||
int ret; | ||||
T_BEGIN { | ||||
ret = mailbox_rename_real(src, dest); | ||||
} T_END; | ||||
return ret; | ||||
} | ||||
int mailbox_set_subscribed(struct mailbox *box, bool set) | int mailbox_set_subscribed(struct mailbox *box, bool set) | |||
{ | { | |||
if (mailbox_verify_name(box) < 0) | if (mailbox_verify_name(box) < 0) | |||
return -1; | return -1; | |||
if (mailbox_list_iter_subscriptions_refresh(box->list) < 0) { | if (mailbox_list_iter_subscriptions_refresh(box->list) < 0) { | |||
mail_storage_copy_list_error(box->storage, box->list); | mail_storage_copy_list_error(box->storage, box->list); | |||
return -1; | return -1; | |||
} | } | |||
if (mailbox_is_subscribed(box) == set) | if (mailbox_is_subscribed(box) == set) | |||
return 0; | return 0; | |||
skipping to change at line 2753 | skipping to change at line 2824 | |||
return ret; | return ret; | |||
} | } | |||
int mailbox_copy(struct mail_save_context **_ctx, struct mail *mail) | int mailbox_copy(struct mail_save_context **_ctx, struct mail *mail) | |||
{ | { | |||
struct mail_save_context *ctx = *_ctx; | struct mail_save_context *ctx = *_ctx; | |||
i_assert(!ctx->saving); | i_assert(!ctx->saving); | |||
i_assert(!ctx->moving); | i_assert(!ctx->moving); | |||
return mailbox_copy_int(_ctx, mail); | int ret; | |||
T_BEGIN { | ||||
ret = mailbox_copy_int(_ctx, mail); | ||||
} T_END; | ||||
return ret; | ||||
} | } | |||
int mailbox_move(struct mail_save_context **_ctx, struct mail *mail) | int mailbox_move(struct mail_save_context **_ctx, struct mail *mail) | |||
{ | { | |||
struct mail_save_context *ctx = *_ctx; | struct mail_save_context *ctx = *_ctx; | |||
int ret; | int ret; | |||
i_assert(!ctx->saving); | i_assert(!ctx->saving); | |||
i_assert(!ctx->moving); | i_assert(!ctx->moving); | |||
ctx->moving = TRUE; | ctx->moving = TRUE; | |||
if ((ret = mailbox_copy_int(_ctx, mail)) == 0) | T_BEGIN { | |||
mail_expunge(mail); | if ((ret = mailbox_copy_int(_ctx, mail)) == 0) | |||
mail_expunge(mail); | ||||
} T_END; | ||||
ctx->moving = FALSE; | ctx->moving = FALSE; | |||
return ret; | return ret; | |||
} | } | |||
int mailbox_save_using_mail(struct mail_save_context **_ctx, struct mail *mail) | int mailbox_save_using_mail(struct mail_save_context **_ctx, struct mail *mail) | |||
{ | { | |||
struct mail_save_context *ctx = *_ctx; | struct mail_save_context *ctx = *_ctx; | |||
i_assert(!ctx->saving); | i_assert(!ctx->saving); | |||
i_assert(!ctx->moving); | i_assert(!ctx->moving); | |||
skipping to change at line 3120 | skipping to change at line 3198 | |||
} | } | |||
*lock_r = file_lock_from_dotlock(&dotlock); | *lock_r = file_lock_from_dotlock(&dotlock); | |||
return 1; | return 1; | |||
} | } | |||
int mail_storage_lock_create(const char *lock_path, | int mail_storage_lock_create(const char *lock_path, | |||
const struct file_create_settings *lock_set, | const struct file_create_settings *lock_set, | |||
const struct mail_storage_settings *mail_set, | const struct mail_storage_settings *mail_set, | |||
struct file_lock **lock_r, const char **error_r) | struct file_lock **lock_r, const char **error_r) | |||
{ | { | |||
struct file_create_settings lock_set_new = *lock_set; | ||||
bool created; | bool created; | |||
if (lock_set->lock_method == FILE_LOCK_METHOD_DOTLOCK) | if (lock_set->lock_settings.lock_method == FILE_LOCK_METHOD_DOTLOCK) | |||
return mail_storage_dotlock_create(lock_path, lock_set, mail_set, lock_r, error_r); | return mail_storage_dotlock_create(lock_path, lock_set, mail_set, lock_r, error_r); | |||
if (file_create_locked(lock_path, lock_set, lock_r, | lock_set_new.lock_settings.close_on_free = TRUE; | |||
lock_set_new.lock_settings.unlink_on_free = TRUE; | ||||
if (file_create_locked(lock_path, &lock_set_new, lock_r, | ||||
&created, error_r) == -1) { | &created, error_r) == -1) { | |||
*error_r = t_strdup_printf("file_create_locked(%s) failed: %s", | *error_r = t_strdup_printf("file_create_locked(%s) failed: %s", | |||
lock_path, *error_r); | lock_path, *error_r); | |||
return errno == EAGAIN ? 0 : -1; | return errno == EAGAIN ? 0 : -1; | |||
} | } | |||
file_lock_set_close_on_free(*lock_r, TRUE); | ||||
file_lock_set_unlink_on_free(*lock_r, TRUE); | ||||
return 1; | return 1; | |||
} | } | |||
int mailbox_lock_file_create(struct mailbox *box, const char *lock_fname, | int mailbox_lock_file_create(struct mailbox *box, const char *lock_fname, | |||
unsigned int lock_secs, struct file_lock **lock_r, | unsigned int lock_secs, struct file_lock **lock_r, | |||
const char **error_r) | const char **error_r) | |||
{ | { | |||
const struct mailbox_permissions *perm; | const struct mailbox_permissions *perm; | |||
struct file_create_settings set; | struct file_create_settings set; | |||
const char *lock_path; | const char *lock_path; | |||
perm = mailbox_get_permissions(box); | perm = mailbox_get_permissions(box); | |||
i_zero(&set); | i_zero(&set); | |||
set.lock_timeout_secs = | set.lock_timeout_secs = | |||
mail_storage_get_lock_timeout(box->storage, lock_secs); | mail_storage_get_lock_timeout(box->storage, lock_secs); | |||
set.lock_method = box->storage->set->parsed_lock_method; | set.lock_settings.lock_method = box->storage->set->parsed_lock_method; | |||
set.mode = perm->file_create_mode; | set.mode = perm->file_create_mode; | |||
set.gid = perm->file_create_gid; | set.gid = perm->file_create_gid; | |||
set.gid_origin = perm->file_create_gid_origin; | set.gid_origin = perm->file_create_gid_origin; | |||
if (box->list->set.volatile_dir == NULL) | if (box->list->set.volatile_dir == NULL) | |||
lock_path = t_strdup_printf("%s/%s", box->index->dir, lock_fname) ; | lock_path = t_strdup_printf("%s/%s", box->index->dir, lock_fname) ; | |||
else { | else { | |||
unsigned char box_name_sha1[SHA1_RESULTLEN]; | unsigned char box_name_sha1[SHA1_RESULTLEN]; | |||
string_t *str = t_str_new(128); | string_t *str = t_str_new(128); | |||
End of changes. 24 change blocks. | ||||
16 lines changed or deleted | 96 lines changed or added |