/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ #pragma once #include #include #include #include "Base/Logger.hpp" namespace openVulkanoCpp { namespace LibArchiveHelper { constexpr mode_t FILE_TYPE_MAP[] = { AE_IFMT, AE_IFREG, AE_IFDIR, AE_IFLNK, AE_IFBLK, AE_IFCHR, AE_IFIFO, AE_IFSOCK, AE_IFMT }; constexpr std::filesystem::file_type GetFileType(mode_t type) { switch(type & AE_IFMT) { case AE_IFREG: return std::filesystem::file_type::regular; case AE_IFDIR: return std::filesystem::file_type::directory; case AE_IFLNK: return std::filesystem::file_type::symlink; case AE_IFBLK: return std::filesystem::file_type::block; case AE_IFCHR: return std::filesystem::file_type::character; case AE_IFIFO: return std::filesystem::file_type::fifo; case AE_IFSOCK: return std::filesystem::file_type::socket; } return std::filesystem::file_type::unknown; } constexpr mode_t GetFileType(std::filesystem::file_type type) { return FILE_TYPE_MAP[static_cast(type)]; } template inline ssize_t CopyArchiveData(struct archive* archiveReader, struct archive* archiveWriter) { const void* buffer; size_t size; ssize_t offset, r; while (true) { r = archive_read_data_block(archiveReader, &buffer, &size, &offset); if (r == ARCHIVE_EOF) return ARCHIVE_OK; if (r < ARCHIVE_OK) return r; if constexpr (BLOCK_WRITE) { r = archive_write_data_block(archiveWriter, buffer, size, offset); } else { r = archive_write_data(archiveWriter, buffer, size); } if (r < ARCHIVE_OK) return r; } } inline bool CheckError(int archiveResult, struct archive* arch, const Logger::Ptr& logger) { if (archiveResult >= ARCHIVE_OK) return true; spdlog::level::level_enum lvl = spdlog::level::level_enum::warn; 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 (archiveResult == ARCHIVE_FAILED) throw std::runtime_error(errorString); return false; } } class LibArchiveEntryStreamBuffer final : public std::streambuf { private: struct archive* m_archive; char* m_buffer; size_t m_currentBlockSize; ssize_t offset, r; bool ReadNextBlock() { const void* buffer; bool ok = archive_read_data_block(m_archive, &buffer, &m_currentBlockSize, &offset) == ARCHIVE_OK; m_buffer = static_cast(const_cast(buffer)); return ok; } public: LibArchiveEntryStreamBuffer(struct archive* arch) : m_archive(arch), m_currentBlockSize(0) {} int underflow() override { if (gptr() == egptr()) { if (ReadNextBlock()) { setg(m_buffer, m_buffer, m_buffer + m_currentBlockSize); } else { return std::char_traits::eof(); } } return std::char_traits::to_int_type(*this->gptr()); } }; }