diff options
author | Martin Matuska <martin@matuska.org> | 2020-02-11 18:34:45 +0100 |
---|---|---|
committer | Martin Matuska <martin@matuska.org> | 2020-02-11 22:46:11 +0100 |
commit | a975473cc39da0045d643ba067edcc8b855f7317 (patch) | |
tree | dc79d9ff728306c38e8d87dc784b3a704b2f4e04 | |
parent | a559b588b4fc9f978501fb31750f48e68a06e2be (diff) | |
download | libarchive-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.c | 18 |
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) { |