bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2008-2018 Dovecot authors, see the included COPYING file */
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen#include "lib.h"
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen#include "lib-signals.h"
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen#include "ioloop.h"
9cd58c1fb9501bf7d3af7f2bb91b5bcbdcd1d8f2Timo Sirainen#include "write-full.h"
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen#include "file-dotlock.h"
361d4380f3a6e95fc680400381ac57eb60e44367Timo Sirainen#include "index/maildir/maildir-uidlist.h"
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen#include <stdio.h>
4e3e50374f74af24b35524a994af85a080c29722Timo Sirainen#include <unistd.h>
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen#include <signal.h>
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainenstatic struct dotlock_settings dotlock_settings = {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .stale_timeout = MAILDIR_UIDLIST_LOCK_STALE_TIMEOUT,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .use_io_notify = TRUE
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen};
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainenstatic struct ioloop *ioloop;
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen
1c7fa51b35231f375998f66d5756f214519218f8Timo Sirainenstatic void sig_die(const siginfo_t *si ATTR_UNUSED, void *context ATTR_UNUSED)
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen{
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen io_loop_stop(ioloop);
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen}
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainenstatic int maildir_lock(const char *path, unsigned int timeout,
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen struct dotlock **dotlock_r)
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen{
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen dotlock_settings.timeout = timeout;
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen dotlock_settings.use_excl_lock = getenv("DOTLOCK_USE_EXCL") != NULL;
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen dotlock_settings.nfs_flush = getenv("MAIL_NFS_STORAGE") != NULL;
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen
4e3e50374f74af24b35524a994af85a080c29722Timo Sirainen path = t_strconcat(path, "/" MAILDIR_UIDLIST_NAME, NULL);
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen return file_dotlock_create(&dotlock_settings, path, 0, dotlock_r);
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen}
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainenint main(int argc, const char *argv[])
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen{
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen struct dotlock *dotlock;
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen unsigned int timeout;
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainen pid_t pid;
9cd58c1fb9501bf7d3af7f2bb91b5bcbdcd1d8f2Timo Sirainen int fd[2], ret;
9cd58c1fb9501bf7d3af7f2bb91b5bcbdcd1d8f2Timo Sirainen char c;
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen if (argc != 3) {
4e3e50374f74af24b35524a994af85a080c29722Timo Sirainen fprintf(stderr, "Usage: maildirlock <path> <timeout>\n"
4e3e50374f74af24b35524a994af85a080c29722Timo Sirainen " - SIGTERM will release the lock.\n");
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen return 1;
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen }
9cd58c1fb9501bf7d3af7f2bb91b5bcbdcd1d8f2Timo Sirainen if (pipe(fd) != 0) {
f29fea1ed4ff62e438b982bd38ae46de12973857Timo Sirainen fprintf(stderr, "pipe() failed: %s", strerror(errno));
9cd58c1fb9501bf7d3af7f2bb91b5bcbdcd1d8f2Timo Sirainen return 1;
9cd58c1fb9501bf7d3af7f2bb91b5bcbdcd1d8f2Timo Sirainen }
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen
4e3e50374f74af24b35524a994af85a080c29722Timo Sirainen pid = fork();
4e3e50374f74af24b35524a994af85a080c29722Timo Sirainen if (pid == (pid_t)-1) {
f29fea1ed4ff62e438b982bd38ae46de12973857Timo Sirainen fprintf(stderr, "fork() failed: %s", strerror(errno));
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen return 1;
4e3e50374f74af24b35524a994af85a080c29722Timo Sirainen }
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen
4e3e50374f74af24b35524a994af85a080c29722Timo Sirainen /* call lib_init() only after fork so that PID gets set correctly */
4e3e50374f74af24b35524a994af85a080c29722Timo Sirainen lib_init();
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen lib_signals_init();
9cd58c1fb9501bf7d3af7f2bb91b5bcbdcd1d8f2Timo Sirainen ioloop = io_loop_create();
5512d420d826a2f9d4e7cb4e4919e1864fe688b0Timo Sirainen lib_signals_set_handler(SIGINT, LIBSIG_FLAG_DELAYED, sig_die, NULL);
5512d420d826a2f9d4e7cb4e4919e1864fe688b0Timo Sirainen lib_signals_set_handler(SIGTERM, LIBSIG_FLAG_DELAYED, sig_die, NULL);
4e3e50374f74af24b35524a994af85a080c29722Timo Sirainen
4e3e50374f74af24b35524a994af85a080c29722Timo Sirainen if (pid != 0) {
cee99a130b493f7068a7577f4c832aab147d2d2eTimo Sirainen i_close_fd(&fd[1]);
9cd58c1fb9501bf7d3af7f2bb91b5bcbdcd1d8f2Timo Sirainen ret = read(fd[0], &c, 1);
9cd58c1fb9501bf7d3af7f2bb91b5bcbdcd1d8f2Timo Sirainen if (ret < 0) {
f29fea1ed4ff62e438b982bd38ae46de12973857Timo Sirainen i_error("read(pipe) failed: %m");
4e3e50374f74af24b35524a994af85a080c29722Timo Sirainen return 1;
9cd58c1fb9501bf7d3af7f2bb91b5bcbdcd1d8f2Timo Sirainen }
9cd58c1fb9501bf7d3af7f2bb91b5bcbdcd1d8f2Timo Sirainen if (ret != 1) {
9cd58c1fb9501bf7d3af7f2bb91b5bcbdcd1d8f2Timo Sirainen /* locking timed out */
9cd58c1fb9501bf7d3af7f2bb91b5bcbdcd1d8f2Timo Sirainen return 1;
9cd58c1fb9501bf7d3af7f2bb91b5bcbdcd1d8f2Timo Sirainen }
9cd58c1fb9501bf7d3af7f2bb91b5bcbdcd1d8f2Timo Sirainen
4e3e50374f74af24b35524a994af85a080c29722Timo Sirainen printf("%s", dec2str(pid));
4e3e50374f74af24b35524a994af85a080c29722Timo Sirainen return 0;
4e3e50374f74af24b35524a994af85a080c29722Timo Sirainen }
4e3e50374f74af24b35524a994af85a080c29722Timo Sirainen
4e3e50374f74af24b35524a994af85a080c29722Timo Sirainen /* child process - stdout has to be closed so that caller knows when
4e3e50374f74af24b35524a994af85a080c29722Timo Sirainen to stop reading it. */
cee99a130b493f7068a7577f4c832aab147d2d2eTimo Sirainen if (dup2(STDERR_FILENO, STDOUT_FILENO) < 0)
cee99a130b493f7068a7577f4c832aab147d2d2eTimo Sirainen i_fatal("dup2() failed: %m");
4e3e50374f74af24b35524a994af85a080c29722Timo Sirainen
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch if (str_to_uint(argv[2], &timeout) < 0)
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch i_fatal("Invalid timeout value: %s", argv[2]);
4e3e50374f74af24b35524a994af85a080c29722Timo Sirainen if (maildir_lock(argv[1], timeout, &dotlock) <= 0)
4e3e50374f74af24b35524a994af85a080c29722Timo Sirainen return 1;
4e3e50374f74af24b35524a994af85a080c29722Timo Sirainen
9cd58c1fb9501bf7d3af7f2bb91b5bcbdcd1d8f2Timo Sirainen /* locked - send a byte */
9cd58c1fb9501bf7d3af7f2bb91b5bcbdcd1d8f2Timo Sirainen if (write_full(fd[1], "", 1) < 0)
9cd58c1fb9501bf7d3af7f2bb91b5bcbdcd1d8f2Timo Sirainen i_fatal("write(pipe) failed: %m");
9cd58c1fb9501bf7d3af7f2bb91b5bcbdcd1d8f2Timo Sirainen
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen io_loop_run(ioloop);
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen file_dotlock_delete(&dotlock);
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen lib_signals_deinit();
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen io_loop_destroy(&ioloop);
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen lib_deinit();
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen return 0;
5ae1765a2cad99de34d3e42b98b087a39b606184Timo Sirainen}