1
0
mirror of synced 2025-01-19 01:24:15 +01:00

sys: Refactor tar file operations into their own class

This commit is contained in:
WerWolv 2022-06-16 15:42:08 +02:00
parent 2a76e45dc5
commit 5e67a1f27b
5 changed files with 153 additions and 34 deletions

View File

@ -125,12 +125,13 @@ set(LIBIMHEX_SOURCES
source/helpers/encoding_file.cpp
source/helpers/loader_script_handler.cpp
source/helpers/logger.cpp
source/helpers/tar.cpp
source/providers/provider.cpp
source/ui/imgui_imhex_extensions.cpp
source/ui/view.cpp
)
)
if (APPLE)
set(OSX_11_0_SDK_PATH /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk)

View File

@ -50,6 +50,12 @@ namespace hex::fs {
return std::filesystem::remove(path, error) && !error;
}
[[maybe_unused]]
static inline bool removeAll(const std::fs::path &path) {
std::error_code error;
return std::filesystem::remove_all(path, error) && !error;
}
[[maybe_unused]]
static inline uintmax_t getFileSize(const std::fs::path &path) {
std::error_code error;

View File

@ -0,0 +1,35 @@
#pragma once
#include <hex.hpp>
#include <hex/helpers/fs.hpp>
#include <microtar.h>
namespace hex {
class Tar {
public:
enum class Mode {
Read,
Write,
Create
};
Tar() = default;
Tar(const std::fs::path &path, Mode mode);
~Tar();
std::vector<u8> read(const std::fs::path &path);
void write(const std::fs::path &path, const std::vector<u8> &data);
std::vector<std::fs::path> listEntries();
void extract(const std::fs::path &path, const std::fs::path &outputPath);
void extractAll(const std::fs::path &outputPath);
private:
mtar_t m_ctx = { };
};
}

View File

@ -0,0 +1,100 @@
#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);
}
}
}

View File

@ -12,12 +12,12 @@
#include <hex/helpers/magic.hpp>
#include <hex/helpers/file.hpp>
#include <hex/helpers/fs.hpp>
#include <hex/helpers/tar.hpp>
#include <fstream>
#include <filesystem>
#include <functional>
#include <nlohmann/json.hpp>
#include <microtar.h>
namespace hex::plugin::builtin {
@ -76,34 +76,8 @@ namespace hex::plugin::builtin {
entry.hasUpdate = false;
if (entry.isFolder) {
mtar_t ctx;
mtar_open(&ctx, this->m_downloadPath.string().c_str(), "r");
mtar_header_t header;
auto extractBasePath = this->m_downloadPath.parent_path() / this->m_downloadPath.stem();
while (mtar_read_header(&ctx, &header) != MTAR_ENULLRECORD) {
auto filePath = extractBasePath / std::fs::path(header.name);
if (filePath.filename() == "@PaxHeader") {
mtar_next(&ctx);
continue;
}
fs::createDirectories(filePath.parent_path());
fs::File outputFile(filePath.string(), fs::File::Mode::Create);
std::vector<u8> buffer(0x10000);
for (u64 offset = 0; offset < header.size; offset += buffer.size()) {
auto readSize = std::min<u64>(buffer.size(), header.size - offset);
mtar_read_data(&ctx, buffer.data(), readSize);
buffer.resize(readSize);
outputFile.write(buffer);
}
mtar_next(&ctx);
}
mtar_finalize(&ctx);
mtar_close(&ctx);
Tar tar(this->m_downloadPath, Tar::Mode::Read);
tar.extractAll(this->m_downloadPath.parent_path() / this->m_downloadPath.stem());
}
downloadDoneCallback(entry);
@ -257,12 +231,15 @@ namespace hex::plugin::builtin {
}
bool ViewStore::remove(fs::ImHexPath pathType, const std::string &fileName) {
bool removed = false;
bool removed = true;
for (const auto &path : fs::getDefaultPaths(pathType)) {
bool removedFile = fs::remove(path / std::fs::path(fileName));
bool removedFolder = fs::remove(path / std::fs::path(fileName).stem());
const auto filePath = path / fileName;
const auto folderPath = (path / std::fs::path(fileName).stem());
removed = removed || removedFile || removedFolder;
fs::remove(filePath);
fs::removeAll(folderPath);
removed = removed && !fs::exists(filePath) && !fs::exists(folderPath);
}
return removed;