sys: Refactor tar file operations into their own class
This commit is contained in:
parent
2a76e45dc5
commit
5e67a1f27b
@ -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)
|
||||
|
@ -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;
|
||||
|
35
lib/libimhex/include/hex/helpers/tar.hpp
Normal file
35
lib/libimhex/include/hex/helpers/tar.hpp
Normal 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 = { };
|
||||
};
|
||||
|
||||
}
|
100
lib/libimhex/source/helpers/tar.cpp
Normal file
100
lib/libimhex/source/helpers/tar.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user