diff --git a/.gitignore b/.gitignore index c8a371a..dedee73 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ # Dont'd add IDE files cmake-build-* -.ide* +.idea .vscode # Don't add generated headers diff --git a/build.sh b/build.sh index 5f6a0f7..6460932 100755 --- a/build.sh +++ b/build.sh @@ -62,7 +62,7 @@ build() { done 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)) echo "$a build complete, artifacts: $PWD/build_$a" done diff --git a/src/FunctionManager.cpp b/src/FunctionManager.cpp index 090fe80..ed43e31 100644 --- a/src/FunctionManager.cpp +++ b/src/FunctionManager.cpp @@ -78,7 +78,7 @@ void basic_function_manager::registerFunction( } } 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)); LOGN(PMTF, INFO) << _functions.back()->name() << " successfully registered." << std::endl; diff --git a/src/PartitionManager.cpp b/src/PartitionManager.cpp index acc3b07..83c6121 100644 --- a/src/PartitionManager.cpp +++ b/src/PartitionManager.cpp @@ -55,9 +55,11 @@ static void sigHandler(const int sig) { static int write(void *cookie, const char *buf, const int size) { auto *real = static_cast(cookie); - if (!Variables->quietProcess) - return fwrite(buf, 1, static_cast(size), real); - else return size; + if (!Variables->quietProcess) { + const int ret = fwrite(buf, 1, static_cast(size), real); + fflush(real); + return ret; + } else return size; } static FILE *make_fp(FILE *real) { @@ -68,10 +70,11 @@ auto Variables = std::make_unique(); FILE *pstdout = make_fp(stdout); FILE *pstderr = make_fp(stderr); +static Helper::garbageCollector collector; + int Main(int argc, char **argv) { try { // try-catch start - Helper::garbageCollector collector; collector.closeAfterProgress(pstdout); collector.closeAfterProgress(pstderr); @@ -146,14 +149,14 @@ int Main(int argc, char **argv) { Helper::hasAdbPermissions()) || FuncManager.isUsed("memoryTestFunction"))) 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; } catch (Helper::Error &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()); return EXIT_FAILURE; } catch (CLI::Error &error) { diff --git a/src/functions/InfoFunction.cpp b/src/functions/InfoFunction.cpp index 17af290..79c6525 100644 --- a/src/functions/InfoFunction.cpp +++ b/src/functions/InfoFunction.cpp @@ -30,8 +30,10 @@ INIT(infoFunction) { << std::endl; cmd = _app.add_subcommand("info", "Tell info(s) of input partition list") ->footer("Use get-all or getvar-all as partition name for getting " - "info's of all " - "partitions."); + "info's of all partitions.\nUse get-logicals as partition " + "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).") ->required() ->delimiter(','); @@ -55,19 +57,11 @@ INIT(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 jParts; - 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)) { + auto func = [this, + &jParts](std::string partition, + const PartitionMap::Map_t::BasicInf props) -> bool { + if (Variables->onLogical && !props.isLogical) { if (Variables->forceProcess) LOGN(IFUN, WARNING) << "Partition " << partition @@ -79,18 +73,25 @@ RUN(infoFunction) { } if (jsonFormat) - jParts.push_back({partition, - {Variables->PartMap->sizeOf(partition), - Variables->PartMap->isLogical(partition)}}); + jParts.push_back({partition, {props.size, props.isLogical}}); else #ifdef __LP64__ println("partition=%s size=%lu isLogical=%s", #else println("partition=%s size=%llu isLogical=%s", #endif - partition.data(), Variables->PartMap->sizeOf(partition), - Variables->PartMap->isLogical(partition) ? "true" : "false"); - } + partition.data(), props.size, props.isLogical ? "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) { nlohmann::json j; diff --git a/src/functions/MemoryTestFunction.cpp b/src/functions/MemoryTestFunction.cpp index 770dd4d..31e5f8c 100644 --- a/src/functions/MemoryTestFunction.cpp +++ b/src/functions/MemoryTestFunction.cpp @@ -74,15 +74,14 @@ RUN(memoryTestFunction) { const int wfd = Helper::openAndAddToCloseList( test, collector, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, 0644); - if (wfd < 0) - throw Error("Can't open/create test file: %s\n", strerror(errno)); + if (wfd < 0) throw Error("Can't open/create test file: %s", strerror(errno)); LOGN(MTFUN, INFO) << "Sequential write test started!" << std::endl; const auto startWrite = std::chrono::high_resolution_clock::now(); ssize_t bytesWritten = 0; while (bytesWritten < testFileSize) { 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; } @@ -101,7 +100,7 @@ RUN(memoryTestFunction) { (reinterpret_cast(rawBuffer) + 4096 - 1) & ~(4096 - 1)); const int rfd = 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; const auto startRead = std::chrono::high_resolution_clock::now(); diff --git a/src/functions/PartitionSizeFunction.cpp b/src/functions/PartitionSizeFunction.cpp index 0a9c5f3..07c3283 100644 --- a/src/functions/PartitionSizeFunction.cpp +++ b/src/functions/PartitionSizeFunction.cpp @@ -33,8 +33,10 @@ INIT(partitionSizeFunction) { << std::endl; cmd = _app.add_subcommand("sizeof", "Tell size(s) of input partition list") ->footer("Use get-all or getvar-all as partition name for getting " - "sizes of all " - "partitions."); + "sizes of all partitions.\nUse get-logicals as partition " + "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).") ->required() ->delimiter(','); @@ -58,18 +60,9 @@ INIT(partitionSizeFunction) { } RUN(partitionSizeFunction) { - 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()); - } - - 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)) { + auto func = [this](std::string partition, + PartitionMap::Map_t::BasicInf props) -> bool { + if (Variables->onLogical && !props.isLogical) { if (Variables->forceProcess) LOGN(SFUN, WARNING) << "Partition " << partition @@ -86,15 +79,21 @@ RUN(partitionSizeFunction) { if (asMega) multiple = "MB"; if (asGiga) multiple = "GB"; - if (onlySize) - println( - "%s", - convertTo(Variables->PartMap->sizeOf(partition), multiple).data()); + if (onlySize) println("%s", convertTo(props.size, multiple).data()); else println("%s: %s%s", partition.data(), - convertTo(Variables->PartMap->sizeOf(partition), multiple).data(), - multiple.data()); - } + convertTo(props.size, 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; } diff --git a/src/functions/TypeFunction.cpp b/src/functions/TypeFunction.cpp index a9460f6..26490e3 100644 --- a/src/functions/TypeFunction.cpp +++ b/src/functions/TypeFunction.cpp @@ -50,8 +50,7 @@ RUN(typeFunction) { for (const auto &content : contents) { if (!Variables->PartMap->hasPartition(content) && !Helper::fileIsExists(content)) - throw Error("Couldn't find partition or image file: %s\n", - content.data()); + throw Error("Couldn't find partition or image file: %s", content.data()); bool found = false; for (const auto &[magic, name] : magics) { @@ -68,7 +67,7 @@ RUN(typeFunction) { } 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?)" : ""); } diff --git a/srclib/libpartition_map/include/libpartition_map/lib.hpp b/srclib/libpartition_map/include/libpartition_map/lib.hpp index f43c43d..4cead69 100644 --- a/srclib/libpartition_map/include/libpartition_map/lib.hpp +++ b/srclib/libpartition_map/include/libpartition_map/lib.hpp @@ -19,6 +19,7 @@ #include // for uint64_t #include +#include #include #include #include @@ -241,6 +242,31 @@ public: */ void clear(); + /** + * Do input function (lambda) for all partitions. + */ + void doForAllPartitions( + const std::function &func) const; + + /** + * Do input function (lambda) for physical partitions. + */ + void doForPhysicalPartitions( + const std::function &func) const; + + /** + * Do input function (lambda) for logical partitions. + */ + void doForLogicalPartitions( + const std::function &func) const; + + /** + * Do input function (lambda) for input partition list. + */ + void doForPartitionList( + const std::vector &partitions, + const std::function &func) const; + /** * The entered path is defined as the new search * directory and the search is performed in the entered @@ -303,6 +329,10 @@ public: * Get Map_t object reference */ Map_t &operator*(); + + /** + * Get constant Map_t object reference + */ const Map_t &operator*() const; }; diff --git a/srclib/libpartition_map/src/PartitionMap.cpp b/srclib/libpartition_map/src/PartitionMap.cpp index 5c24f7d..3570462 100644 --- a/srclib/libpartition_map/src/PartitionMap.cpp +++ b/srclib/libpartition_map/src/PartitionMap.cpp @@ -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, const bool logical) { + if (!Helper::directoryIsExists(path) && logical) { + LOGN(MAP, WARNING) << "This device not contains logical partitions." + << std::endl; + return {}; + } + Map_t map; std::vector entries{ 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()) - << "" << path - << "is exists but generated vector is empty " + << path + << " is exists but generated vector is empty " "(std::vector)." << std::endl; for (const auto &entry : entries) { @@ -269,6 +275,71 @@ bool basic_partition_map_builder::empty() const { return _current_map.empty(); } +void basic_partition_map_builder::doForAllPartitions( + const std::function &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 &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 &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 &partitions, + const std::function &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 basic_partition_map_builder::sizeOf(const std::string_view name) const { _map_build_check();