]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Unlink before creating a hardlink on Windows
authorMartin Matuska <martin@matuska.org>
Tue, 11 Feb 2020 17:34:45 +0000 (18:34 +0100)
committerMartin Matuska <martin@matuska.org>
Tue, 11 Feb 2020 21:46:11 +0000 (22:46 +0100)
when using ARCHIVE_EXTRACT_SAFE_WRITES.

Completes #1330 for Windows.

libarchive/archive_write_disk_windows.c

index 111b54128c750c8e828e4be5373fbe8b77262849..77e36c4a621dd04b6a4b4e040c5d3df756103560 100644 (file)
@@ -1670,6 +1670,20 @@ create_filesystem_object(struct archive_write_disk *a)
                        errno = EINVAL;
                        r = -1;
                } else {
+                       /*
+                        * Unlinking and linking here is really not atomic,
+                        * but doing it right, would require us to construct
+                        * an mktemplink() function, and then use _wrename().
+                        */
+                       if (a->flags & ARCHIVE_EXTRACT_SAFE_WRITES) {
+                               attrs = GetFileAttributesW(namefull);
+                               if (attrs != INVALID_FILE_ATTRIBUTES) {
+                                       if (attrs & FILE_ATTRIBUTE_DIRECTORY)
+                                               disk_rmdir(namefull);
+                                       else
+                                               disk_unlink(namefull);
+                               }
+                       }
                        r = la_CreateHardLinkW(namefull, linkfull);
                        if (r == 0) {
                                la_dosmaperr(GetLastError());
@@ -1709,9 +1723,7 @@ create_filesystem_object(struct archive_write_disk *a)
                /*
                 * Unlinking and linking here is really not atomic,
                 * but doing it right, would require us to construct
-                * an mktemplink() function, and then use rename(2).
-                *
-                * The original link may be a directory symlink.
+                * an mktemplink() function, and then use _wrename().
                 */
                attrs = GetFileAttributesW(a->name);
                if (attrs != INVALID_FILE_ATTRIBUTES) {