summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArttu Tarkiainen <arttu.tarkiainen@qt.io>2022-04-29 14:36:07 +0300
committerArttu Tarkiainen <arttu.tarkiainen@qt.io>2022-05-04 09:22:22 +0300
commit61b05e03159195ccafe6173707c249f8d56bbb8d (patch)
treea4d060b8b915da626efaf6cb92c1247f0fca852d
parentd3dbae7cc82d1cb9cc45d9ca82fdd02f433e16a3 (diff)
Fix "Can't unlink already-existing object" errors on extract
On Windows, extracting archives containing same files and directories would sometimes cause "Can't unlink already-existing object: Permission denied" error when replacing existing files. This was caused by releasing the FileGuard lock object for the archive entry without ensuring the entry was closed. Normally libarchive clients do not need to care about this, as the entry is closed automatically by archive_write_header() and archive_write_close() as required, but in our case there is a need access synchronization because archives can extract entries with the same entry paths in parallel. Fix by calling archive_write_finish_entry() before releasing the lock, so that no file handles are left open and no file attribute changes are left pending for the implicit closing on writing the next entry header. Task-number: QTIFW-2620 Change-Id: I7e7322927964296c3b32ef4a052a91f1ba29aac3 Reviewed-by: Katja Marttila <katja.marttila@qt.io>
-rw-r--r--src/libs/installer/libarchivearchive.cpp14
1 files changed, 10 insertions, 4 deletions
diff --git a/src/libs/installer/libarchivearchive.cpp b/src/libs/installer/libarchivearchive.cpp
index 156a84d26..4573da2b1 100644
--- a/src/libs/installer/libarchivearchive.cpp
+++ b/src/libs/installer/libarchivearchive.cpp
@@ -426,8 +426,11 @@ bool ExtractWorker::writeEntry(archive *reader, archive *writer, archive_entry *
forever {
status = archive_read_data_block(reader, &buff, &size, &offset);
- if (status == ARCHIVE_EOF)
- return true;
+ if (status == ARCHIVE_EOF) {
+ status = archive_write_finish_entry(writer);
+ if (status == ARCHIVE_OK)
+ return true;
+ }
if (status != ARCHIVE_OK) {
m_status = Failure;
emit finished(tr("Cannot write entry \"%1\" to disk: %2")
@@ -1064,8 +1067,11 @@ bool LibArchiveArchive::writeEntry(archive *reader, archive *writer, archive_ent
forever {
status = archive_read_data_block(reader, &buff, &size, &offset);
- if (status == ARCHIVE_EOF)
- return true;
+ if (status == ARCHIVE_EOF) {
+ status = archive_write_finish_entry(writer);
+ if (status == ARCHIVE_OK)
+ return true;
+ }
if (status != ARCHIVE_OK) {
setErrorString(errorStringWithCode(reader));
return false;