diff src/master/ssl-init-main.c @ 5601:b02af502bcd6 HEAD

When running multiple Dovecot instances, only one of them needs to regenerate ssl-parameters.dat.
author Timo Sirainen <tss@iki.fi>
date Sun, 13 May 2007 16:45:49 +0300
parents 04958ae9a2e3
children 9dd899f563fe
line wrap: on
line diff
--- a/src/master/ssl-init-main.c	Sun May 13 16:24:35 2007 +0300
+++ b/src/master/ssl-init-main.c	Sun May 13 16:45:49 2007 +0300
@@ -2,6 +2,7 @@
 
 #include "lib.h"
 #include "lib-signals.h"
+#include "file-lock.h"
 #include "randgen.h"
 #include "ssl-init.h"
 
@@ -11,17 +12,17 @@
 #include <sys/stat.h>
 
 #ifdef HAVE_SSL
-static void generate_parameters_file(const char *fname)
+static int generate_parameters_file(const char *fname)
 {
 	const char *temp_fname;
+	struct file_lock *lock;
 	mode_t old_mask;
-	int fd;
+	int fd, ret;
 
 	temp_fname = t_strconcat(fname, ".tmp", NULL);
-	(void)unlink(temp_fname);
 
 	old_mask = umask(0);
-	fd = open(temp_fname, O_WRONLY | O_CREAT | O_EXCL, 0644);
+	fd = open(temp_fname, O_WRONLY | O_CREAT, 0644);
 	umask(old_mask);
 
 	if (fd == -1) {
@@ -29,25 +30,42 @@
 			temp_fname);
 	}
 
-	_ssl_generate_parameters(fd, temp_fname);
+	/* If multiple dovecot instances are running, only one of them needs
+	   to regenerate this file. */
+	ret = file_try_lock(fd, temp_fname, F_WRLCK,
+			    FILE_LOCK_METHOD_FCNTL, &lock);
+	if (ret < 0)
+		i_fatal("file_try_lock(%s) failed: %m", temp_fname);
+	if (ret == 0) {
+		/* someone else is writing this */
+		return -1;
+	}
+	if (ftruncate(fd, 0) < 0)
+		i_fatal("ftruncate(%s) failed: %m", temp_fname);
 
-	if (close(fd) < 0)
-		i_fatal("close(%s) failed: %m", temp_fname);
+	_ssl_generate_parameters(fd, temp_fname);
 
 	if (rename(temp_fname, fname) < 0)
 		i_fatal("rename(%s, %s) failed: %m", temp_fname, fname);
+	if (close(fd) < 0)
+		i_fatal("close(%s) failed: %m", temp_fname);
+	file_lock_free(&lock);
 
 	i_info("SSL parameters regeneration completed");
+	return 0;
 }
 #else
-static void generate_parameters_file(const char *fname __attr_unused__)
+static int generate_parameters_file(const char *fname __attr_unused__)
 {
 	i_fatal("Dovecot built without SSL support");
+	return -1;
 }
 #endif
 
 int main(int argc, char *argv[])
 {
+	int ret;
+
 	lib_init();
 	i_set_failure_internal();
 
@@ -55,9 +73,10 @@
 		i_fatal("Usage: ssl-build-param <path>");
 
 	random_init();
-	generate_parameters_file(argv[1]);
+	if (generate_parameters_file(argv[1]) < 0)
+		ret = 1;
 
 	random_deinit();
 	lib_deinit();
-	return 0;
+	return ret;
 }