Add archive writer support for existing c FILE*

also deduplicate some code
This commit is contained in:
Georg Hagen
2025-05-19 20:52:29 +02:00
parent 58922106f0
commit 8716857efe
2 changed files with 51 additions and 19 deletions

View File

@@ -15,47 +15,75 @@
namespace OpenVulkano namespace OpenVulkano
{ {
ArchiveWriter::ArchiveWriter(const char* fileName, ArchiveConfiguration archiveConfiguration, const std::shared_ptr<spdlog::logger>& logger, const char* password) ArchiveWriter::ArchiveWriter(ArchiveConfiguration archiveConfiguration, const std::shared_ptr<spdlog::logger>& logger, const char* password)
: ArchiveBase(archive_write_new(), archive_entry_new(), logger) : ArchiveBase(archive_write_new(), archive_entry_new(), logger)
, m_archiveConfig(archiveConfiguration) , m_archiveConfig(archiveConfiguration)
, m_shouldCompress(&SimpleFileTypeShouldCompressChecker) , m_shouldCompress(&SimpleFileTypeShouldCompressChecker)
{ //TODO error handling { //TODO better error handling
ChkErr(archive_write_set_format(m_archive, archiveConfiguration.GetLibArchiveArchiveType())); ChkErr(archive_write_set_format(m_archive, archiveConfiguration.GetLibArchiveArchiveType()));
if (archiveConfiguration.type == ArchiveType::TAR) if (archiveConfiguration.type == ArchiveType::TAR)
{ {
ChkErr(archive_write_add_filter(m_archive, archiveConfiguration.GetLibArchiveCompressionType())); ChkErr(archive_write_add_filter(m_archive, archiveConfiguration.GetLibArchiveCompressionType()));
} }
if (archiveConfiguration.compression != CompressionType::NONE && if (archiveConfiguration.compression != CompressionType::NONE &&
archiveConfiguration.compressionLevel > 0) archiveConfiguration.compressionLevel > 0)
{ {
std::string level = "compression-level=" + std::to_string(archiveConfiguration.compressionLevel); std::string level = "compression-level=" + std::to_string(archiveConfiguration.compressionLevel);
ChkErr(archive_write_set_options(m_archive, level.c_str())); ChkErr(archive_write_set_options(m_archive, level.c_str()));
} }
if (password) ChkErr(archive_write_set_passphrase(m_archive, password)); if (password) ChkErr(archive_write_set_passphrase(m_archive, password));
}
ArchiveWriter::ArchiveWriter(const char* fileName, ArchiveConfiguration archiveConfiguration, const std::shared_ptr<spdlog::logger>& logger, const char* password)
: ArchiveWriter(archiveConfiguration, logger, password)
{
ChkErr(archive_write_open_filename(m_archive, fileName)); ChkErr(archive_write_open_filename(m_archive, fileName));
} }
ArchiveWriter::ArchiveWriter(const std::filesystem::path& fileName, ArchiveConfiguration archiveConfiguration, const std::shared_ptr<spdlog::logger>& logger, const char* password) ArchiveWriter::ArchiveWriter(const std::filesystem::path& fileName, ArchiveConfiguration archiveConfiguration, const std::shared_ptr<spdlog::logger>& logger, const char* password)
: ArchiveBase(archive_write_new(), archive_entry_new(), logger) : ArchiveWriter(archiveConfiguration, logger, password)
, m_archiveConfig(archiveConfiguration) {
, m_shouldCompress(&SimpleFileTypeShouldCompressChecker) #pragma clang diagnostic push
{ //TODO error handling #pragma ide diagnostic ignored "UnreachableCode"
ChkErr(archive_write_set_format(m_archive, archiveConfiguration.GetLibArchiveArchiveType()));
if (archiveConfiguration.type == ArchiveType::TAR)
{
ChkErr(archive_write_add_filter(m_archive, archiveConfiguration.GetLibArchiveCompressionType()));
}
if (archiveConfiguration.compression != CompressionType::NONE &&
archiveConfiguration.compressionLevel > 0)
{
std::string level = "compression-level=" + std::to_string(archiveConfiguration.compressionLevel);
ChkErr(archive_write_set_options(m_archive, level.c_str()));
}
if (password) ChkErr(archive_write_set_passphrase(m_archive, password));
if constexpr (std::is_same_v<std::filesystem::path::value_type, char>) if constexpr (std::is_same_v<std::filesystem::path::value_type, char>)
ChkErr(archive_write_open_filename(m_archive, (const char*)fileName.c_str())); ChkErr(archive_write_open_filename(m_archive, (const char*)fileName.c_str()));
else else
ChkErr(archive_write_open_filename_w(m_archive, (const wchar_t*)fileName.c_str())); ChkErr(archive_write_open_filename_w(m_archive, (const wchar_t*)fileName.c_str()));
#pragma clang diagnostic pop
}
namespace
{
static int LibArchiveFileOpen(struct archive* a, void* clientData)
{
(void)clientData; /* UNUSED */
archive_write_set_bytes_in_last_block(a, 1);
return (ARCHIVE_OK);
}
static ssize_t LibArchiveFileWrite(struct archive* a, void* clientData, const void* buff, size_t length)
{
FILE* file = (FILE*)clientData;
size_t bytesWritten;
while (true)
{
bytesWritten = fwrite(buff, 1, length, file);
if (bytesWritten <= 0)
{
if (errno == EINTR) continue;
archive_set_error(a, errno, "Write error");
return (-1);
}
return (bytesWritten);
}
}
}
ArchiveWriter::ArchiveWriter(FILE* file, ArchiveConfiguration archiveConfiguration, const std::shared_ptr<spdlog::logger>& logger, const char* password)
: ArchiveWriter(archiveConfiguration, logger, password)
{
ChkErr(archive_write_open2(m_archive, file, LibArchiveFileOpen, LibArchiveFileWrite, NULL, NULL));
} }
ArchiveWriter::~ArchiveWriter() ArchiveWriter::~ArchiveWriter()

View File

@@ -26,6 +26,8 @@ namespace OpenVulkano
bool m_lastCompressed = true; bool m_lastCompressed = true;
std::function<bool(const FileDescription&)> m_shouldCompress; std::function<bool(const FileDescription&)> m_shouldCompress;
ArchiveWriter(ArchiveConfiguration archiveConfiguration, const std::shared_ptr<spdlog::logger>& logger, const char* password);
public: public:
ArchiveWriter(const char* fileName, const std::shared_ptr<spdlog::logger>& logger = nullptr, const char* password = nullptr) ArchiveWriter(const char* fileName, const std::shared_ptr<spdlog::logger>& logger = nullptr, const char* password = nullptr)
: ArchiveWriter(fileName, ArchiveConfiguration::FromFileName(fileName), logger, password) : ArchiveWriter(fileName, ArchiveConfiguration::FromFileName(fileName), logger, password)
@@ -39,6 +41,8 @@ namespace OpenVulkano
ArchiveWriter(const std::filesystem::path& fileName, ArchiveConfiguration archiveConfiguration, const std::shared_ptr<spdlog::logger>& logger = nullptr, const char* password = nullptr); ArchiveWriter(const std::filesystem::path& fileName, ArchiveConfiguration archiveConfiguration, const std::shared_ptr<spdlog::logger>& logger = nullptr, const char* password = nullptr);
ArchiveWriter(FILE* file, ArchiveConfiguration archiveConfiguration, const std::shared_ptr<spdlog::logger>& logger = nullptr, const char* password = nullptr);
~ArchiveWriter() override; ~ArchiveWriter() override;
[[nodiscard]] size_t GetTotalWrittenBytes() const { return m_bytesWritten; } [[nodiscard]] size_t GetTotalWrittenBytes() const { return m_bytesWritten; }