]> git.ipfire.org Git - thirdparty/rrdtool-1.x.git/commitdiff
Fix: Cannot rename temporary file to final file
authorWolfgang Stöggl <c72578@yahoo.de>
Fri, 18 Jan 2019 17:05:47 +0000 (18:05 +0100)
committerTobias Oetiker <tobi@oetiker.ch>
Sat, 19 Jan 2019 15:54:56 +0000 (16:54 +0100)
- Fixes the following failing tests under Windows:
  modify1, modify2, modify3, modify4, modify5
- Use CreateFileA() with FILE_SHARE_DELETE in rrd_open.c,
  so that the outfilename can later be replaced by tmpfilename using
  write_rrd() in rrd_create.c

src/rrd_create.c
src/rrd_open.c

index 464073b7c4e67547fd314280bab9f1c3f3a251c7..32e9ce2fa61047fc26bcc718b82ef3716087014b 100644 (file)
@@ -1482,13 +1482,30 @@ int write_rrd(
             }
 
 #ifdef WIN32
-/* in windows, renaming to an existing file is verboten */
-            unlink(outfilename);
-#endif
+/* In Windows, renaming to an existing file is not allowed. Even, if the file
+ * is deleted before, using _unlink() here. Furthermore the FILE_SHARE_DELETE
+ * flag is required, which is used in CreateFileA in rrd_open.c
+ * Check first, if the file exists. Use ReplaceFileA if the file exists.
+ * Otherwise rename as usual */
+            if (_access_s(outfilename, 0) == 0) {
+                if (ReplaceFileA(outfilename, tmpfilename, NULL, 0, 0, 0) ==
+                    0) {
+                    rrd_set_error("Cannot replace %s!", outfilename);
+                    goto done;
+                }
+            } else {
+                if (rename(tmpfilename, outfilename) != 0) {
+                    rrd_set_error
+                        ("Cannot rename temporary file to final file!");
+                    goto done;
+                }
+            }
+#else
             if (rename(tmpfilename, outfilename) != 0) {
                 rrd_set_error("Cannot rename temporary file to final file!");
                 goto done;
             }
+#endif
 
             // after the rename: forget the file again, just to be sure...
             if (rrdc_is_any_connected()) {
index 0337771046f4944b3282e0668041da382a30a9fb..d02acfe27a681cca60f80de617f2f6a5980ffaef 100644 (file)
@@ -270,10 +270,26 @@ rrd_file_t *rrd_open(
     flags |= O_BINARY;
 #endif
 
+#if defined(_WIN32)
+    /* In Windows we need FILE_SHARE_DELETE, so that the file can be
+     * renamed/replaced later on in rrd_create.c
+     * This is only possible using CreateFileA() first and not using open() alone */
+    HANDLE    handle;
+
+    handle =
+        CreateFileA(file_name, GENERIC_READ | GENERIC_WRITE,
+                    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                    NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+    if ((rrd_simple_file->fd = _open_osfhandle((intptr_t) handle, flags)) < 0) {
+        rrd_set_error("opening '%s': %s", file_name, rrd_strerror(errno));
+        goto out_free;
+    }
+#else
     if ((rrd_simple_file->fd = open(file_name, flags, 0666)) < 0) {
         rrd_set_error("opening '%s': %s", file_name, rrd_strerror(errno));
         goto out_free;
     }
+#endif
 
 #ifdef HAVE_MMAP
 #ifdef HAVE_BROKEN_MS_ASYNC