| @@ -499,9 +499,9 @@ static la_ssize_t archiveReadVectorCallback(struct archive *a, void* client_data | |||
| return len; | |||
| } | |||
| static void unarchiveToDirectory(const std::string& archivePath, const std::vector<uint8_t>* archiveData, const std::string& dirPath) { | |||
| static void unarchiveToDirectory(const std::string& archivePath, const std::vector<uint8_t>* archiveData, const std::string& dirPathStr) { | |||
| #if defined ARCH_MAC | |||
| // libarchive depends on locale so set thread | |||
| // libarchive depends on locale so set thread locale | |||
| // If locale is not found, returns NULL which resets thread to global locale | |||
| locale_t loc = newlocale(LC_CTYPE_MASK, "en_US.UTF-8", NULL); | |||
| locale_t oldLoc = uselocale(loc); | |||
| @@ -511,6 +511,8 @@ static void unarchiveToDirectory(const std::string& archivePath, const std::vect | |||
| }); | |||
| #endif | |||
| fs::path dirPath = fs::u8path(dirPathStr); | |||
| // Based on minitar.c extract() in libarchive examples | |||
| int r; | |||
| @@ -564,20 +566,34 @@ static void unarchiveToDirectory(const std::string& archivePath, const std::vect | |||
| throw Exception("Unarchiver could not read entry from archive: %s", archive_error_string(a)); | |||
| // Convert relative pathname to absolute based on dirPath | |||
| std::string entryPath = archive_entry_pathname(entry); | |||
| // DEBUG("entryPath: %s", entryPath.c_str()); | |||
| if (!fs::u8path(entryPath).is_relative()) | |||
| throw Exception("Unarchiver does not support absolute tar paths: %s", entryPath.c_str()); | |||
| entryPath = (fs::u8path(dirPath) / fs::u8path(entryPath)).generic_u8string(); | |||
| fs::path entryPath = fs::u8path(archive_entry_pathname(entry)); | |||
| // DEBUG("entryPath: %s", entryPath.generic_u8string().c_str()); | |||
| if (!entryPath.is_relative()) | |||
| throw Exception("Unarchiver does not support absolute tar paths: %s", entryPath.u8string().c_str()); | |||
| entryPath = dirPath / entryPath; | |||
| #if defined ARCH_WIN | |||
| archive_entry_copy_pathname_w(entry, string::UTF8toUTF16(entryPath).c_str()); | |||
| archive_entry_copy_pathname_w(entry, string::UTF8toUTF16(entryPath.u8string()).c_str()); | |||
| #else | |||
| archive_entry_set_pathname(entry, entryPath.c_str()); | |||
| archive_entry_set_pathname(entry, entryPath.u8string().c_str()); | |||
| #endif | |||
| mode_t mode = archive_entry_mode(entry); | |||
| mode_t filetype = archive_entry_filetype(entry); | |||
| int64_t size = archive_entry_size(entry); | |||
| // Force minimum modes | |||
| if (filetype == AE_IFREG) { | |||
| mode |= 0644; | |||
| } | |||
| else if (filetype == AE_IFDIR) { | |||
| mode |= 0755; | |||
| } | |||
| archive_entry_set_mode(entry, mode); | |||
| // Delete zero-byte files | |||
| if (archive_entry_filetype(entry) == AE_IFREG && archive_entry_size(entry) == 0) { | |||
| remove(entryPath); | |||
| if (filetype == AE_IFREG && size == 0) { | |||
| remove(entryPath.generic_u8string()); | |||
| continue; | |||
| } | |||