pmt: Introduce, fixup

- Fix pstderr file pointer.
 - Improve and add more functions on libpartition_map.
 - Improve functions.
This commit is contained in:
2025-08-28 23:13:52 +03:00
parent d7bd11165d
commit 1a9b4ff5ad
10 changed files with 161 additions and 59 deletions

2
.gitignore vendored
View File

@@ -1,6 +1,6 @@
# Dont'd add IDE files # Dont'd add IDE files
cmake-build-* cmake-build-*
.ide* .idea
.vscode .vscode
# Don't add generated headers # Don't add generated headers

View File

@@ -62,7 +62,7 @@ build() {
done done
for a in ${TARGET_ABI_LIST[@]}; do for a in ${TARGET_ABI_LIST[@]}; do
echo "Building $a artifacts..." echo "Building $a artifacts... Using $(($(nproc) - 2)) thread."
cmake --build build_$a -j$(($(nproc) - 2)) cmake --build build_$a -j$(($(nproc) - 2))
echo "$a build complete, artifacts: $PWD/build_$a" echo "$a build complete, artifacts: $PWD/build_$a"
done done

View File

@@ -78,7 +78,7 @@ void basic_function_manager::registerFunction(
} }
} }
if (!_func->init(_app)) if (!_func->init(_app))
throw Error("Cannot init function: %s\n", _func->name()); throw Error("Cannot init function: %s", _func->name());
_functions.push_back(std::move(_func)); _functions.push_back(std::move(_func));
LOGN(PMTF, INFO) << _functions.back()->name() << " successfully registered." LOGN(PMTF, INFO) << _functions.back()->name() << " successfully registered."
<< std::endl; << std::endl;

View File

