bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "lib.h"
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen#include "eacces-error.h"
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen#include "restrict-access.h"
181c1aff950e6f8e0556f8974e79d0747845ac0fTimo Sirainen#include "nfs-workarounds.h"
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen#include "ipwd.h"
6dc4af35c045e10609b13fe80f9cf33f3a06c3ceTimo Sirainen#include "mail-index-private.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "mbox-storage.h"
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen#include "istream-raw-mbox.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "mbox-file.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "mbox-lock.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include <time.h>
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include <unistd.h>
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include <fcntl.h>
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include <sys/stat.h>
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#ifdef HAVE_FLOCK
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen# include <sys/file.h>
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#endif
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen/* 0.1 .. 0.2msec */
62461eb609e1d852e027cf4e07d30d51288678a2Aki Tuomi#define LOCK_RANDOM_USLEEP_TIME (100000 + (unsigned int)i_rand() % 100000)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenenum mbox_lock_type {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen MBOX_LOCK_DOTLOCK,
9d6dec796909384293006e4289436579089d88d5Timo Sirainen MBOX_LOCK_DOTLOCK_TRY,
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen MBOX_LOCK_FCNTL,
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen MBOX_LOCK_FLOCK,
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen MBOX_LOCK_LOCKF,
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen MBOX_LOCK_COUNT
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen};
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainenenum mbox_dotlock_op {
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen MBOX_DOTLOCK_OP_LOCK,
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen MBOX_DOTLOCK_OP_UNLOCK,
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen MBOX_DOTLOCK_OP_TOUCH
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen};
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstruct mbox_lock_context {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen struct mbox_mailbox *mbox;
8e047750fa23706e883b14584d0ed7c4bfde3892Timo Sirainen bool locked_status[MBOX_LOCK_COUNT];
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen bool checked_file;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen int lock_type;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen bool dotlock_last_stale;
181c1aff950e6f8e0556f8974e79d0747845ac0fTimo Sirainen bool fcntl_locked;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen bool using_privileges;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen};
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenstruct mbox_lock_data {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen enum mbox_lock_type type;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen const char *name;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen int (*func)(struct mbox_lock_context *ctx, int lock_type,
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen time_t max_wait_time);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen};
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstatic int mbox_lock_dotlock(struct mbox_lock_context *ctx, int lock_type,
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen time_t max_wait_time);
9d6dec796909384293006e4289436579089d88d5Timo Sirainenstatic int mbox_lock_dotlock_try(struct mbox_lock_context *ctx, int lock_type,
9d6dec796909384293006e4289436579089d88d5Timo Sirainen time_t max_wait_time);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstatic int mbox_lock_fcntl(struct mbox_lock_context *ctx, int lock_type,
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen time_t max_wait_time);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen#ifdef HAVE_FLOCK
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstatic int mbox_lock_flock(struct mbox_lock_context *ctx, int lock_type,
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen time_t max_wait_time);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen#else
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen# define mbox_lock_flock NULL
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen#endif
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen#ifdef HAVE_LOCKF
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstatic int mbox_lock_lockf(struct mbox_lock_context *ctx, int lock_type,
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen time_t max_wait_time);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen#else
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen# define mbox_lock_lockf NULL
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen#endif
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
ab0d9eecd85f74acae18fe88529302e0776cc500Timo Sirainenstatic struct mbox_lock_data lock_data[] = {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen { MBOX_LOCK_DOTLOCK, "dotlock", mbox_lock_dotlock },
9d6dec796909384293006e4289436579089d88d5Timo Sirainen { MBOX_LOCK_DOTLOCK_TRY, "dotlock_try", mbox_lock_dotlock_try },
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen { MBOX_LOCK_FCNTL, "fcntl", mbox_lock_fcntl },
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen { MBOX_LOCK_FLOCK, "flock", mbox_lock_flock },
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen { MBOX_LOCK_LOCKF, "lockf", mbox_lock_lockf },
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen { 0, NULL, NULL }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen};
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainenstatic int ATTR_NOWARN_UNUSED_RESULT
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainenmbox_lock_list(struct mbox_lock_context *ctx, int lock_type,
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen time_t max_wait_time, int idx);
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainenstatic int ATTR_NOWARN_UNUSED_RESULT
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainenmbox_unlock_files(struct mbox_lock_context *ctx);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenstatic void mbox_read_lock_methods(const char *str, const char *env,
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen enum mbox_lock_type *locks)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen enum mbox_lock_type type;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen const char *const *lock;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen int i, dest;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen for (lock = t_strsplit(str, " "), dest = 0; *lock != NULL; lock++) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen for (type = 0; lock_data[type].name != NULL; type++) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (strcasecmp(*lock, lock_data[type].name) == 0) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen type = lock_data[type].type;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen break;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (lock_data[type].name == NULL)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen i_fatal("%s: Invalid value %s", env, *lock);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (lock_data[type].func == NULL) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen i_fatal("%s: Support for lock type %s "
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen "not compiled into binary", env, *lock);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen for (i = 0; i < dest; i++) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (locks[i] == type)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen i_fatal("%s: Duplicated value %s", env, *lock);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen /* @UNSAFE */
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen locks[dest++] = type;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen locks[dest] = (enum mbox_lock_type)-1;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen}
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenstatic void mbox_init_lock_settings(struct mbox_storage *storage)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen{
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen enum mbox_lock_type read_locks[MBOX_LOCK_COUNT+1];
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen enum mbox_lock_type write_locks[MBOX_LOCK_COUNT+1];
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen int r, w;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen mbox_read_lock_methods(storage->set->mbox_read_locks,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen "mbox_read_locks", read_locks);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen mbox_read_lock_methods(storage->set->mbox_write_locks,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen "mbox_write_locks", write_locks);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen /* check that read/write list orders match. write_locks must contain
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen at least read_locks and possibly more. */
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen for (r = w = 0; write_locks[w] != (enum mbox_lock_type)-1; w++) {
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen if (read_locks[r] == (enum mbox_lock_type)-1)
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen break;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen if (read_locks[r] == write_locks[w])
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen r++;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen }
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen if (read_locks[r] != (enum mbox_lock_type)-1) {
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen i_fatal("mbox read/write lock list settings are invalid. "
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen "Lock ordering must be the same with both, "
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen "and write locks must contain all read locks "
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen "(and possibly more)");
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen }
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen storage->read_locks = p_new(storage->storage.pool,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen enum mbox_lock_type, MBOX_LOCK_COUNT+1);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen memcpy(storage->read_locks, read_locks,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen sizeof(*storage->read_locks) * (MBOX_LOCK_COUNT+1));
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen storage->write_locks = p_new(storage->storage.pool,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen enum mbox_lock_type, MBOX_LOCK_COUNT+1);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen memcpy(storage->write_locks, write_locks,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen sizeof(*storage->write_locks) * (MBOX_LOCK_COUNT+1));
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen storage->lock_settings_initialized = TRUE;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstatic int mbox_file_open_latest(struct mbox_lock_context *ctx, int lock_type)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen{
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen struct mbox_mailbox *mbox = ctx->mbox;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen struct stat st;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (ctx->checked_file || lock_type == F_UNLCK)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return 0;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (mbox->mbox_fd != -1) {
08ea8b302b62bc688f6b34f89f674e08eda7828cTimo Sirainen /* we could flush NFS file handle cache here if we wanted to
08ea8b302b62bc688f6b34f89f674e08eda7828cTimo Sirainen be sure that the file is latest, but mbox files get rarely
08ea8b302b62bc688f6b34f89f674e08eda7828cTimo Sirainen deleted and the flushing might cause errors (e.g. EBUSY for
08ea8b302b62bc688f6b34f89f674e08eda7828cTimo Sirainen trying to flush a /var/mail mountpoint) */
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen if (nfs_safe_stat(mailbox_get_path(&mbox->box), &st) < 0) {
145ecefd208f5d7f6a52cb326a85f28d2154e217Timo Sirainen if (errno == ENOENT)
d22301419109ed4a38351715e6760011421dadecTimo Sirainen mailbox_set_deleted(&mbox->box);
145ecefd208f5d7f6a52cb326a85f28d2154e217Timo Sirainen else
145ecefd208f5d7f6a52cb326a85f28d2154e217Timo Sirainen mbox_set_syscall_error(mbox, "stat()");
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return -1;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (st.st_ino != mbox->mbox_ino ||
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen !CMP_DEV_T(st.st_dev, mbox->mbox_dev))
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mbox_file_close(mbox);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (mbox->mbox_fd == -1) {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (mbox_file_open(mbox) < 0)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return -1;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen ctx->checked_file = TRUE;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return 0;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenstatic bool dotlock_callback(unsigned int secs_left, bool stale, void *context)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen{
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen struct mbox_lock_context *ctx = context;
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen enum mbox_lock_type *lock_types;
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen int i;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen if (ctx->using_privileges)
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen restrict_access_drop_priv_gid();
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (stale && !ctx->dotlock_last_stale) {
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen /* get next index we wish to try locking. it's the one after
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen dotlocking. */
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen lock_types = ctx->lock_type == F_WRLCK ||
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen (ctx->lock_type == F_UNLCK &&
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen ctx->mbox->mbox_lock_type == F_WRLCK) ?
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ctx->mbox->storage->write_locks :
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ctx->mbox->storage->read_locks;
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen for (i = 0; lock_types[i] != (enum mbox_lock_type)-1; i++) {
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen if (lock_types[i] == MBOX_LOCK_DOTLOCK)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen break;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen if (lock_types[i] != (enum mbox_lock_type)-1 &&
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen lock_types[i+1] != (enum mbox_lock_type)-1) {
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen i++;
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen if (mbox_lock_list(ctx, ctx->lock_type, 0, i) <= 0) {
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen /* we couldn't get fd lock -
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen it's really locked */
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen ctx->dotlock_last_stale = TRUE;
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen return FALSE;
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen }
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen mbox_lock_list(ctx, F_UNLCK, 0, i);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen ctx->dotlock_last_stale = stale;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen index_storage_lock_notify(&ctx->mbox->box, stale ?
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen MAILBOX_LOCK_NOTIFY_MAILBOX_OVERRIDE :
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen MAILBOX_LOCK_NOTIFY_MAILBOX_ABORT,
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen secs_left);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen if (ctx->using_privileges) {
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen if (restrict_access_use_priv_gid() < 0) {
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen /* shouldn't get here */
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen return FALSE;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen }
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return TRUE;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainenstatic int ATTR_NULL(2) ATTR_NOWARN_UNUSED_RESULT
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainenmbox_dotlock_privileged_op(struct mbox_mailbox *mbox,
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen struct dotlock_settings *set,
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen enum mbox_dotlock_op op)
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen{
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen const char *box_path, *dir, *fname;
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen int ret = -1, orig_dir_fd, orig_errno;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen orig_dir_fd = open(".", O_RDONLY);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen if (orig_dir_fd == -1) {
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(&mbox->box, "open(.) failed: %m");
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen return -1;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen }
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen /* allow dotlocks to be created only for files we can read while we're
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen unprivileged. to make sure there are no race conditions we first
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen have to chdir to the mbox file's directory and then use relative
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen paths. unless this is done, users could:
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen - create *.lock files to any directory writable by the
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen privileged group
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen - DoS other users by dotlocking their mailboxes infinitely
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen */
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen box_path = mailbox_get_path(&mbox->box);
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen fname = strrchr(box_path, '/');
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen if (fname == NULL) {
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen /* already relative */
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen fname = box_path;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen } else {
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen dir = t_strdup_until(box_path, fname);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen if (chdir(dir) < 0) {
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(&mbox->box,
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen "chdir(%s) failed: %m", dir);
4307c886579381dbb1897ea1388ae6978c96f560Timo Sirainen i_close_fd(&orig_dir_fd);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen return -1;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen }
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen fname++;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen }
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen if (op == MBOX_DOTLOCK_OP_LOCK) {
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen if (access(fname, R_OK) < 0) {
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(&mbox->box,
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen "access(%s) failed: %m", box_path);
af8b1248fed8529d26985460acdc4b1e4b7de675Timo Sirainen i_close_fd(&orig_dir_fd);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen return -1;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen }
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen }
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen if (restrict_access_use_priv_gid() < 0) {
4307c886579381dbb1897ea1388ae6978c96f560Timo Sirainen i_close_fd(&orig_dir_fd);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen return -1;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen }
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen switch (op) {
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen case MBOX_DOTLOCK_OP_LOCK:
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen /* we're now privileged - avoid doing as much as possible */
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen ret = file_dotlock_create(set, fname, 0, &mbox->mbox_dotlock);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen if (ret > 0)
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen mbox->mbox_used_privileges = TRUE;
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen else if (ret < 0 && errno == EACCES) {
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen const char *errmsg =
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen eacces_error_get_creating("file_dotlock_create",
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen fname);
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(&mbox->box, "%s", errmsg);
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen } else {
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen mbox_set_syscall_error(mbox, "file_dotlock_create()");
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen }
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen break;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen case MBOX_DOTLOCK_OP_UNLOCK:
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen /* we're now privileged - avoid doing as much as possible */
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen ret = file_dotlock_delete(&mbox->mbox_dotlock);
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen if (ret < 0)
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen mbox_set_syscall_error(mbox, "file_dotlock_delete()");
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen mbox->mbox_used_privileges = FALSE;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen break;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen case MBOX_DOTLOCK_OP_TOUCH:
0ff28df76775a0740faa4370ec72d5a6a97534bfTimo Sirainen ret = file_dotlock_touch(mbox->mbox_dotlock);
0ff28df76775a0740faa4370ec72d5a6a97534bfTimo Sirainen if (ret < 0)
0ff28df76775a0740faa4370ec72d5a6a97534bfTimo Sirainen mbox_set_syscall_error(mbox, "file_dotlock_touch()");
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen break;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen }
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen orig_errno = errno;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen restrict_access_drop_priv_gid();
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen if (fchdir(orig_dir_fd) < 0) {
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(&mbox->box, "fchdir() failed: %m");
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen }
4307c886579381dbb1897ea1388ae6978c96f560Timo Sirainen i_close_fd(&orig_dir_fd);
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen errno = orig_errno;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen return ret;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen}
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainenstatic void
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainenmbox_dotlock_log_eacces_error(struct mbox_mailbox *mbox, const char *path)
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen{
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen const char *dir, *errmsg, *name;
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen struct stat st;
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen struct group group;
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen int orig_errno = errno;
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen errmsg = eacces_error_get_creating("file_dotlock_create", path);
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen dir = strrchr(path, '/');
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen dir = dir == NULL ? "." : t_strdup_until(path, dir);
fbb324fedccfd1cff9fb41b64f715ca77e5d588fTimo Sirainen /* allow privileged locking for
fbb324fedccfd1cff9fb41b64f715ca77e5d588fTimo Sirainen a) user's own INBOX,
fbb324fedccfd1cff9fb41b64f715ca77e5d588fTimo Sirainen b) another user's shared INBOX, and
fbb324fedccfd1cff9fb41b64f715ca77e5d588fTimo Sirainen c) anything called INBOX (in inbox=no namespace) */
fbb324fedccfd1cff9fb41b64f715ca77e5d588fTimo Sirainen if (!mbox->box.inbox_any && strcmp(mbox->box.name, "INBOX") != 0) {
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(&mbox->box,
6fbd30cc189c5acb4cfce841e17ed0eeff5056f4Timo Sirainen "%s (not INBOX -> no privileged locking)", errmsg);
6fbd30cc189c5acb4cfce841e17ed0eeff5056f4Timo Sirainen } else if (!mbox->mbox_privileged_locking) {
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen dir = mailbox_list_get_root_forced(mbox->box.list,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen MAILBOX_LIST_PATH_TYPE_DIR);
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(&mbox->box,
dcf49e7ccf042982fde41ce256723f925fb9f1e4Timo Sirainen "%s (under root dir %s -> no privileged locking)",
dcf49e7ccf042982fde41ce256723f925fb9f1e4Timo Sirainen errmsg, dir);
dcf49e7ccf042982fde41ce256723f925fb9f1e4Timo Sirainen } else if (stat(dir, &st) == 0 &&
dcf49e7ccf042982fde41ce256723f925fb9f1e4Timo Sirainen (st.st_mode & 02) == 0 && /* not world-writable */
dcf49e7ccf042982fde41ce256723f925fb9f1e4Timo Sirainen (st.st_mode & 020) != 0) { /* group-writable */
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen if (i_getgrgid(st.st_gid, &group) <= 0)
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen name = dec2str(st.st_gid);
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen else
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen name = group.gr_name;
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(&mbox->box,
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen "%s (set mail_privileged_group=%s)", errmsg, name);
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen } else {
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(&mbox->box,
dcf49e7ccf042982fde41ce256723f925fb9f1e4Timo Sirainen "%s (nonstandard permissions in %s)", errmsg, dir);
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen }
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen errno = orig_errno;
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen}
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen
9d6dec796909384293006e4289436579089d88d5Timo Sirainenstatic int
9d6dec796909384293006e4289436579089d88d5Timo Sirainenmbox_lock_dotlock_int(struct mbox_lock_context *ctx, int lock_type, bool try)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen{
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen struct mbox_mailbox *mbox = ctx->mbox;
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen struct dotlock_settings set;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen int ret;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (lock_type == F_UNLCK) {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (!mbox->mbox_dotlocked)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return 1;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen if (!mbox->mbox_used_privileges) {
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen if (file_dotlock_delete(&mbox->mbox_dotlock) <= 0) {
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen mbox_set_syscall_error(mbox,
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen "file_dotlock_delete()");
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen }
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen } else {
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen ctx->using_privileges = TRUE;
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen mbox_dotlock_privileged_op(mbox, NULL,
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen MBOX_DOTLOCK_OP_UNLOCK);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen ctx->using_privileges = FALSE;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen }
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mbox->mbox_dotlocked = FALSE;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return 1;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (mbox->mbox_dotlocked)
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen return 1;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen
a9a3687619f38c862849f38db45506cc1d2f8f75Phil Carmody ctx->dotlock_last_stale = TRUE;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&set);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen set.use_excl_lock = mbox->storage->storage.set->dotlock_use_excl;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen set.nfs_flush = mbox->storage->storage.set->mail_nfs_storage;
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen set.timeout = mail_storage_get_lock_timeout(&mbox->storage->storage,
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen mbox->storage->set->mbox_lock_timeout);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen set.stale_timeout = mbox->storage->set->mbox_dotlock_change_timeout;
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen set.callback = dotlock_callback;
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen set.context = ctx;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen ret = file_dotlock_create(&set, mailbox_get_path(&mbox->box), 0,
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen &mbox->mbox_dotlock);
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen if (ret >= 0) {
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen /* success / timeout */
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen } else if (errno == EACCES && restrict_access_have_priv_gid() &&
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen mbox->mbox_privileged_locking) {
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen /* try again, this time with extra privileges */
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen ret = mbox_dotlock_privileged_op(mbox, &set,
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen MBOX_DOTLOCK_OP_LOCK);
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen } else if (errno == EACCES)
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen mbox_dotlock_log_eacces_error(mbox, mailbox_get_path(&mbox->box));
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen else
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen mbox_set_syscall_error(mbox, "file_dotlock_create()");
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (ret < 0) {
9d6dec796909384293006e4289436579089d88d5Timo Sirainen if ((ENOSPACE(errno) || errno == EACCES) && try)
9d6dec796909384293006e4289436579089d88d5Timo Sirainen return 1;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return -1;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (ret == 0) {
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen mail_storage_set_error(&mbox->storage->storage,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen MAIL_ERROR_TEMP, MAIL_ERRSTR_LOCK_TIMEOUT);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return 0;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mbox->mbox_dotlocked = TRUE;
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (mbox_file_open_latest(ctx, lock_type) < 0)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return -1;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return 1;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
9d6dec796909384293006e4289436579089d88d5Timo Sirainenstatic int mbox_lock_dotlock(struct mbox_lock_context *ctx, int lock_type,
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen time_t max_wait_time ATTR_UNUSED)
9d6dec796909384293006e4289436579089d88d5Timo Sirainen{
9d6dec796909384293006e4289436579089d88d5Timo Sirainen return mbox_lock_dotlock_int(ctx, lock_type, FALSE);
9d6dec796909384293006e4289436579089d88d5Timo Sirainen}
9d6dec796909384293006e4289436579089d88d5Timo Sirainen
9d6dec796909384293006e4289436579089d88d5Timo Sirainenstatic int mbox_lock_dotlock_try(struct mbox_lock_context *ctx, int lock_type,
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen time_t max_wait_time ATTR_UNUSED)
9d6dec796909384293006e4289436579089d88d5Timo Sirainen{
9d6dec796909384293006e4289436579089d88d5Timo Sirainen return mbox_lock_dotlock_int(ctx, lock_type, TRUE);
9d6dec796909384293006e4289436579089d88d5Timo Sirainen}
9d6dec796909384293006e4289436579089d88d5Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#ifdef HAVE_FLOCK
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstatic int mbox_lock_flock(struct mbox_lock_context *ctx, int lock_type,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen time_t max_wait_time)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainen time_t now;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen unsigned int next_alarm;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (mbox_file_open_latest(ctx, lock_type) < 0)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return -1;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (lock_type == F_UNLCK && ctx->mbox->mbox_fd == -1)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return 1;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (lock_type == F_WRLCK)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen lock_type = LOCK_EX;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen else if (lock_type == F_RDLCK)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen lock_type = LOCK_SH;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen else
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen lock_type = LOCK_UN;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen if (max_wait_time == 0) {
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen /* usually we're waiting here, but if we came from
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen mbox_lock_dotlock(), we just want to try locking */
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen lock_type |= LOCK_NB;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen } else {
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen now = time(NULL);
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen if (now >= max_wait_time)
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen alarm(1);
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen else
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen alarm(I_MIN(max_wait_time - now, 5));
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen }
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen while (flock(ctx->mbox->mbox_fd, lock_type) < 0) {
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen if (errno != EINTR) {
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen if (errno == EWOULDBLOCK && max_wait_time == 0) {
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen /* non-blocking lock trying failed */
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen return 0;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen }
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen alarm(0);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mbox_set_syscall_error(ctx->mbox, "flock()");
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return -1;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen now = time(NULL);
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen if (now >= max_wait_time) {
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen alarm(0);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return 0;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen /* notify locks once every 5 seconds.
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen try to use rounded values. */
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen next_alarm = (max_wait_time - now) % 5;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen if (next_alarm == 0)
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen next_alarm = 5;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen alarm(next_alarm);
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen index_storage_lock_notify(&ctx->mbox->box,
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen MAILBOX_LOCK_NOTIFY_MAILBOX_ABORT,
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen max_wait_time - now);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen alarm(0);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return 1;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#endif
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen#ifdef HAVE_LOCKF
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstatic int mbox_lock_lockf(struct mbox_lock_context *ctx, int lock_type,
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen time_t max_wait_time)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen{
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainen time_t now;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen unsigned int next_alarm;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (mbox_file_open_latest(ctx, lock_type) < 0)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return -1;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (lock_type == F_UNLCK && ctx->mbox->mbox_fd == -1)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return 1;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen if (lock_type == F_UNLCK)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen lock_type = F_ULOCK;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen else if (max_wait_time == 0) {
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen /* usually we're waiting here, but if we came from
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen mbox_lock_dotlock(), we just want to try locking */
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen lock_type = F_TLOCK;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen } else {
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen now = time(NULL);
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen if (now >= max_wait_time)
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen alarm(1);
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen else
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen alarm(I_MIN(max_wait_time - now, 5));
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen lock_type = F_LOCK;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen while (lockf(ctx->mbox->mbox_fd, lock_type, 0) < 0) {
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen if (errno != EINTR) {
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen if ((errno == EACCES || errno == EAGAIN) &&
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen max_wait_time == 0) {
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen /* non-blocking lock trying failed */
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen return 0;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen }
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen alarm(0);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mbox_set_syscall_error(ctx->mbox, "lockf()");
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen return -1;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen now = time(NULL);
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen if (now >= max_wait_time) {
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen alarm(0);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen return 0;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen /* notify locks once every 5 seconds.
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen try to use rounded values. */
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen next_alarm = (max_wait_time - now) % 5;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen if (next_alarm == 0)
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen next_alarm = 5;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen alarm(next_alarm);
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen index_storage_lock_notify(&ctx->mbox->box,
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen MAILBOX_LOCK_NOTIFY_MAILBOX_ABORT,
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen max_wait_time - now);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen alarm(0);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen return 1;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen}
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen#endif
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstatic int mbox_lock_fcntl(struct mbox_lock_context *ctx, int lock_type,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen time_t max_wait_time)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen struct flock fl;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen time_t now;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen unsigned int next_alarm;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen int wait_type;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (mbox_file_open_latest(ctx, lock_type) < 0)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return -1;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (lock_type == F_UNLCK && ctx->mbox->mbox_fd == -1)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return 1;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&fl);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen fl.l_type = lock_type;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen fl.l_whence = SEEK_SET;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen fl.l_start = 0;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen fl.l_len = 0;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
822b71c04ddd61cb08a0104f9e58f55334725e2aTimo Sirainen if (max_wait_time == 0) {
7c27b0ab7213121ea43994499c04059413f6d0f2Timo Sirainen /* usually we're waiting here, but if we came from
7c27b0ab7213121ea43994499c04059413f6d0f2Timo Sirainen mbox_lock_dotlock(), we just want to try locking */
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen wait_type = F_SETLK;
822b71c04ddd61cb08a0104f9e58f55334725e2aTimo Sirainen } else {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen wait_type = F_SETLKW;
822b71c04ddd61cb08a0104f9e58f55334725e2aTimo Sirainen now = time(NULL);
822b71c04ddd61cb08a0104f9e58f55334725e2aTimo Sirainen if (now >= max_wait_time)
822b71c04ddd61cb08a0104f9e58f55334725e2aTimo Sirainen alarm(1);
822b71c04ddd61cb08a0104f9e58f55334725e2aTimo Sirainen else
822b71c04ddd61cb08a0104f9e58f55334725e2aTimo Sirainen alarm(I_MIN(max_wait_time - now, 5));
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen }
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen while (fcntl(ctx->mbox->mbox_fd, wait_type, &fl) < 0) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (errno != EINTR) {
88de8e8fb4ad86f59ac0c4d85f5a9103dfd3fcc0Timo Sirainen if ((errno == EACCES || errno == EAGAIN) &&
88de8e8fb4ad86f59ac0c4d85f5a9103dfd3fcc0Timo Sirainen wait_type == F_SETLK) {
88de8e8fb4ad86f59ac0c4d85f5a9103dfd3fcc0Timo Sirainen /* non-blocking lock trying failed */
88de8e8fb4ad86f59ac0c4d85f5a9103dfd3fcc0Timo Sirainen return 0;
88de8e8fb4ad86f59ac0c4d85f5a9103dfd3fcc0Timo Sirainen }
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen alarm(0);
6797b2bb35596ec47d7f140eba79d4c686f370bcTimo Sirainen if (errno != EACCES) {
6797b2bb35596ec47d7f140eba79d4c686f370bcTimo Sirainen mbox_set_syscall_error(ctx->mbox, "fcntl()");
6797b2bb35596ec47d7f140eba79d4c686f370bcTimo Sirainen return -1;
6797b2bb35596ec47d7f140eba79d4c686f370bcTimo Sirainen }
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(&ctx->mbox->box,
6797b2bb35596ec47d7f140eba79d4c686f370bcTimo Sirainen "fcntl() failed with mbox file %s: "
6797b2bb35596ec47d7f140eba79d4c686f370bcTimo Sirainen "File is locked by another process (EACCES)",
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen mailbox_get_path(&ctx->mbox->box));
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return -1;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen now = time(NULL);
822b71c04ddd61cb08a0104f9e58f55334725e2aTimo Sirainen if (now >= max_wait_time) {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen alarm(0);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return 0;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen }
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen /* notify locks once every 5 seconds.
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen try to use rounded values. */
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen next_alarm = (max_wait_time - now) % 5;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (next_alarm == 0)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen next_alarm = 5;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen alarm(next_alarm);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen index_storage_lock_notify(&ctx->mbox->box,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen MAILBOX_LOCK_NOTIFY_MAILBOX_ABORT,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen max_wait_time - now);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen alarm(0);
181c1aff950e6f8e0556f8974e79d0747845ac0fTimo Sirainen ctx->fcntl_locked = TRUE;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return 1;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainenstatic int ATTR_NOWARN_UNUSED_RESULT
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainenmbox_lock_list(struct mbox_lock_context *ctx, int lock_type,
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen time_t max_wait_time, int idx)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen enum mbox_lock_type *lock_types;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen enum mbox_lock_type type;
8e047750fa23706e883b14584d0ed7c4bfde3892Timo Sirainen int i, ret = 0;
8e047750fa23706e883b14584d0ed7c4bfde3892Timo Sirainen bool locked_status;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen ctx->lock_type = lock_type;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen lock_types = lock_type == F_WRLCK ||
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen (lock_type == F_UNLCK && ctx->mbox->mbox_lock_type == F_WRLCK) ?
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ctx->mbox->storage->write_locks :
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ctx->mbox->storage->read_locks;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen for (i = idx; lock_types[i] != (enum mbox_lock_type)-1; i++) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen type = lock_types[i];
8e047750fa23706e883b14584d0ed7c4bfde3892Timo Sirainen locked_status = lock_type != F_UNLCK;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8e047750fa23706e883b14584d0ed7c4bfde3892Timo Sirainen if (ctx->locked_status[type] == locked_status)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen continue;
8e047750fa23706e883b14584d0ed7c4bfde3892Timo Sirainen ctx->locked_status[type] = locked_status;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen ret = lock_data[type].func(ctx, lock_type, max_wait_time);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (ret <= 0)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen break;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return ret;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
181c1aff950e6f8e0556f8974e79d0747845ac0fTimo Sirainenstatic int mbox_update_locking(struct mbox_mailbox *mbox, int lock_type,
181c1aff950e6f8e0556f8974e79d0747845ac0fTimo Sirainen bool *fcntl_locked_r)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen struct mbox_lock_context ctx;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen time_t max_wait_time;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen int ret, i;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen bool drop_locks;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
181c1aff950e6f8e0556f8974e79d0747845ac0fTimo Sirainen *fcntl_locked_r = FALSE;
181c1aff950e6f8e0556f8974e79d0747845ac0fTimo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen index_storage_lock_notify_reset(&mbox->box);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (!mbox->storage->lock_settings_initialized)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen mbox_init_lock_settings(mbox->storage);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (mbox->mbox_fd == -1 && mbox->mbox_file_stream != NULL) {
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen /* read-only mbox stream. no need to lock. */
c000c8eca8f24b2a0c76393ec4bbf76a505a4983Timo Sirainen i_assert(mbox_is_backend_readonly(mbox));
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mbox->mbox_lock_type = lock_type;
c817e46049c4dc07f7bbc16f43f903ab7ea9ae7dTimo Sirainen return 1;
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen }
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen max_wait_time = time(NULL) +
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen mail_storage_get_lock_timeout(&mbox->storage->storage,
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen mbox->storage->set->mbox_lock_timeout);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&ctx);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen ctx.mbox = mbox;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (mbox->mbox_lock_type == F_WRLCK) {
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen /* dropping to shared lock. first drop those that we
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen don't remove completely. */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen const enum mbox_lock_type *read_locks =
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen mbox->storage->read_locks;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen for (i = 0; i < MBOX_LOCK_COUNT; i++)
8e047750fa23706e883b14584d0ed7c4bfde3892Timo Sirainen ctx.locked_status[i] = TRUE;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen for (i = 0; read_locks[i] != (enum mbox_lock_type)-1; i++)
8e047750fa23706e883b14584d0ed7c4bfde3892Timo Sirainen ctx.locked_status[read_locks[i]] = FALSE;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen drop_locks = TRUE;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen } else {
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen drop_locks = FALSE;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen }
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mbox->mbox_lock_type = lock_type;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen ret = mbox_lock_list(&ctx, lock_type, max_wait_time, 0);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (ret <= 0) {
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen if (!drop_locks)
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen mbox_unlock_files(&ctx);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (ret == 0) {
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen mail_storage_set_error(&mbox->storage->storage,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen MAIL_ERROR_TEMP, MAIL_ERRSTR_LOCK_TIMEOUT);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return ret;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen if (drop_locks) {
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen /* dropping to shared lock: drop the locks that are only
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen in write list */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen const enum mbox_lock_type *read_locks =
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen mbox->storage->read_locks;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen const enum mbox_lock_type *write_locks =
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen mbox->storage->write_locks;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
8e047750fa23706e883b14584d0ed7c4bfde3892Timo Sirainen memset(ctx.locked_status, 0, sizeof(ctx.locked_status));
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen for (i = 0; write_locks[i] != (enum mbox_lock_type)-1; i++)
8e047750fa23706e883b14584d0ed7c4bfde3892Timo Sirainen ctx.locked_status[write_locks[i]] = TRUE;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen for (i = 0; read_locks[i] != (enum mbox_lock_type)-1; i++)
8e047750fa23706e883b14584d0ed7c4bfde3892Timo Sirainen ctx.locked_status[read_locks[i]] = FALSE;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mbox->mbox_lock_type = F_WRLCK;
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen mbox_lock_list(&ctx, F_UNLCK, 0, 0);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mbox->mbox_lock_type = F_RDLCK;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen }
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen
181c1aff950e6f8e0556f8974e79d0747845ac0fTimo Sirainen *fcntl_locked_r = ctx.fcntl_locked;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen return 1;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen}
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainenint mbox_lock(struct mbox_mailbox *mbox, int lock_type,
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen unsigned int *lock_id_r)
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen{
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen const char *path = mailbox_get_path(&mbox->box);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen int mbox_fd = mbox->mbox_fd;
181c1aff950e6f8e0556f8974e79d0747845ac0fTimo Sirainen bool fcntl_locked;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen int ret;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen
4780c036a0f52079068bd23e8a77b67ff457dba6Timo Sirainen if (lock_type == F_RDLCK && mbox->external_transactions > 0 &&
4780c036a0f52079068bd23e8a77b67ff457dba6Timo Sirainen mbox->mbox_lock_type != F_RDLCK) {
86c6b2546b0bbfce326583f14d05f59674a6d861Timo Sirainen /* we have a transaction open that is going to save mails
86c6b2546b0bbfce326583f14d05f59674a6d861Timo Sirainen and apparently also wants to read from the same mailbox
86c6b2546b0bbfce326583f14d05f59674a6d861Timo Sirainen (copy, move, catenate). we need to write lock the mailbox,
86c6b2546b0bbfce326583f14d05f59674a6d861Timo Sirainen since we can't later upgrade a read lock to write lock. */
86c6b2546b0bbfce326583f14d05f59674a6d861Timo Sirainen lock_type = F_WRLCK;
86c6b2546b0bbfce326583f14d05f59674a6d861Timo Sirainen }
86c6b2546b0bbfce326583f14d05f59674a6d861Timo Sirainen
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen /* allow only unlock -> shared/exclusive or exclusive -> shared */
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen i_assert(lock_type == F_RDLCK || lock_type == F_WRLCK);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen i_assert(lock_type == F_RDLCK || mbox->mbox_lock_type != F_RDLCK);
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (mbox->mbox_lock_type == F_UNLCK) {
181c1aff950e6f8e0556f8974e79d0747845ac0fTimo Sirainen ret = mbox_update_locking(mbox, lock_type, &fcntl_locked);
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen if (ret <= 0)
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen return ret;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (mbox->storage->storage.set->mail_nfs_storage) {
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen if (fcntl_locked) {
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen nfs_flush_attr_cache_fd_locked(path, mbox_fd);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen nfs_flush_read_cache_locked(path, mbox_fd);
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen } else {
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen nfs_flush_attr_cache_unlocked(path);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen nfs_flush_read_cache_unlocked(path, mbox_fd);
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen }
181c1aff950e6f8e0556f8974e79d0747845ac0fTimo Sirainen }
181c1aff950e6f8e0556f8974e79d0747845ac0fTimo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mbox->mbox_lock_id += 2;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen }
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen if (lock_type == F_RDLCK) {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mbox->mbox_shared_locks++;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen *lock_id_r = mbox->mbox_lock_id;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen } else {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mbox->mbox_excl_locks++;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen *lock_id_r = mbox->mbox_lock_id + 1;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen }
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen if (mbox->mbox_stream != NULL)
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen istream_raw_mbox_set_locked(mbox->mbox_stream);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return 1;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstatic int mbox_unlock_files(struct mbox_lock_context *ctx)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen int ret = 0;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (mbox_lock_list(ctx, F_UNLCK, 0, 0) < 0)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen ret = -1;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen ctx->mbox->mbox_lock_id += 2;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen ctx->mbox->mbox_lock_type = F_UNLCK;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return ret;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainenint mbox_unlock(struct mbox_mailbox *mbox, unsigned int lock_id)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen struct mbox_lock_context ctx;
181c1aff950e6f8e0556f8974e79d0747845ac0fTimo Sirainen bool fcntl_locked;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen int i;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen i_assert(mbox->mbox_lock_id == (lock_id & ~1));
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
23bdbb7b1831785c6ba6df190f6369da882d2b9dTimo Sirainen if ((lock_id & 1) != 0) {
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen /* dropping exclusive lock */
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen i_assert(mbox->mbox_excl_locks > 0);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (--mbox->mbox_excl_locks > 0)
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen return 0;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (mbox->mbox_shared_locks > 0) {
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen /* drop to shared lock */
181c1aff950e6f8e0556f8974e79d0747845ac0fTimo Sirainen if (mbox_update_locking(mbox, F_RDLCK,
181c1aff950e6f8e0556f8974e79d0747845ac0fTimo Sirainen &fcntl_locked) < 0)
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen return -1;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen return 0;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen }
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen } else {
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen /* dropping shared lock */
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen i_assert(mbox->mbox_shared_locks > 0);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (--mbox->mbox_shared_locks > 0)
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen return 0;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (mbox->mbox_excl_locks > 0)
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen return 0;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen }
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen /* all locks gone */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen /* make sure we don't read the stream while unlocked */
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen if (mbox->mbox_stream != NULL)
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen istream_raw_mbox_set_unlocked(mbox->mbox_stream);
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&ctx);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen ctx.mbox = mbox;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen for (i = 0; i < MBOX_LOCK_COUNT; i++)
8e047750fa23706e883b14584d0ed7c4bfde3892Timo Sirainen ctx.locked_status[i] = TRUE;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return mbox_unlock_files(&ctx);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen
86c6b2546b0bbfce326583f14d05f59674a6d861Timo Sirainenunsigned int mbox_get_cur_lock_id(struct mbox_mailbox *mbox)
86c6b2546b0bbfce326583f14d05f59674a6d861Timo Sirainen{
86c6b2546b0bbfce326583f14d05f59674a6d861Timo Sirainen return mbox->mbox_lock_id +
86c6b2546b0bbfce326583f14d05f59674a6d861Timo Sirainen (mbox->mbox_excl_locks > 0 ? 1 : 0);
86c6b2546b0bbfce326583f14d05f59674a6d861Timo Sirainen}
86c6b2546b0bbfce326583f14d05f59674a6d861Timo Sirainen
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainenvoid mbox_dotlock_touch(struct mbox_mailbox *mbox)
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen{
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen if (mbox->mbox_dotlock == NULL)
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen return;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen if (!mbox->mbox_used_privileges)
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen (void)file_dotlock_touch(mbox->mbox_dotlock);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen else {
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen mbox_dotlock_privileged_op(mbox, NULL,
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen MBOX_DOTLOCK_OP_TOUCH);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen }
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen}