Add FsProcess

This commit is contained in:
jakcron 2021-10-02 22:57:12 +08:00
parent 5f1e8b27de
commit 7a9ef48a38
2 changed files with 164 additions and 0 deletions

129
src/FsProcess.cpp Normal file
View file

@ -0,0 +1,129 @@
#include "FsProcess.h"
#include <iostream>
nstool::FsProcess::FsProcess() :
mModuleLabel("nstool::FsProcess"),
mInputFs(),
mShowFs(false),
mExtractPath()
{
}
void nstool::FsProcess::setInputFileSystem(const std::shared_ptr<tc::io::IStorage>& input_fs)
{
mInputFs = input_fs;
}
void nstool::FsProcess::setFsLabel(const std::string& fs_label)
{
mFsLabel = fs_label;
}
void nstool::FsProcess::setCliOutputMode(bool show_fs)
{
mShowFs = show_fs;
}
void nstool::FsProcess::setExtractPath(const tc::io::Path& extract_path)
{
mExtractPath = extract_path;
}
void nstool::FsProcess::process()
{
if (mInputFs == nullptr)
{
throw tc::InvalidOperationException(mModuleLabel, "No input filesystem");
}
if (mShowFs)
printFs();
if (mExtractPath.isSet())
extractFs();
}
void nstool::FsProcess::printFs()
{
fmt::print("[{:s}FsTree]\n", (mFsLabel.isSet() ? (mFsLabel.get() + "/") : ""));
visitDir(tc::io::Path("/"), tc::io::Path("/"), false, true);
}
void nstool::FsProcess::extractFs()
{
fmt::print("[{:s}FsExtract]\n", (mFsLabel.isSet() ? (mFsLabel.get() + "/") : ""));
visitDir(tc::io::Path("/"), mExtractPath.get(), true, false);
}
void nstool::FsProcess::visitDir(const tc::io::Path& v_path, const tc::io::Path& l_path, bool extract_fs, bool print_fs)
{
tc::io::LocalStorage local_fs;
// get listing for directory
tc::io::sDirectoryListing info;
mInputFs->getDirectoryListing(v_path, info);
if (print_fs)
{
for (size_t i = 0; i < v_path.size(); i++)
fmt::print(" ");;
fmt::print("{:s}/\n", ((v_path.size() == 1) ? "Root:" : v_path.back()));
}
if (extract_fs)
{
// create local dir
local_fs.createDirectory(l_path);
}
// iterate thru child files
tc::ByteData cache = tc::ByteData(0x10000);
size_t cache_read_len;
tc::io::Path out_path;
std::string out_path_str;
std::shared_ptr<tc::io::IStream> in_stream;
std::shared_ptr<tc::io::IStream> out_stream;
for (auto itr = info.file_list.begin(); itr != info.file_list.end(); itr++)
{
if (print_fs)
{
for (size_t i = 0; i < v_path.size(); i++)
fmt::print(" ");
fmt::print(" {:s}\n", *itr);
}
if (extract_fs)
{
// build out path
out_path = l_path + *itr;
tc::io::PathUtil::pathToUnixUTF8(out_path, out_path_str);
fmt::print("Saving {:s}...\n", out_path_str);
// begin export
mInputFs->openFile(v_path + *itr, tc::io::FileMode::Open, tc::io::FileAccess::Read, in_stream);
local_fs.openFile(out_path, tc::io::FileMode::OpenOrCreate, tc::io::FileAccess::Write, out_stream);
in_stream->seek(0, tc::io::SeekOrigin::Begin);
out_stream->seek(0, tc::io::SeekOrigin::Begin);
for (int64_t remaining_data = in_stream->length(); remaining_data > 0;)
{
cache_read_len = in_stream->read(cache.data(), cache.size());
if (cache_read_len == 0)
{
throw tc::io::IOException(mModuleLabel, fmt::format("Failed to read from {:s}file.", (mFsLabel.isSet() ? (mFsLabel.get() + " ") : "")));
}
out_stream->write(cache.data(), cache_read_len);
remaining_data -= int64_t(cache_read_len);
}
}
}
// iterate thru child dirs
for (auto itr = info.dir_list.begin(); itr != info.dir_list.end(); itr++)
{
visitDir(v_path + *itr, l_path + *itr, extract_fs, print_fs);
}
}

35
src/FsProcess.h Normal file
View file

@ -0,0 +1,35 @@
#pragma once
#include <tc/Optional.h>
#include <tc/io.h>
#include "types.h"
namespace nstool
{
class FsProcess
{
public:
FsProcess();
void setInputFileSystem(const std::shared_ptr<tc::io::IStorage>& input_fs);
void setFsLabel(const std::string& fs_label);
void setCliOutputMode(bool show_fs);
void setExtractPath(const tc::io::Path& extract_path);
void process();
private:
std::string mModuleLabel;
std::shared_ptr<tc::io::IStorage> mInputFs;
tc::Optional<std::string> mFsLabel;
bool mShowFs;
tc::Optional<tc::io::Path> mExtractPath;
void printFs();
void extractFs();
void visitDir(const tc::io::Path& v_path, const tc::io::Path& l_path, bool extract_fs, bool print_fs);
};
}