dhcpv6-ia : write statefile atomically
authorHans Dedecker <dedeckeh@gmail.com>
Sat, 8 Aug 2020 23:08:23 +0000 (19:08 -0400)
committerHans Dedecker <dedeckeh@gmail.com>
Sun, 15 Nov 2020 17:33:22 +0000 (18:33 +0100)
Applications (e.g. unbound) need a consistent view of the statefile;
therefore write all the lease info to a temporary file which is later
renamed to the configured statefile name

Suggested-by : John Fremlin <john@fremlin.org>
Signed-off-by: Hans Dedecker <dedeckeh@gmail.com>
src/dhcpv6-ia.c

index 38a901bfc534f97db87972d3903087bf355917d3..7ca8e4faad2b5a73c5563eb28191a6f1239b7fe6 100644 (file)
@@ -306,18 +306,24 @@ void dhcpv6_ia_write_statefile(void)
        md5_begin(&ctxt.md5);
 
        if (config.dhcp_statefile) {
+               unsigned tmp_statefile_strlen = strlen(config.dhcp_statefile) + strlen(".tmp") + 1;
+               char *tmp_statefile = alloca(tmp_statefile_strlen);
                time_t now = odhcpd_time(), wall_time = time(NULL);
-               int fd = open(config.dhcp_statefile, O_CREAT | O_WRONLY | O_CLOEXEC, 0644);
+               int fd, ret;
                char leasebuf[512];
 
+               snprintf(tmp_statefile, tmp_statefile_strlen, "%s.tmp", config.dhcp_statefile);
+
+               fd = open(tmp_statefile, O_CREAT | O_WRONLY | O_CLOEXEC, 0644);
                if (fd < 0)
                        return;
-               int ret;
+
                ret = lockf(fd, F_LOCK, 0);
                if (ret < 0) {
                        close(fd);
                        return;
                }
+
                if (ftruncate(fd, 0) < 0) {}
 
                ctxt.fp = fdopen(fd, "w");
@@ -410,6 +416,8 @@ void dhcpv6_ia_write_statefile(void)
                }
 
                fclose(ctxt.fp);
+
+               rename(tmp_statefile, config.dhcp_statefile);
        }
 
        uint8_t newmd5[16];