100 lines
3.3 KiB
C++
100 lines
3.3 KiB
C++
|
#include <hex/helpers/tar.hpp>
|
||
|
#include <hex/helpers/literals.hpp>
|
||
|
#include <hex/helpers/file.hpp>
|
||
|
|
||
|
namespace hex {
|
||
|
|
||
|
using namespace hex::literals;
|
||
|
|
||
|
Tar::Tar(const std::fs::path &path, Mode mode) {
|
||
|
if (mode == Tar::Mode::Read)
|
||
|
mtar_open(&this->m_ctx, path.string().c_str(), "r");
|
||
|
else if (mode == Tar::Mode::Write)
|
||
|
mtar_open(&this->m_ctx, path.string().c_str(), "a");
|
||
|
else if (mode == Tar::Mode::Create)
|
||
|
mtar_open(&this->m_ctx, path.string().c_str(), "w");
|
||
|
}
|
||
|
|
||
|
Tar::~Tar() {
|
||
|
mtar_finalize(&this->m_ctx);
|
||
|
mtar_close(&this->m_ctx);
|
||
|
}
|
||
|
|
||
|
std::vector<std::fs::path> Tar::listEntries() {
|
||
|
std::vector<std::fs::path> result;
|
||
|
|
||
|
const std::string PaxHeaderName = "@PaxHeader";
|
||
|
mtar_header_t header;
|
||
|
while (mtar_read_header(&this->m_ctx, &header) != MTAR_ENULLRECORD) {
|
||
|
if (header.name != PaxHeaderName) {
|
||
|
result.emplace_back(header.name);
|
||
|
}
|
||
|
|
||
|
mtar_next(&this->m_ctx);
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
std::vector<u8> Tar::read(const std::fs::path &path) {
|
||
|
mtar_header_t header;
|
||
|
mtar_find(&this->m_ctx, path.string().c_str(), &header);
|
||
|
|
||
|
std::vector<u8> result(header.size, 0x00);
|
||
|
mtar_read_data(&this->m_ctx, result.data(), result.size());
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
void Tar::write(const std::fs::path &path, const std::vector<u8> &data) {
|
||
|
if (path.has_parent_path()) {
|
||
|
std::fs::path pathPart;
|
||
|
for (const auto &part : path.parent_path()) {
|
||
|
pathPart /= part;
|
||
|
mtar_write_dir_header(&this->m_ctx, pathPart.string().c_str());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
mtar_write_file_header(&this->m_ctx, path.string().c_str(), data.size());
|
||
|
mtar_write_data(&this->m_ctx, data.data(), data.size());
|
||
|
}
|
||
|
|
||
|
void Tar::extract(const std::fs::path &path, const std::fs::path &outputPath) {
|
||
|
mtar_header_t header;
|
||
|
mtar_find(&this->m_ctx, path.string().c_str(), &header);
|
||
|
|
||
|
constexpr static u64 BufferSize = 1_MiB;
|
||
|
|
||
|
fs::File outputFile(outputPath, fs::File::Mode::Create);
|
||
|
|
||
|
std::vector<u8> buffer(BufferSize, 0x00);
|
||
|
for (u64 offset = 0; offset < header.size; offset += BufferSize) {
|
||
|
mtar_read_data(&this->m_ctx, buffer.data(), std::min(BufferSize, header.size - offset));
|
||
|
outputFile.write(buffer);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Tar::extractAll(const std::fs::path &outputPath) {
|
||
|
constexpr static u64 BufferSize = 1_MiB;
|
||
|
|
||
|
mtar_header_t header;
|
||
|
while (mtar_read_header(&this->m_ctx, &header) != MTAR_ENULLRECORD) {
|
||
|
const auto filePath = std::fs::absolute(outputPath / std::fs::path(header.name));
|
||
|
|
||
|
if (filePath.filename() != "@PaxHeader") {
|
||
|
|
||
|
std::fs::create_directories(filePath.parent_path());
|
||
|
fs::File outputFile(filePath, fs::File::Mode::Create);
|
||
|
|
||
|
std::vector<u8> buffer(BufferSize, 0x00);
|
||
|
for (u64 offset = 0; offset < header.size; offset += BufferSize) {
|
||
|
mtar_read_data(&this->m_ctx, buffer.data(), std::min(BufferSize, header.size - offset));
|
||
|
outputFile.write(buffer);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
mtar_next(&this->m_ctx);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|