Handle multipart tar archives when reading archive

This commit is contained in:
2021-04-01 19:44:19 +02:00
parent f7c73167eb
commit 57dfbb0108
3 changed files with 38 additions and 9 deletions

View File

@@ -5,6 +5,7 @@
*/ */
#include "ArchiveReader.hpp" #include "ArchiveReader.hpp"
#include "ArchiveConfiguration.hpp"
#include "LibArchiveHelper.hpp" #include "LibArchiveHelper.hpp"
#include "Base/Utils.hpp" #include "Base/Utils.hpp"
#include <archive.h> #include <archive.h>
@@ -43,7 +44,12 @@ namespace openVulkanoCpp
void ArchiveReader::PrepOpen() 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_filter_all(m_archive));
ChkErr(archive_read_support_format_all(m_archive)); ChkErr(archive_read_support_format_all(m_archive));
m_open = true; m_open = true;
@@ -72,12 +78,27 @@ namespace openVulkanoCpp
bool ArchiveReader::Open(const std::vector<std::string>& archiveFiles) bool ArchiveReader::Open(const std::vector<std::string>& archiveFiles)
{ {
auto files = Utils::toCString(archiveFiles); if (archiveFiles.empty()) return false;
files.push_back(nullptr); ArchiveConfiguration ac = ArchiveConfiguration::FromFileName(archiveFiles.front().c_str());
PrepOpen(); if (ac.type == ArchiveType::TAR) // TODO handle all archive types correctly
ChkErr(archive_read_open_filenames(m_archive, files.data(), BUFFER_SIZE)); { // Queue based approach for all archive types that do not natively support split archives
ReadNextHeader(); for(const std::string& file : archiveFiles)
return HasNext(); {
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) bool ArchiveReader::Open(const std::filesystem::path& dir, const std::string& fileNamePattern)
@@ -113,7 +134,12 @@ namespace openVulkanoCpp
if (result == ARCHIVE_EOF) if (result == ARCHIVE_EOF)
{ {
m_archiveEntry = nullptr; m_archiveEntry = nullptr;
m_eof = true; if (!m_archivesToRead.empty())
{
Open(m_archivesToRead.front());
m_archivesToRead.pop();
}
else m_eof = true;
} }
} }

View File

@@ -12,6 +12,7 @@
#include <optional> #include <optional>
#include <functional> #include <functional>
#include <ostream> #include <ostream>
#include <queue>
namespace openVulkanoCpp namespace openVulkanoCpp
{ {
@@ -20,6 +21,8 @@ namespace openVulkanoCpp
bool m_open = false; bool m_open = false;
bool m_eof = false; bool m_eof = false;
std::queue<std::string> m_archivesToRead;
public: public:
explicit ArchiveReader(const std::shared_ptr<spdlog::logger>& logger = nullptr); explicit ArchiveReader(const std::shared_ptr<spdlog::logger>& logger = nullptr);

View File

@@ -81,7 +81,7 @@ namespace openVulkanoCpp
if (archiveResult <= ARCHIVE_FATAL) lvl = spdlog::level::level_enum::critical; if (archiveResult <= ARCHIVE_FATAL) lvl = spdlog::level::level_enum::critical;
else if (archiveResult <= ARCHIVE_FAILED) lvl = spdlog::level::level_enum::err; else if (archiveResult <= ARCHIVE_FAILED) lvl = spdlog::level::level_enum::err;
const char* errorString = archive_error_string(arch); 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); if (archiveResult == ARCHIVE_FAILED) throw std::runtime_error(errorString);
return false; return false;
} }