From 57dfbb0108d49491fbbe68be1524ca881fc33b6b Mon Sep 17 00:00:00 2001 From: GeorgH93 Date: Thu, 1 Apr 2021 19:44:19 +0200 Subject: [PATCH] Handle multipart tar archives when reading archive --- openVulkanoCpp/IO/Archive/ArchiveReader.cpp | 42 +++++++++++++++---- openVulkanoCpp/IO/Archive/ArchiveReader.hpp | 3 ++ .../IO/Archive/LibArchiveHelper.hpp | 2 +- 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/openVulkanoCpp/IO/Archive/ArchiveReader.cpp b/openVulkanoCpp/IO/Archive/ArchiveReader.cpp index 6721701..f30101e 100644 --- a/openVulkanoCpp/IO/Archive/ArchiveReader.cpp +++ b/openVulkanoCpp/IO/Archive/ArchiveReader.cpp @@ -5,6 +5,7 @@ */ #include "ArchiveReader.hpp" +#include "ArchiveConfiguration.hpp" #include "LibArchiveHelper.hpp" #include "Base/Utils.hpp" #include @@ -43,7 +44,12 @@ namespace openVulkanoCpp void ArchiveReader::PrepOpen() { - if (m_open) ChkErr(archive_read_close(m_archive)); + if (m_open) + { + ChkErr(archive_read_close(m_archive)); + ChkErr(archive_free(m_archive)); + m_archive = archive_read_new(); + } ChkErr(archive_read_support_filter_all(m_archive)); ChkErr(archive_read_support_format_all(m_archive)); m_open = true; @@ -72,12 +78,27 @@ namespace openVulkanoCpp bool ArchiveReader::Open(const std::vector& archiveFiles) { - auto files = Utils::toCString(archiveFiles); - files.push_back(nullptr); - PrepOpen(); - ChkErr(archive_read_open_filenames(m_archive, files.data(), BUFFER_SIZE)); - ReadNextHeader(); - return HasNext(); + if (archiveFiles.empty()) return false; + ArchiveConfiguration ac = ArchiveConfiguration::FromFileName(archiveFiles.front().c_str()); + if (ac.type == ArchiveType::TAR) // TODO handle all archive types correctly + { // Queue based approach for all archive types that do not natively support split archives + for(const std::string& file : archiveFiles) + { + m_archivesToRead.push(file); + } + bool state = Open(m_archivesToRead.front()); + m_archivesToRead.pop(); + return state; + } + else + { // This might only be used for archive types that support split archives (like zip, rar, 7zip, ...) + auto files = Utils::toCString(archiveFiles); + files.push_back(nullptr); + PrepOpen(); + ChkErr(archive_read_open_filenames(m_archive, files.data(), BUFFER_SIZE)); + ReadNextHeader(); + return HasNext(); + } } bool ArchiveReader::Open(const std::filesystem::path& dir, const std::string& fileNamePattern) @@ -113,7 +134,12 @@ namespace openVulkanoCpp if (result == ARCHIVE_EOF) { m_archiveEntry = nullptr; - m_eof = true; + if (!m_archivesToRead.empty()) + { + Open(m_archivesToRead.front()); + m_archivesToRead.pop(); + } + else m_eof = true; } } diff --git a/openVulkanoCpp/IO/Archive/ArchiveReader.hpp b/openVulkanoCpp/IO/Archive/ArchiveReader.hpp index 46cc0e3..e542adb 100644 --- a/openVulkanoCpp/IO/Archive/ArchiveReader.hpp +++ b/openVulkanoCpp/IO/Archive/ArchiveReader.hpp @@ -12,6 +12,7 @@ #include #include #include +#include namespace openVulkanoCpp { @@ -20,6 +21,8 @@ namespace openVulkanoCpp bool m_open = false; bool m_eof = false; + std::queue m_archivesToRead; + public: explicit ArchiveReader(const std::shared_ptr& logger = nullptr); diff --git a/openVulkanoCpp/IO/Archive/LibArchiveHelper.hpp b/openVulkanoCpp/IO/Archive/LibArchiveHelper.hpp index b75de60..8d8559a 100644 --- a/openVulkanoCpp/IO/Archive/LibArchiveHelper.hpp +++ b/openVulkanoCpp/IO/Archive/LibArchiveHelper.hpp @@ -81,7 +81,7 @@ namespace openVulkanoCpp if (archiveResult <= ARCHIVE_FATAL) lvl = spdlog::level::level_enum::critical; else if (archiveResult <= ARCHIVE_FAILED) lvl = spdlog::level::level_enum::err; const char* errorString = archive_error_string(arch); - if (logger) logger->log(lvl, errorString); + if (logger) logger->log(lvl, errorString ? errorString : "Unknown error while handling archive"); if (archiveResult == ARCHIVE_FAILED) throw std::runtime_error(errorString); return false; }