sys: Refactor tar file operations into their own class
This commit is contained in:
parent
2a76e45dc5
commit
5e67a1f27b
@ -125,6 +125,7 @@ set(LIBIMHEX_SOURCES
|
|||||||
source/helpers/encoding_file.cpp
|
source/helpers/encoding_file.cpp
|
||||||
source/helpers/loader_script_handler.cpp
|
source/helpers/loader_script_handler.cpp
|
||||||
source/helpers/logger.cpp
|
source/helpers/logger.cpp
|
||||||
|
source/helpers/tar.cpp
|
||||||
|
|
||||||
source/providers/provider.cpp
|
source/providers/provider.cpp
|
||||||
|
|
||||||
|
@ -50,6 +50,12 @@ namespace hex::fs {
|
|||||||
return std::filesystem::remove(path, error) && !error;
|
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]]
|
[[maybe_unused]]
|
||||||
static inline uintmax_t getFileSize(const std::fs::path &path) {
|
static inline uintmax_t getFileSize(const std::fs::path &path) {
|
||||||
std::error_code error;
|
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/magic.hpp>
|
||||||
#include <hex/helpers/file.hpp>
|
#include <hex/helpers/file.hpp>
|
||||||
#include <hex/helpers/fs.hpp>
|
#include <hex/helpers/fs.hpp>
|
||||||
|
#include <hex/helpers/tar.hpp>
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
#include <microtar.h>
|
|
||||||
|
|
||||||
namespace hex::plugin::builtin {
|
namespace hex::plugin::builtin {
|
||||||
|
|
||||||
@ -76,34 +76,8 @@ namespace hex::plugin::builtin {
|
|||||||
entry.hasUpdate = false;
|
entry.hasUpdate = false;
|
||||||
|
|
||||||
if (entry.isFolder) {
|
if (entry.isFolder) {
|
||||||
mtar_t ctx;
|
Tar tar(this->m_downloadPath, Tar::Mode::Read);
|
||||||
mtar_open(&ctx, this->m_downloadPath.string().c_str(), "r");
|
tar.extractAll(this->m_downloadPath.parent_path() / this->m_downloadPath.stem());
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadDoneCallback(entry);
|
downloadDoneCallback(entry);
|
||||||
@ -257,12 +231,15 @@ namespace hex::plugin::builtin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ViewStore::remove(fs::ImHexPath pathType, const std::string &fileName) {
|
bool ViewStore::remove(fs::ImHexPath pathType, const std::string &fileName) {
|
||||||
bool removed = false;
|
bool removed = true;
|
||||||
for (const auto &path : fs::getDefaultPaths(pathType)) {
|
for (const auto &path : fs::getDefaultPaths(pathType)) {
|
||||||
bool removedFile = fs::remove(path / std::fs::path(fileName));
|
const auto filePath = path / fileName;
|
||||||
bool removedFolder = fs::remove(path / std::fs::path(fileName).stem());
|
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;
|
return removed;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user