diff options
Diffstat (limited to 'src/util/maildirlock.c')
-rw-r--r-- | src/util/maildirlock.c | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/src/util/maildirlock.c b/src/util/maildirlock.c new file mode 100644 index 0000000..89fbacc --- /dev/null +++ b/src/util/maildirlock.c @@ -0,0 +1,106 @@ +/* Copyright (c) 2008-2018 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "lib-signals.h" +#include "ioloop.h" +#include "write-full.h" +#include "file-dotlock.h" +#include "index/maildir/maildir-uidlist.h" + +#include <stdio.h> +#include <unistd.h> +#include <signal.h> + +static struct dotlock_settings dotlock_settings = { + .stale_timeout = MAILDIR_UIDLIST_LOCK_STALE_TIMEOUT, + .use_io_notify = TRUE +}; + +static struct ioloop *ioloop; + +static void sig_die(const siginfo_t *si ATTR_UNUSED, void *context ATTR_UNUSED) +{ + io_loop_stop(ioloop); +} + +static int maildir_lock(const char *path, unsigned int timeout, + struct dotlock **dotlock_r) +{ + dotlock_settings.timeout = timeout; + dotlock_settings.use_excl_lock = getenv("DOTLOCK_USE_EXCL") != NULL; + dotlock_settings.nfs_flush = getenv("MAIL_NFS_STORAGE") != NULL; + + path = t_strconcat(path, "/" MAILDIR_UIDLIST_NAME, NULL); + return file_dotlock_create(&dotlock_settings, path, 0, dotlock_r); +} + +int main(int argc, const char *argv[]) +{ + struct dotlock *dotlock; + unsigned int timeout; + pid_t pid; + int fd[2], ret; + char c; + + if (argc != 3) { + fprintf(stderr, "Usage: maildirlock <path> <timeout>\n" + " - SIGTERM will release the lock.\n"); + return 1; + } + if (pipe(fd) != 0) { + fprintf(stderr, "pipe() failed: %s", strerror(errno)); + return 1; + } + + pid = fork(); + if (pid == (pid_t)-1) { + fprintf(stderr, "fork() failed: %s", strerror(errno)); + return 1; + } + + /* call lib_init() only after fork so that PID gets set correctly */ + lib_init(); + lib_signals_init(); + ioloop = io_loop_create(); + lib_signals_set_handler(SIGINT, LIBSIG_FLAG_DELAYED, sig_die, NULL); + lib_signals_set_handler(SIGTERM, LIBSIG_FLAG_DELAYED, sig_die, NULL); + + if (pid != 0) { + i_close_fd(&fd[1]); + ret = read(fd[0], &c, 1); + if (ret < 0) { + i_error("read(pipe) failed: %m"); + return 1; + } + if (ret != 1) { + /* locking timed out */ + return 1; + } + + printf("%s", dec2str(pid)); + return 0; + } + + /* child process - stdout has to be closed so that caller knows when + to stop reading it. */ + if (dup2(STDERR_FILENO, STDOUT_FILENO) < 0) + i_fatal("dup2() failed: %m"); + + if (str_to_uint(argv[2], &timeout) < 0) + i_fatal("Invalid timeout value: %s", argv[2]); + if (maildir_lock(argv[1], timeout, &dotlock) <= 0) + return 1; + + /* locked - send a byte */ + if (write_full(fd[1], "", 1) < 0) + i_fatal("write(pipe) failed: %m"); + + io_loop_run(ioloop); + + file_dotlock_delete(&dotlock); + lib_signals_deinit(); + + io_loop_destroy(&ioloop); + lib_deinit(); + return 0; +} |