Mercurial > dovecot > original-hg > dovecot-1.2
changeset 8783:f3ce7c7c0b58 HEAD
mbox: Give better error messages if dotlocking fails.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 26 Feb 2009 13:54:30 -0500 |
parents | e5cc81734221 |
children | 89e4d5da5ba7 |
files | src/lib-storage/index/mbox/mbox-lock.c |
diffstat | 1 files changed, 65 insertions(+), 16 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-storage/index/mbox/mbox-lock.c Thu Feb 26 11:24:21 2009 -0500 +++ b/src/lib-storage/index/mbox/mbox-lock.c Thu Feb 26 13:54:30 2009 -0500 @@ -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 <unistd.h> #include <fcntl.h> #include <sys/stat.h> +#include <grp.h> #ifdef HAVE_FLOCK # include <sys/file.h> @@ -260,7 +262,7 @@ 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 @@ 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 @@ "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 @@ 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 @@ 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) {