]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Fix #595: unbound-anchor cannot deal with full disk; it will now
authorYorgos Thessalonikefs <yorgos@nlnetlabs.nl>
Mon, 8 Apr 2024 12:15:03 +0000 (14:15 +0200)
committerYorgos Thessalonikefs <yorgos@nlnetlabs.nl>
Mon, 8 Apr 2024 12:15:03 +0000 (14:15 +0200)
  first write out to a temp file before replacing the original one,
  like Unbound already does for auto-trust-anchor-file.

doc/Changelog
smallapp/unbound-anchor.c

index 705e451a992ac725dee3355a7e1c4a2a9014bc76..11a450b81bdbd4eac86cf8d33996a88486df1cce 100644 (file)
@@ -1,3 +1,8 @@
+8 April 2024: Yorgos
+       - Fix #595: unbound-anchor cannot deal with full disk; it will now
+         first write out to a temp file before replacing the original one,
+         like Unbound already does for auto-trust-anchor-file.
+
 5 April 2024: Wouter
        - Fix comment syntax for view function views_find_view.
 
index 20a100cec80b86f03f2d04f76cead8e40386fe9e..137b2e94e29c15dcc1746f0ab4f0b2bcec632385 100644 (file)
@@ -1835,15 +1835,49 @@ verify_p7sig(BIO* data, BIO* p7s, STACK_OF(X509)* trust, const char* p7signer)
        return secure;
 }
 
+/** open a temp file */
+static FILE*
+tempfile_open(char* tempf, size_t tempflen, const char* fname, const char* mode)
+{
+       snprintf(tempf, tempflen, "%s~", fname);
+       return fopen(tempf, mode);
+}
+
+/** close an open temp file and replace the original with it */
+static void
+tempfile_close(FILE* fd, const char* tempf, const char* fname)
+{
+       fflush(fd);
+#ifdef HAVE_FSYNC
+       fsync(fileno(fd));
+#else
+       FlushFileBuffers((HANDLE)_get_osfhandle(_fileno(fd)));
+#endif
+       if(fclose(fd) != 0) {
+               printf("could not complete write: %s: %s\n",
+                       tempf, strerror(errno));
+               unlink(tempf);
+               return;
+       }
+       /* success; overwrite actual file */
+#ifdef USE_WINSOCK
+       (void)unlink(fname); /* windows does not replace file with rename() */
+#endif
+       if(rename(tempf, fname) < 0) {
+               printf("rename(%s to %s): %s", tempf, fname, strerror(errno));
+       }
+}
+
 /** write unsigned root anchor file, a 5011 revoked tp */
 static void
 write_unsigned_root(const char* root_anchor_file)
 {
        FILE* out;
        time_t now = time(NULL);
-       out = fopen(root_anchor_file, "w");
+       char tempf[2048];
+       out = tempfile_open(tempf, sizeof(tempf), root_anchor_file, "w");
        if(!out) {
-               if(verb) printf("%s: %s\n", root_anchor_file, strerror(errno));
+               if(verb) printf("%s: %s\n", tempf, strerror(errno));
                return;
        }
        if(fprintf(out, "; autotrust trust anchor file\n"
@@ -1858,13 +1892,7 @@ write_unsigned_root(const char* root_anchor_file)
                        root_anchor_file);
                if(verb && errno != 0) printf("%s\n", strerror(errno));
        }
-       fflush(out);
-#ifdef HAVE_FSYNC
-       fsync(fileno(out));
-#else
-       FlushFileBuffers((HANDLE)_get_osfhandle(_fileno(out)));
-#endif
-       fclose(out);
+       tempfile_close(out, tempf, root_anchor_file);
 }
 
 /** write root anchor file */
@@ -1874,29 +1902,24 @@ write_root_anchor(const char* root_anchor_file, BIO* ds)
        char* pp = NULL;
        int len;
        FILE* out;
+       char tempf[2048];
        (void)BIO_seek(ds, 0);
        len = BIO_get_mem_data(ds, &pp);
        if(!len || !pp) {
                if(verb) printf("out of memory\n");
                return;
        }
-       out = fopen(root_anchor_file, "w");
+       out = tempfile_open(tempf, sizeof(tempf), root_anchor_file, "w");
        if(!out) {
-               if(verb) printf("%s: %s\n", root_anchor_file, strerror(errno));
+               if(verb) printf("%s: %s\n", tempf, strerror(errno));
                return;
        }
        if(fwrite(pp, (size_t)len, 1, out) != 1) {
                if(verb) printf("failed to write all data to %s\n",
-                       root_anchor_file);
+                       tempf);
                if(verb && errno != 0) printf("%s\n", strerror(errno));
        }
-       fflush(out);
-#ifdef HAVE_FSYNC
-       fsync(fileno(out));
-#else
-       FlushFileBuffers((HANDLE)_get_osfhandle(_fileno(out)));
-#endif
-       fclose(out);
+       tempfile_close(out, tempf, root_anchor_file);
 }
 
 /** Perform the verification and update of the trustanchor file */
@@ -2040,18 +2063,19 @@ try_read_anchor(const char* file)
 static void
 write_builtin_anchor(const char* file)
 {
+       char tempf[2048];
        const char* builtin_root_anchor = get_builtin_ds();
-       FILE* out = fopen(file, "w");
+       FILE* out = tempfile_open(tempf, sizeof(tempf), file, "w");
        if(!out) {
                printf("could not write builtin anchor, to file %s: %s\n",
-                       file, strerror(errno));
+                       tempf, strerror(errno));
                return;
        }
        if(!fwrite(builtin_root_anchor, strlen(builtin_root_anchor), 1, out)) {
                printf("could not complete write builtin anchor, to file %s: %s\n",
-                       file, strerror(errno));
+                       tempf, strerror(errno));
        }
-       fclose(out);
+       tempfile_close(out, tempf, file);
 }
 
 /**