summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Matuska <martin@matuska.org>2020-02-11 18:34:45 +0100
committerMartin Matuska <martin@matuska.org>2020-02-11 22:46:11 +0100
commita975473cc39da0045d643ba067edcc8b855f7317 (patch)
treedc79d9ff728306c38e8d87dc784b3a704b2f4e04
parenta559b588b4fc9f978501fb31750f48e68a06e2be (diff)
downloadlibarchive-a975473cc39da0045d643ba067edcc8b855f7317.tar.gz
Unlink before creating a hardlink on Windows
when using ARCHIVE_EXTRACT_SAFE_WRITES. Completes #1330 for Windows.
-rw-r--r--libarchive/archive_write_disk_windows.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/libarchive/archive_write_disk_windows.c b/libarchive/archive_write_disk_windows.c
index 111b5412..77e36c4a 100644
--- a/libarchive/archive_write_disk_windows.c
+++ b/libarchive/archive_write_disk_windows.c
@@ -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) {