From a975473cc39da0045d643ba067edcc8b855f7317 Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Tue, 11 Feb 2020 18:34:45 +0100 Subject: [PATCH] Unlink before creating a hardlink on Windows when using ARCHIVE_EXTRACT_SAFE_WRITES. Completes #1330 for Windows. --- libarchive/archive_write_disk_windows.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/libarchive/archive_write_disk_windows.c b/libarchive/archive_write_disk_windows.c index 111b54128..77e36c4a6 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) { -- 2.47.2