@@ -55,9 +55,11 @@ static void sigHandler(const int sig) {
static int write(void *cookie, const char *buf, const int size) { static int write(void *cookie, const char *buf, const int size) {
auto *real = static_cast<FILE *>(cookie); auto *real = static_cast<FILE *>(cookie);
if (!Variables->quietProcess) if (!Variables->quietProcess) {
return fwrite(buf, 1, static_cast<size_t>(size), real); const int ret = fwrite(buf, 1, static_cast<size_t>(size), real);
else return size; fflush(real);
return ret;
} else return size;
} }
static FILE *make_fp(FILE *real) { static FILE *make_fp(FILE *real) {
@@ -68,10 +70,11 @@ auto Variables = std::make_unique<VariableTable>();
FILE *pstdout = make_fp(stdout); FILE *pstdout = make_fp(stdout);
FILE *pstderr = make_fp(stderr); FILE *pstderr = make_fp(stderr);
static Helper::garbageCollector collector;
int Main(int argc, char **argv) { int Main(int argc, char **argv) {
try { try {
// try-catch start // try-catch start
Helper::garbageCollector collector;
collector.closeAfterProgress(pstdout); collector.closeAfterProgress(pstdout);
collector.closeAfterProgress(pstderr); collector.closeAfterProgress(pstderr);
@@ -146,14 +149,14 @@ int Main(int argc, char **argv) {
Helper::hasAdbPermissions()) || Helper::hasAdbPermissions()) ||
FuncManager.isUsed("memoryTestFunction"))) FuncManager.isUsed("memoryTestFunction")))
throw Error( throw Error(
"Partition Manager Tool is requires super-user privileges!\n"); "Partition Manager Tool is requires super-user privileges!");
} }
return FuncManager.handleAll() == true ? EXIT_SUCCESS : EXIT_FAILURE; return FuncManager.handleAll() == true ? EXIT_SUCCESS : EXIT_FAILURE;
} catch (Helper::Error &error) { } catch (Helper::Error &error) {
// catch Helper::Error // catch Helper::Error
fprintf(pstderr, "%s%sERROR(S) OCCURRED:%s\n%s", RED, BOLD, STYLE_RESET, fprintf(pstderr, "%s%sERROR(S) OCCURRED:%s\n%s\n", RED, BOLD, STYLE_RESET,
error.what()); error.what());
return EXIT_FAILURE; return EXIT_FAILURE;
} catch (CLI::Error &error) { } catch (CLI::Error &error) {

View File

@@ -30,8 +30,10 @@ INIT(infoFunction) {
<< std::endl; << std::endl;
cmd = _app.add_subcommand("info", "Tell info(s) of input partition list") cmd = _app.add_subcommand("info", "Tell info(s) of input partition list")
->footer("Use get-all or getvar-all as partition name for getting " ->footer("Use get-all or getvar-all as partition name for getting "
"info's of all " "info's of all partitions.\nUse get-logicals as partition "
"partitions."); "name for getting info's of logical partitions.\n"
"Use get-physical as partition name for getting info's of "
"physical partitions.");
cmd->add_option("partition(s)", partitions, "Partition name(s).") cmd->add_option("partition(s)", partitions, "Partition name(s).")
->required() ->required()
->delimiter(','); ->delimiter(',');
@@ -55,19 +57,11 @@ INIT(infoFunction) {
} }
RUN(infoFunction) { RUN(infoFunction) {
if (partitions.back() == "get-all" || partitions.back() == "getvar-all") {
if (!Variables->PartMap->copyPartitionsToVector(partitions))
throw Error("Cannot get list of all partitions! See logs for more "
"information (%s)",
Helper::LoggingProperties::FILE.data());
}
std::vector<PartitionMap::Partition_t> jParts; std::vector<PartitionMap::Partition_t> jParts;
for (const auto &partition : partitions) { auto func = [this,
if (!Variables->PartMap->hasPartition(partition)) &jParts](std::string partition,
throw Error("Couldn't find partition: %s", partition.data()); const PartitionMap::Map_t::BasicInf props) -> bool {
if (Variables->onLogical && !props.isLogical) {
if (Variables->onLogical && !Variables->PartMap->isLogical(partition)) {
if (Variables->forceProcess) if (Variables->forceProcess)
LOGN(IFUN, WARNING) LOGN(IFUN, WARNING)
<< "Partition " << partition << "Partition " << partition
@@ -79,18 +73,25 @@ RUN(infoFunction) {
} }
if (jsonFormat) if (jsonFormat)
jParts.push_back({partition, jParts.push_back({partition, {props.size, props.isLogical}});
{Variables->PartMap->sizeOf(partition),
Variables->PartMap->isLogical(partition)}});
else else
#ifdef __LP64__ #ifdef __LP64__
println("partition=%s size=%lu isLogical=%s", println("partition=%s size=%lu isLogical=%s",
#else #else
println("partition=%s size=%llu isLogical=%s", println("partition=%s size=%llu isLogical=%s",
#endif #endif
partition.data(), Variables->PartMap->sizeOf(partition), partition.data(), props.size, props.isLogical ? "true" : "false");
Variables->PartMap->isLogical(partition) ? "true" : "false");
} return true;
};
if (partitions.back() == "get-all" || partitions.back() == "getvar-all")
Variables->PartMap->doForAllPartitions(func);
else if (partitions.back() == "get-logicals")
Variables->PartMap->doForLogicalPartitions(func);
else if (partitions.back() == "get-physicals")
Variables->PartMap->doForPhysicalPartitions(func);
else Variables->PartMap->doForPartitionList(partitions, func);
if (jsonFormat) { if (jsonFormat) {
nlohmann::json j; nlohmann::json j;

View File

@@ -74,15 +74,14 @@ RUN(memoryTestFunction) {
const int wfd = Helper::openAndAddToCloseList( const int wfd = Helper::openAndAddToCloseList(
test, collector, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, 0644); test, collector, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, 0644);
if (wfd < 0) if (wfd < 0) throw Error("Can't open/create test file: %s", strerror(errno));
throw Error("Can't open/create test file: %s\n", strerror(errno));
LOGN(MTFUN, INFO) << "Sequential write test started!" << std::endl; LOGN(MTFUN, INFO) << "Sequential write test started!" << std::endl;
const auto startWrite = std::chrono::high_resolution_clock::now(); const auto startWrite = std::chrono::high_resolution_clock::now();
ssize_t bytesWritten = 0; ssize_t bytesWritten = 0;
while (bytesWritten < testFileSize) { while (bytesWritten < testFileSize) {
const ssize_t ret = write(wfd, buffer, bufferSize); const ssize_t ret = write(wfd, buffer, bufferSize);
if (ret < 0) throw Error("Can't write to test file: %s\n", strerror(errno)); if (ret < 0) throw Error("Can't write to test file: %s", strerror(errno));
bytesWritten += ret; bytesWritten += ret;
} }
@@ -101,7 +100,7 @@ RUN(memoryTestFunction) {
(reinterpret_cast<uintptr_t>(rawBuffer) + 4096 - 1) & ~(4096 - 1)); (reinterpret_cast<uintptr_t>(rawBuffer) + 4096 - 1) & ~(4096 - 1));
const int rfd = const int rfd =
Helper::openAndAddToCloseList(test, collector, O_RDONLY | O_DIRECT); Helper::openAndAddToCloseList(test, collector, O_RDONLY | O_DIRECT);
if (rfd < 0) throw Error("Can't open test file: %s\n", strerror(errno)); if (rfd < 0) throw Error("Can't open test file: %s", strerror(errno));
LOGN(MTFUN, INFO) << "Sequential read test started!" << std::endl; LOGN(MTFUN, INFO) << "Sequential read test started!" << std::endl;
const auto startRead = std::chrono::high_resolution_clock::now(); const auto startRead = std::chrono::high_resolution_clock::now();

View File

@@ -33,8 +33,10 @@ INIT(partitionSizeFunction) {
<< std::endl; << std::endl;
cmd = _app.add_subcommand("sizeof", "Tell size(s) of input partition list") cmd = _app.add_subcommand("sizeof", "Tell size(s) of input partition list")
->footer("Use get-all or getvar-all as partition name for getting " ->footer("Use get-all or getvar-all as partition name for getting "
"sizes of all " "sizes of all partitions.\nUse get-logicals as partition "
"partitions."); "name for getting sizes of logical partitions.\n"
"Use get-physical as partition name for getting sizes of "
"physical partitions.");
cmd->add_option("partition(s)", partitions, "Partition name(s).") cmd->add_option("partition(s)", partitions, "Partition name(s).")
->required() ->required()
->delimiter(','); ->delimiter(',');
@@ -58,18 +60,9 @@ INIT(partitionSizeFunction) {
} }
RUN(partitionSizeFunction) { RUN(partitionSizeFunction) {
if (partitions.back() == "get-all" || partitions.back() == "getvar-all") { auto func = [this](std::string partition,
if (!Variables->PartMap->copyPartitionsToVector(partitions)) PartitionMap::Map_t::BasicInf props) -> bool {
throw Error("Cannot get list of all partitions! See logs for more " if (Variables->onLogical && !props.isLogical) {
"information (%s)",
Helper::LoggingProperties::FILE.data());
}
for (const auto &partition : partitions) {
if (!Variables->PartMap->hasPartition(partition))
throw Error("Couldn't find partition: %s", partition.data());
if (Variables->onLogical && !Variables->PartMap->isLogical(partition)) {
if (Variables->forceProcess) if (Variables->forceProcess)
LOGN(SFUN, WARNING) LOGN(SFUN, WARNING)
<< "Partition " << partition << "Partition " << partition
@@ -86,15 +79,21 @@ RUN(partitionSizeFunction) {
if (asMega) multiple = "MB"; if (asMega) multiple = "MB";
if (asGiga) multiple = "GB"; if (asGiga) multiple = "GB";
if (onlySize) if (onlySize) println("%s", convertTo(props.size, multiple).data());
println(
"%s",
convertTo(Variables->PartMap->sizeOf(partition), multiple).data());
else else
println("%s: %s%s", partition.data(), println("%s: %s%s", partition.data(),
convertTo(Variables->PartMap->sizeOf(partition), multiple).data(), convertTo(props.size, multiple).data(), multiple.data());
multiple.data());
} return true;
};
if (partitions.back() == "get-all" || partitions.back() == "getvar-all")
Variables->PartMap->doForAllPartitions(func);
else if (partitions.back() == "get-logicals")
Variables->PartMap->doForLogicalPartitions(func);
else if (partitions.back() == "get-physicals")
Variables->PartMap->doForPhysicalPartitions(func);
else Variables->PartMap->doForPartitionList(partitions, func);
return true; return true;
} }

View File

@@ -50,8 +50,7 @@ RUN(typeFunction) {
for (const auto &content : contents) { for (const auto &content : contents) {
if (!Variables->PartMap->hasPartition(content) && if (!Variables->PartMap->hasPartition(content) &&
!Helper::fileIsExists(content)) !Helper::fileIsExists(content))
throw Error("Couldn't find partition or image file: %s\n", throw Error("Couldn't find partition or image file: %s", content.data());
content.data());
bool found = false; bool found = false;
for (const auto &[magic, name] : magics) { for (const auto &[magic, name] : magics) {
@@ -68,7 +67,7 @@ RUN(typeFunction) {
} }
if (!found) if (!found)
throw Error("Couldn't determine type of %s%s\n", content.data(), throw Error("Couldn't determine type of %s%s", content.data(),
content == "userdata" ? " (encrypted file system?)" : ""); content == "userdata" ? " (encrypted file system?)" : "");
} }

View File

@@ -19,6 +19,7 @@
#include <cstdint> // for uint64_t #include <cstdint> // for uint64_t
#include <exception> #include <exception>
#include <functional>
#include <libhelper/lib.hpp> #include <libhelper/lib.hpp>
#include <list> #include <list>
#include <memory> #include <memory>
@@ -241,6 +242,31 @@ public:
*/ */
void clear(); void clear();
/**
* Do input function (lambda) for all partitions.
*/
void doForAllPartitions(
const std::function<bool(std::string, Map_t::BasicInf)> &func) const;
/**
* Do input function (lambda) for physical partitions.
*/
void doForPhysicalPartitions(
const std::function<bool(std::string, Map_t::BasicInf)> &func) const;
/**
* Do input function (lambda) for logical partitions.
*/
void doForLogicalPartitions(
const std::function<bool(std::string, Map_t::BasicInf)> &func) const;
/**
* Do input function (lambda) for input partition list.
*/
void doForPartitionList(
const std::vector<std::string> &partitions,
const std::function<bool(std::string, Map_t::BasicInf)> &func) const;
/** /**
* The entered path is defined as the new search * The entered path is defined as the new search
* directory and the search is performed in the entered * directory and the search is performed in the entered
@@ -303,6 +329,10 @@ public:
* Get Map_t object reference * Get Map_t object reference
*/ */
Map_t &operator*(); Map_t &operator*();
/**
* Get constant Map_t object reference
*/
const Map_t &operator*() const; const Map_t &operator*() const;
}; };

View File

@@ -50,6 +50,12 @@ bool basic_partition_map_builder::_is_real_block_dir(
Map_t basic_partition_map_builder::_build_map(std::string_view path, Map_t basic_partition_map_builder::_build_map(std::string_view path,
const bool logical) { const bool logical) {
if (!Helper::directoryIsExists(path) && logical) {
LOGN(MAP, WARNING) << "This device not contains logical partitions."
<< std::endl;
return {};
}
Map_t map; Map_t map;
std::vector<std::filesystem::directory_entry> entries{ std::vector<std::filesystem::directory_entry> entries{
std::filesystem::directory_iterator(path), std::filesystem::directory_iterator(path),
@@ -59,8 +65,8 @@ Map_t basic_partition_map_builder::_build_map(std::string_view path,
}); });
LOGN_IF(MAP, WARNING, entries.empty()) LOGN_IF(MAP, WARNING, entries.empty())
<< "" << path << path
<< "is exists but generated vector is empty " << " is exists but generated vector is empty "
"(std::vector<std::filesystem::directory_entry>)." "(std::vector<std::filesystem::directory_entry>)."
<< std::endl; << std::endl;
for (const auto &entry : entries) { for (const auto &entry : entries) {
@@ -269,6 +275,71 @@ bool basic_partition_map_builder::empty() const {
return _current_map.empty(); return _current_map.empty();
} }
void basic_partition_map_builder::doForAllPartitions(
const std::function<bool(std::string, Map_t::BasicInf)> &func) const {
_map_build_check();
LOGN(MAP, INFO) << "Doing input function for all partitions." << std::endl;
for (const auto &[name, props] : _current_map) {
if (func(name, {props.size, props.isLogical}))
LOGN(MAP, INFO) << "Done progress for " << name << " partition."
<< std::endl;
else
LOGN(MAP, ERROR) << "Failed progress for " << name << " partition."
<< std::endl;
}
}
void basic_partition_map_builder::doForPhysicalPartitions(
const std::function<bool(std::string, Map_t::BasicInf)> &func) const {
_map_build_check();
LOGN(MAP, INFO) << "Doing input function for physical partitions."
<< std::endl;
for (const auto &[name, props] : _current_map) {
if (props.isLogical) continue;
if (func(name, {props.size, props.isLogical}))
LOGN(MAP, INFO) << "Done progress for " << name << " partition."
<< std::endl;
else
LOGN(MAP, ERROR) << "Failed progress for " << name << " partition."
<< std::endl;
}
}
void basic_partition_map_builder::doForLogicalPartitions(
const std::function<bool(std::string, Map_t::BasicInf)> &func) const {
_map_build_check();
LOGN(MAP, INFO) << "Doing input function for logical partitions."
<< std::endl;
for (const auto &[name, props] : _current_map) {
if (!props.isLogical) continue;
if (func(name, {props.size, props.isLogical}))
LOGN(MAP, INFO) << "Done progress for " << name << " partition."
<< std::endl;
else
LOGN(MAP, ERROR) << "Failed progress for " << name << " partition."
<< std::endl;
}
}
void basic_partition_map_builder::doForPartitionList(
const std::vector<std::string> &partitions,
const std::function<bool(std::string, Map_t::BasicInf)> &func) const {
_map_build_check();
LOGN(MAP, INFO) << "Doing input function for input partition list."
<< std::endl;
for (const auto &partition : partitions) {
if (!hasPartition(partition))
throw Error("Couldn't find partition: %s", partition.data());
if (!func(partition, {sizeOf(partition), isLogical(partition)}))
LOGN(MAP, ERROR) << "Failed progress for partition: " << partition
<< std::endl;
}
}
uint64_t uint64_t
basic_partition_map_builder::sizeOf(const std::string_view name) const { basic_partition_map_builder::sizeOf(const std::string_view name) const {
_map_build_check(); _map_build_check();