From: Timo Sirainen Date: Thu, 26 Feb 2009 18:54:30 +0000 (-0500) Subject: mbox: Give better error messages if dotlocking fails. X-Git-Tag: 1.2.beta2~48 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=62ccd8152d2f0142ab3301da4f5270b9d4f06718;p=thirdparty%2Fdovecot%2Fcore.git mbox: Give better error messages if dotlocking fails. --HG-- branch : HEAD --- diff --git a/src/lib-storage/index/mbox/mbox-lock.c b/src/lib-storage/index/mbox/mbox-lock.c index 1e8084497d..972df6ac9a 100644 --- a/src/lib-storage/index/mbox/mbox-lock.c +++ b/src/lib-storage/index/mbox/mbox-lock.c @@ -1,6 +1,7 @@ /* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */ #include "lib.h" +#include "eacces-error.h" #include "restrict-access.h" #include "nfs-workarounds.h" #include "mail-index-private.h" @@ -14,6 +15,7 @@ #include #include #include +#include #ifdef HAVE_FLOCK # include @@ -260,7 +262,7 @@ static int mbox_dotlock_privileged_op(struct mbox_mailbox *mbox, enum mbox_dotlock_op op) { const char *dir, *fname; - int ret = -1, orig_dir_fd; + int ret = -1, orig_dir_fd, orig_errno; orig_dir_fd = open(".", O_RDONLY); if (orig_dir_fd == -1) { @@ -310,23 +312,42 @@ static int mbox_dotlock_privileged_op(struct mbox_mailbox *mbox, ret = file_dotlock_create(set, fname, 0, &mbox->mbox_dotlock); if (ret > 0) mbox->mbox_used_privileges = TRUE; + else if (ret < 0 && errno == EACCES) { + const char *errmsg = + eacces_error_get_creating("file_dotlock_create", + fname); + mail_storage_set_critical(&mbox->storage->storage, + "%s", errmsg); + } else { + mbox_set_syscall_error(mbox, "file_dotlock_create()"); + } break; case MBOX_DOTLOCK_OP_UNLOCK: /* we're now privileged - avoid doing as much as possible */ ret = file_dotlock_delete(&mbox->mbox_dotlock); + if (ret < 0) + mbox_set_syscall_error(mbox, "file_dotlock_delete()"); mbox->mbox_used_privileges = FALSE; break; case MBOX_DOTLOCK_OP_TOUCH: if (!file_dotlock_is_locked(mbox->mbox_dotlock)) { - file_dotlock_delete(&mbox->mbox_dotlock); + if (file_dotlock_delete(&mbox->mbox_dotlock) < 0) { + mbox_set_syscall_error(mbox, + "file_dotlock_delete()"); + } mbox->mbox_used_privileges = TRUE; ret = -1; } else { ret = file_dotlock_touch(mbox->mbox_dotlock); + if (ret < 0) { + mbox_set_syscall_error(mbox, + "file_dotlock_touch()"); + } } break; } + orig_errno = errno; restrict_access_drop_priv_gid(); if (fchdir(orig_dir_fd) < 0) { @@ -334,9 +355,35 @@ static int mbox_dotlock_privileged_op(struct mbox_mailbox *mbox, "fchdir() failed: %m"); } (void)close(orig_dir_fd); + errno = orig_errno; return ret; } +static void +mbox_dotlock_log_eacces_error(struct mbox_mailbox *mbox, const char *path) +{ + const char *dir, *errmsg; + struct stat st; + const struct group *group; + int orig_errno = errno; + + errmsg = eacces_error_get_creating("file_dotlock_create", path); + dir = strrchr(path, '/'); + dir = dir == NULL ? "." : t_strdup_until(path, dir); + if (stat(dir, &st) == 0 && + (st.st_mode & 02) == 0 && /* not world-writable */ + (st.st_mode & 020) != 0) { /* group-writable */ + group = getgrgid(st.st_gid); + mail_storage_set_critical(&mbox->storage->storage, + "%s (set mail_privileged_group=%s)", errmsg, + group == NULL ? dec2str(st.st_gid) : group->gr_name); + } else { + mail_storage_set_critical(&mbox->storage->storage, + "%s (nonstandard permissions in %s)", errmsg, path); + } + errno = orig_errno; +} + static int mbox_lock_dotlock_int(struct mbox_lock_context *ctx, int lock_type, bool try) { @@ -348,18 +395,17 @@ mbox_lock_dotlock_int(struct mbox_lock_context *ctx, int lock_type, bool try) if (!mbox->mbox_dotlocked) return 1; - if (!mbox->mbox_used_privileges) - ret = file_dotlock_delete(&mbox->mbox_dotlock); - else { + if (!mbox->mbox_used_privileges) { + if (file_dotlock_delete(&mbox->mbox_dotlock) <= 0) { + mbox_set_syscall_error(mbox, + "file_dotlock_delete()"); + } + } else { ctx->using_privileges = TRUE; - ret = mbox_dotlock_privileged_op(mbox, NULL, - MBOX_DOTLOCK_OP_UNLOCK); + (void)mbox_dotlock_privileged_op(mbox, NULL, + MBOX_DOTLOCK_OP_UNLOCK); ctx->using_privileges = FALSE; } - if (ret <= 0) { - mbox_set_syscall_error(mbox, "file_dotlock_delete()"); - ret = -1; - } mbox->mbox_dotlocked = FALSE; return 1; } @@ -380,18 +426,21 @@ mbox_lock_dotlock_int(struct mbox_lock_context *ctx, int lock_type, bool try) set.context = ctx; ret = file_dotlock_create(&set, mbox->path, 0, &mbox->mbox_dotlock); - if (ret < 0 && errno == EACCES && restrict_access_have_priv_gid() && - mbox->mbox_privileged_locking) { + if (ret >= 0) { + /* success / timeout */ + } else if (errno == EACCES && restrict_access_have_priv_gid() && + mbox->mbox_privileged_locking) { /* try again, this time with extra privileges */ ret = mbox_dotlock_privileged_op(mbox, &set, MBOX_DOTLOCK_OP_LOCK); - } + } else if (errno == EACCES) + mbox_dotlock_log_eacces_error(mbox, mbox->path); + else + mbox_set_syscall_error(mbox, "file_dotlock_create()"); if (ret < 0) { if ((ENOSPACE(errno) || errno == EACCES) && try) return 1; - - mbox_set_syscall_error(mbox, "file_lock_dotlock()"); return -1; } if (ret == 0) {