pmt: ready for release

- Fix memory leaks
 - Writed functions and apply
 - Test pmt and verify stability
This commit is contained in:
2025-08-06 21:58:05 +03:00
parent 670f2bfad5
commit 6294482b39
29 changed files with 1033 additions and 502 deletions

43
src/CMakeLists.txt Normal file
View File

@@ -0,0 +1,43 @@
#
# Copyright 2025 Yağız Zengin
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
set(PMT_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/FunctionManager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/PartitionManager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Main.cpp
${CMAKE_CURRENT_SOURCE_DIR}/functions/BackupFunction.cpp
${CMAKE_CURRENT_SOURCE_DIR}/functions/EraseFunction.cpp
${CMAKE_CURRENT_SOURCE_DIR}/functions/FlashFunction.cpp
${CMAKE_CURRENT_SOURCE_DIR}/functions/InfoFunction.cpp
${CMAKE_CURRENT_SOURCE_DIR}/functions/PartitionSizeFunction.cpp
)
# Add pmt
add_executable(pmt ${PMT_SOURCES})
add_executable(pmt_static ${PMT_SOURCES})
# Set linker options
target_link_libraries(pmt PRIVATE helper_shared PRIVATE partition_map_shared)
target_link_libraries(pmt_static PRIVATE helper_static PRIVATE partition_map_static)
target_link_options(pmt PRIVATE "LINKER:-rpath,/data/data/com.termux/files/usr/lib")
target_link_options(pmt_static PRIVATE "LINKER:-rpath,/data/data/com.termux/files/usr/lib")
if(NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
target_compile_options(pmt PRIVATE -Os)
target_compile_options(pmt_static PRIVATE -Os)
target_link_options(pmt PRIVATE -s)
target_link_options(pmt_static PRIVATE -s)
endif()

View File

@@ -17,37 +17,56 @@
#include <vector>
#include <memory>
#include <string>
#include <PartitionManager/lib.hpp>
#include <unordered_set>
#include <PartitionManager/PartitionManager.hpp>
namespace PartitionManager {
std::vector<std::string> splitIfHasDelim(const std::string& s, const char delim, const bool checkForBadUsage)
{
if (s.find(delim) == std::string::npos) return {};
auto vec = CLI::detail::split(s, delim);
if (checkForBadUsage) {
std::unordered_set<std::string> set;
for (const auto& str : vec) {
if (set.find(str) != set.end()) throw CLI::ValidationError("Duplicate element in your inputs!");
set.insert(str);
}
}
return vec;
}
void processCommandLine(std::vector<std::string>& vec1, std::vector<std::string>& vec2, const std::string& s1, const std::string& s2, const char delim, const bool checkForBadUsage)
{
vec1 = splitIfHasDelim(s1, delim, checkForBadUsage);
vec2 = splitIfHasDelim(s2, delim, checkForBadUsage);
if (vec1.empty() && !s1.empty()) vec1.push_back(s1);
if (vec2.empty() && !s2.empty()) vec2.push_back(s2);
}
void basic_function_manager::registerFunction(std::unique_ptr<basic_function> _func, CLI::App& _app)
{
LOGN(PMTF, INFO) << "registering function: " << _func->name() << std::endl;
if (!_func->init(_app)) throw Error("Cannot init function: %s\n", _func->name());
_functions.push_back(std::move(_func));
LOGN(PMTF, INFO) << _func->name() << " successfully registered." << std::endl;
LOGN(PMTF, INFO) << _functions.back()->name() << " successfully registered." << std::endl;
}
const char* basic_function_manager::whatIsRunnedCommandName()
bool basic_function_manager::handleAll() const
{
for (auto &func : _functions) {
if (func->cmd->parsed()) return func->name();
}
return nullptr;
}
bool basic_function_manager::handleAll()
{
LOGN(PMTF, INFO) << "running catched function commands in command-line." << std::endl;
for (auto &func : _functions) {
if (func->cmd->parsed()) {
LOGN(PMTF, INFO) << "running function: " << func->name() << std::endl;
return (func->run()) ? true : false;
LOGN(PMTF, INFO) << "running caught function commands in command-line." << std::endl;
for (const auto& func : _functions) {
if (func->isUsed()) {
LOGN(PMTF, INFO) << func->name() << " is calling because used in command-line." << std::endl;
return func->run();
}
}
LOGN(PMTF, INFO) << "not found any used function from command-line." << std::endl;
print("Target progress is not specified. Specify a progress.");
return false;
}

View File

@@ -1,97 +0,0 @@
/*
Copyright 2025 Yağız Zengin
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <PartitionManager/lib.hpp>
#include <generated/buildInfo.hpp>
#include "functions/functions.hpp"
namespace PartitionManager {
basic_variables::basic_variables() : PartMap(),
searchPath(""),
onLogical(false),
silentProcess(false),
verboseMode(false),
viewVersion(false)
{}
VariableTable* Variables = new VariableTable();
int Main(int argc, char** argv)
{
try { // try-catch start
CLI::App AppMain{"Partition Manager Tool"};
FunctionManager FuncManager;
AppMain.add_option("-S,--search-path", Variables->searchPath, "Set partition search path");
AppMain.add_flag("-l,--logical", Variables->onLogical, "Specify that the target partition is dynamic");
AppMain.add_flag("-s,--silent", Variables->silentProcess, "The process is performed silently without any output.");
AppMain.add_flag("-V,--verbose", Variables->verboseMode, "Detailed information is written on the screen while the transaction is being carried out");
AppMain.add_flag("-v,--version", Variables->viewVersion, "Print version and exit");
FuncManager.registerFunction(std::make_unique<backupFunction>(), AppMain);
FuncManager.registerFunction(std::make_unique<flashFunction>(), AppMain);
FuncManager.registerFunction(std::make_unique<eraseFunction>(), AppMain);
FuncManager.registerFunction(std::make_unique<partitionSizeFunction>(), AppMain);
CLI11_PARSE(AppMain, argc, argv);
const char* used = FuncManager.whatIsRunnedCommandName();
if (used != nullptr)
LOGN(PMTE, INFO) << "used command: " << used << std::endl;
if (!Variables->searchPath.empty())
Variables->PartMap(Variables->searchPath);
if (!Variables->PartMap) {
if (Variables->searchPath.empty())
throw Error("No default search entries were found. Specify a search directory with -S (--search-path)");
}
FuncManager.handleAll();
} catch (Helper::Error &error) { // catch Helper::Error
if (!Variables->silentProcess) fprintf(stderr, "%s: %s.\n", argv[0], error.what());
delete Variables;
return -1;
} catch (CLI::ParseError &error) { // catch CLI::ParseError
fprintf(stderr, "%s: FLAG PARSE ERROR: %s\n", argv[0], error.what());
return -1;
} // try-catch block end
}
std::string getLibVersion()
{
char vinfo[512];
sprintf(vinfo, MKVERSION("libpmt"));
return std::string(vinfo);
}
std::string getAppVersion()
{
char vinfo[512];
sprintf(vinfo, MKVERSION("pmt"));
return std::string(vinfo);
}
} // namespace PartitionManager

View File

@@ -14,10 +14,11 @@
limitations under the License.
*/
#include <PartitionManager/lib.hpp>
#include <PartitionManager/PartitionManager.hpp>
int main(int argc, char** argv)
{
// Call integrated main function in library
Helper::LoggingProperties::setProgramName(PMTE);
return PartitionManager::Main(argc, argv);
}

119
src/PartitionManager.cpp Executable file
View File

@@ -0,0 +1,119 @@
/*
Copyright 2025 Yağız Zengin
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstdarg>
#include <PartitionManager/PartitionManager.hpp>
#include <generated/buildInfo.hpp>
#include "functions/functions.hpp"
namespace PartitionManager {
auto Variables = new VariableTable();
logSetter::logSetter() { Helper::LoggingProperties::setLogFile("/sdcard/Documents/last_pmt_logs.log"); }
basic_variables::~basic_variables() { delete PartMap; }
basic_variables::basic_variables() : PartMap(new PartitionMap::BuildMap()),
logFile("/sdcard/Documents/last_pmt_logs.log"),
onLogical(false),
quietProcess(false),
verboseMode(false),
viewVersion(false),
forceProcess(false)
{}
int Main(int argc, char** argv)
{
try { // try-catch start
CLI::App AppMain{"Partition Manager Tool"};
FunctionManager FuncManager;
AppMain.set_help_all_flag("--help-all", "Print full help message");
AppMain.footer("Partition Manager Tool is written by YZBruh\nThis project licensed under Apache 2.0 license\nReport bugs to https://github.com/ShawkTeam/pmt-renovated/issues");
AppMain.add_option("-S,--search-path", Variables->searchPath, "Set partition search path")->check([&](const std::string& val) {
if (val.find("/block/") == std::string::npos) throw CLI::ValidationError("Partition search path is unexpected! Couldn't find 'block' in input path!");
return std::string();
});
AppMain.add_option("-L,--log-file", Variables->logFile, "Set log file");
AppMain.add_flag("-f,--force", Variables->forceProcess, "Force process to be processed");
AppMain.add_flag("-l,--logical", Variables->onLogical, "Specify that the target partition is dynamic");
AppMain.add_flag("-q,--quiet", Variables->quietProcess, "Quiet process");
AppMain.add_flag("-V,--verbose", Variables->verboseMode, "Detailed information is written on the screen while the transaction is being carried out");
AppMain.add_flag("-v,--version", Variables->viewVersion, "Print version and exit");
if (argc < 2) {
print("Usage: %s [OPTIONS] [SUBCOMMAND]\nUse --help for more information.\n", argv[0]);
return EXIT_FAILURE;
}
FuncManager.registerFunction(std::make_unique<backupFunction>(), AppMain);
FuncManager.registerFunction(std::make_unique<flashFunction>(), AppMain);
FuncManager.registerFunction(std::make_unique<eraseFunction>(), AppMain);
FuncManager.registerFunction(std::make_unique<partitionSizeFunction>(), AppMain);
FuncManager.registerFunction(std::make_unique<infoFunction>(), AppMain);
CLI11_PARSE(AppMain, argc, argv);
if (Variables->verboseMode) Helper::LoggingProperties::setPrinting(YES);
if (Variables->viewVersion) {
print("%s\n", getAppVersion().data());
return EXIT_SUCCESS;
}
if (!Variables->searchPath.empty()) (*Variables->PartMap)(Variables->searchPath);
if (!Variables->PartMap && Variables->searchPath.empty())
throw Error("No default search entries were found. Specify a search directory with -S (--search-path)");
return FuncManager.handleAll() == true ? EXIT_SUCCESS : EXIT_FAILURE;
} catch (Helper::Error &error) { // catch Helper::Error
if (!Variables->quietProcess) fprintf(stderr, "%s: %s.\n", argv[0], error.what());
delete Variables;
return EXIT_FAILURE;
} catch (CLI::Error &error) { // catch CLI::Error
delete Variables;
fprintf(stderr, "%s: FLAG PARSE ERROR: %s\n", argv[0], error.what());
return EXIT_FAILURE;
} // try-catch block end
}
void print(const char* format, ...)
{
va_list args;
va_start(args, format);
if (!Variables->quietProcess) vfprintf(stdout, format, args);
va_end(args);
}
std::string getLibVersion()
{
MKVERSION(PMT);
}
std::string getAppVersion()
{
MKVERSION(PMTE);
}
} // namespace PartitionManager

View File

@@ -0,0 +1,101 @@
/*
Copyright 2025 Yağız Zengin
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <cstdlib>
#include <fcntl.h>
#include <cerrno>
#include <unistd.h>
#include <PartitionManager/PartitionManager.hpp>
#include "functions.hpp"
#define BFUN "backupFunction"
namespace PartitionManager {
bool backupFunction::init(CLI::App &_app)
{
LOGN(BFUN, INFO) << "Initializing variables of backup function." << std::endl;
cmd = _app.add_subcommand("backup", "Backup partition(s) to file(s)");
cmd->add_option("partition(s)", rawPartitions, "Partition name(s)")->required();
cmd->add_option("output(s)", rawOutputNames, "File name(s) (or path(s)) to save the partition image(s)");
cmd->add_option("-b,--buffer-size", bufferSize, "Buffer size for reading partition(s) and writing to file(s)");
return true;
}
bool backupFunction::run()
{
processCommandLine(partitions, outputNames, rawPartitions, rawOutputNames, ',', true);
if (!outputNames.empty() && partitions.size() != outputNames.size())
throw CLI::ValidationError("You must provide an output name(s) as long as the partition name(s)");
for (size_t i = 0; i < partitions.size(); i++) {
std::string partitionName = partitions[i];
std::string outputName = outputNames.empty() ? partitionName + ".img" : outputNames[i];
LOGN(BFUN, INFO) << "backupping " << partitionName << " as " << outputName << std::endl;
if (!Variables->PartMap->hasPartition(partitionName))
throw Error("Couldn't find partition: %s", partitionName.data());
if (Variables->onLogical && !Variables->PartMap->isLogical(partitionName)) {
if (Variables->forceProcess) LOGN(BFUN, WARNING) << "Partition " << partitionName << " is exists but not logical. Ignoring (from --force, -f)." << std::endl;
else throw Error("Used --logical (-l) flag but is not logical partition: %s", partitionName.data());
}
if (Helper::fileIsExists(outputName) && !Variables->forceProcess) throw Error("%s is exists. Remove it, or use --force (-f) flag.", outputName.data());
else LOGN(BFUN, INFO) << outputName << " is exists but ignoring (from --force, -f). Re-creating." << std::endl;
bufferSize = (Variables->PartMap->sizeOf(partitionName) % bufferSize == 0) ? bufferSize : 1;
LOGN(BFUN, INFO) << "Using buffer size: " << bufferSize << std::endl;
const int pfd = open(Variables->PartMap->getRealPathOf(partitionName).data(), O_RDONLY);
if (pfd < 0)
throw Error("Can't open partition: %s: %s", partitionName.data(), strerror(errno));
const int ffd = open(outputName.data(), O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (ffd < 0) {
close(pfd);
throw Error("Can't create/open output file %s: %s", outputName.data(), strerror(errno));
}
LOGN(BFUN, INFO) << "Writing partition " << partitionName << " to file: " << outputName << std::endl;
auto* buffer = new char[bufferSize];
memset(buffer, 0x00, bufferSize);
ssize_t bytesRead;
while ((bytesRead = read(pfd, buffer, bufferSize)) > 0) {
if (const ssize_t bytesWritten = write(ffd, buffer, bytesRead); bytesWritten != bytesRead) {
close(pfd);
close(ffd);
delete[] buffer;
throw Error("Can't write partition to output file %s: %s", outputName.data(), strerror(errno));
}
}
close(pfd);
close(ffd);
delete[] buffer;
}
LOGN(BFUN, INFO) << "Operation successfully completed." << std::endl;
return true;
}
bool backupFunction::isUsed() const { return cmd->parsed(); }
const char* backupFunction::name() const { return BFUN; }
} // namespace PartitionManager

View File

@@ -0,0 +1,86 @@
/*
Copyright 2025 Yağız Zengin
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <cstdlib>
#include <fcntl.h>
#include <cerrno>
#include <unistd.h>
#include <PartitionManager/PartitionManager.hpp>
#include "functions.hpp"
#define EFUN "eraseFunction"
namespace PartitionManager {
bool eraseFunction::init(CLI::App &_app)
{
LOGN(EFUN, INFO) << "Initializing variables of erase function." << std::endl;
cmd = _app.add_subcommand("erase", "Writes zero bytes to partition(s)");
cmd->add_option("partition(s)", partitions, "Partition name(s)")->required()->delimiter(',');
cmd->add_option("-b,--buffer-size", bufferSize, "Buffer size for writing zero bytes to partition(s)");
return true;
}
bool eraseFunction::run()
{
for (const auto& partitionName : partitions) {
if (!Variables->PartMap->hasPartition(partitionName))
throw Error("Couldn't find partition: %s", partitionName.data());
if (Variables->onLogical && !Variables->PartMap->isLogical(partitionName)) {
if (Variables->forceProcess) LOGN(EFUN, WARNING) << "Partition " << partitionName << " is exists but not logical. Ignoring (from --force, -f)." << std::endl;
else throw Error("Used --logical (-l) flag but is not logical partition: %s", partitionName.data());
}
bufferSize = (Variables->PartMap->sizeOf(partitionName) % bufferSize == 0) ? bufferSize : 1;
LOGN(EFUN, INFO) << "Using buffer size: " << bufferSize;
const int pfd = open(Variables->PartMap->getRealPathOf(partitionName).data(), O_WRONLY);
if (pfd < 0)
throw Error("Can't open partition: %s: %s", partitionName.data(), strerror(errno));
if (!Variables->forceProcess) Helper::confirmPropt("Are you sure you want to continue? This could render your device unusable! Do not continue if you do not know what you are doing!");
LOGN(EFUN, INFO) << "Writing zero bytes to partition: " << partitionName << std::endl;
auto* buffer = new char[bufferSize];
memset(buffer, 0x00, bufferSize);
ssize_t bytesWritten = 0;
const uint64_t partitionSize = Variables->PartMap->sizeOf(partitionName);
while (bytesWritten < partitionSize) {
size_t toWrite = sizeof(buffer);
if (partitionSize - bytesWritten < sizeof(buffer)) toWrite = partitionSize - bytesWritten;
if (const ssize_t result = write(pfd, buffer, toWrite); result == -1) {
close(pfd);
delete[] buffer;
throw Error("Can't write zero bytes to partition: %s: %s", partitionName.data(), strerror(errno));
} else bytesWritten += result;
}
close(pfd);
delete[] buffer;
}
LOGN(EFUN, INFO) << "Operation successfully completed." << std::endl;
return true;
}
bool eraseFunction::isUsed() const { return cmd->parsed(); }
const char* eraseFunction::name() const { return EFUN; }
} // namespace PartitionManager

View File

@@ -0,0 +1,104 @@
/*
Copyright 2025 Yağız Zengin
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <cstdlib>
#include <fcntl.h>
#include <cerrno>
#include <unistd.h>
#include <PartitionManager/PartitionManager.hpp>
#include "functions.hpp"
#define FFUN "flashFunction"
namespace PartitionManager {
bool flashFunction::init(CLI::App &_app)
{
LOGN(FFUN, INFO) << "Initializing variables of flash function." << std::endl;
cmd = _app.add_subcommand("flash", "Flash image(s) to partition(s)");
cmd->add_option("partition(s)", rawPartitions, "Partition name(s)")->required();
cmd->add_option("imageFile(s)", rawImageNames, "Name(s) of image file(s)")->required()->check([&](const std::string& val) {
const std::vector<std::string> inputs = splitIfHasDelim(val, ',');
for (const auto& input : inputs) {
if (!Helper::fileIsExists(input)) return std::string("Couldn't find image file: " + input);
}
return std::string();
});
cmd->add_option("-b,--buffer-size", bufferSize, "Buffer size for reading image(s) and writing to partition(s)");
return true;
}
bool flashFunction::run()
{
processCommandLine(partitions, imageNames, rawPartitions, rawImageNames, ',', true);
if (partitions.size() != imageNames.size())
throw CLI::ValidationError("You must provide an image file(s) as long as the partition name(s)");
for (size_t i = 0; i < partitions.size(); i++) {
std::string& partitionName = partitions[i];
std::string& imageName = imageNames[i];
LOGN(FFUN, INFO) << "flashing " << imageName << " to " << partitionName << std::endl;
if (!Variables->PartMap->hasPartition(partitionName))
throw Error("Couldn't find partition: %s", partitionName.data());
if (Variables->onLogical && !Variables->PartMap->isLogical(partitionName)) {
if (Variables->forceProcess) LOGN(FFUN, WARNING) << "Partition " << partitionName << " is exists but not logical. Ignoring (from --force, -f)." << std::endl;
else throw Error("Used --logical (-l) flag but is not logical partition: %s", partitionName.data());
}
bufferSize = (Helper::fileSize(imageName) % bufferSize == 0) ? bufferSize : 1;
LOGN(FFUN, INFO) << "Using buffer size: " << bufferSize;
const int ffd = open(imageName.data(), O_RDONLY);
if (ffd < 0) throw Error("Can't open image file %s: %s", imageName.data(), strerror(errno));
const int pfd = open(Variables->PartMap->getRealPathOf(partitionName).data(), O_RDWR | O_TRUNC);
if (pfd < 0) {
close(ffd);
throw Error("Can't open partition: %s: %s", partitionName.data(), strerror(errno));
}
LOGN(FFUN, INFO) << "Writing image " << imageName << " to partition: " << partitionName << std::endl;
auto* buffer = new char[bufferSize];
memset(buffer, 0x00, bufferSize);
ssize_t bytesRead;
while ((bytesRead = read(ffd, buffer, bufferSize)) > 0) {
if (const ssize_t bytesWritten = write(pfd, buffer, bytesRead); bytesWritten != bytesRead) {
close(pfd);
close(ffd);
delete[] buffer;
throw Error("Can't write partition to output file %s: %s", imageName.data(), strerror(errno));
}
}
close(pfd);
close(ffd);
delete[] buffer;
}
LOGN(FFUN, INFO) << "Operation successfully completed." << std::endl;
return true;
}
bool flashFunction::isUsed() const { return cmd->parsed(); }
const char* flashFunction::name() const { return FFUN; }
} // namespace PartitionManager

View File

@@ -0,0 +1,89 @@
/*
Copyright 2025 Yağız Zengin
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <cstdlib>
#include <fcntl.h>
#include <cerrno>
#include <unistd.h>
#include <PartitionManager/PartitionManager.hpp>
#include "functions.hpp"
#define IFUN "infoFunction"
namespace PartitionManager {
bool infoFunction::init(CLI::App &_app)
{
LOGN(IFUN, INFO) << "Initializing variables of info printer function." << std::endl;
cmd = _app.add_subcommand("info", "Tell info(s) of input partition list")->footer("Use get-all as partition name for getting info's of all partitions.");
cmd->add_option("partition(s)", partitions, "Partition name(s).")->required()->delimiter(',');
cmd->add_flag("-J,--json", jsonFormat, "Print info(s) as JSON body. The body of each partition will be written separately");
cmd->add_option("--json-partition-name", jNamePartition, "Speficy partition name element for JSON body");
cmd->add_option("--json-size-name", jNameSize, "Speficy size element name for JSON body");
cmd->add_option("--json-logical-name", jNameLogical, "Speficy logical element name for JSON body");
return true;
}
bool infoFunction::run()
{
if (partitions.back() == "get-all") {
partitions.clear();
const auto parts = Variables->PartMap->getPartitionList();
if (!parts) throw Error("Cannot get list of all partitions! See logs for more information (%s)", Helper::LoggingProperties::FILE.data());
for (const auto& name : *parts) partitions.push_back(name);
}
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) LOGN(IFUN, WARNING) << "Partition " << partition << " is exists but not logical. Ignoring (from --force, -f)." << std::endl;
else throw Error("Used --logical (-l) flag but is not logical partition: %s", partition.data());
}
if (jsonFormat)
#ifdef __LP64__
print("{\"%s\": \"%s\", \"%s\": %lu, \"%s\": %s}\n",
#else
print("{\"%s\": \"%s\", \"%s\": %llu, \"%s\": %s}\n",
#endif
jNamePartition.data(),
partition.data(),
jNameSize.data(),
Variables->PartMap->sizeOf(partition),
jNameLogical.data(),
Variables->PartMap->isLogical(partition) ? "true" : "false");
else
#ifdef __LP64__
print("partition=%s size=%lu isLogical=%s\n",
#else
print("partition=%s size=%llu isLogical=%s\n",
#endif
partition.data(),
Variables->PartMap->sizeOf(partition),
Variables->PartMap->isLogical(partition) ? "true" : "false");
}
return true;
}
bool infoFunction::isUsed() const { return cmd->parsed(); }
const char* infoFunction::name() const { return IFUN; };
} // namespace PartitionManager

View File

@@ -0,0 +1,72 @@
/*
Copyright 2025 Yağız Zengin
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <PartitionManager/PartitionManager.hpp>
#include "functions.hpp"
#define SFUN "partitionSizeFunction"
std::string convertTo(const uint64_t size, const std::string& multiple)
{
if (multiple == "KB") return std::to_string(TO_KB(size));
if (multiple == "MB") return std::to_string(TO_MB(size));
if (multiple == "GB") return std::to_string(TO_GB(size));
return std::to_string(size);
}
namespace PartitionManager {
bool partitionSizeFunction::init(CLI::App& _app)
{
LOGN(SFUN, INFO) << "Initializing variables of partition size getter function." << std::endl;
cmd = _app.add_subcommand("sizeof", "Tell size(s) of input partition list");
cmd->add_option("partition(s)", partitions, "Partition name(s).")->required()->delimiter(',');
cmd->add_flag("--as-byte", asByte, "Tell input size of partition list as byte.");
cmd->add_flag("--as-kilobyte", asKiloBytes, "Tell input size of partition list as kilobyte.");
cmd->add_flag("--as-megabyte", asMega, "Tell input size of partition list as megabyte.");
cmd->add_flag("--as-gigabyte", asGiga, "Tell input size of partition list as gigabyte.");
cmd->add_flag("--only-size", onlySize, "Tell input size of partition list as not printing multiple.");
return true;
}
bool partitionSizeFunction::run()
{
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) LOGN(SFUN, WARNING) << "Partition " << partition << " is exists but not logical. Ignoring (from --force, -f)." << std::endl;
else throw Error("Used --logical (-l) flag but is not logical partition: %s", partition.data());
}
std::string multiple;
if (asByte) multiple = "B";
if (asKiloBytes) multiple = "KB";
if (asMega) multiple = "MB";
if (asGiga) multiple = "GB";
print("%s: %s%s\n", partition.data(), convertTo(Variables->PartMap->sizeOf(partition), multiple).data(), multiple.data());
}
return true;
}
bool partitionSizeFunction::isUsed() const { return cmd->parsed(); }
const char* partitionSizeFunction::name() const { return SFUN; }
} // namespace PartitionManager

View File

@@ -14,48 +14,92 @@
limitations under the License.
*/
#include <PartitionManager/lib.hpp>
#ifndef FUNCTIONS_HPP
#define FUNCTIONS_HPP
#include <PartitionManager/PartitionManager.hpp>
#include <vector>
namespace PartitionManager {
// Back-up function
class backupFunction : public PartitionManager::FunctionBase {
class backupFunction final : public FunctionBase {
private:
std::vector<std::string> partitions, outputNames;
std::string rawPartitions, rawOutputNames;
int bufferSize = 2048;
public:
CLI::App* cmd = nullptr;
bool init(CLI::App& _app) override;
bool run() override;
const char* name() override;
[[nodiscard]] bool isUsed() const override;
[[nodiscard]] const char* name() const override;
};
// Image flasher function
class flashFunction : public PartitionManager::FunctionBase {
class flashFunction final : public FunctionBase {
private:
std::vector<std::string> partitions, imageNames;
std::string rawPartitions, rawImageNames;
int bufferSize = 2048;
public:
CLI::App* cmd = nullptr;
bool init(CLI::App& _app) override;
bool run() override;
const char* name() override;
[[nodiscard]] bool isUsed() const override;
[[nodiscard]] const char* name() const override;
};
// Eraser function (only the partition content is cleared)
class eraseFunction : public PartitionManager::FunctionBase {
// Eraser function (writes zero bytes to partition)
class eraseFunction final : public FunctionBase {
private:
std::vector<std::string> partitions;
int bufferSize = 2048;
public:
CLI::App* cmd = nullptr;
bool init(CLI::App& _app) override;
bool run() override;
const char* name() override;
[[nodiscard]] bool isUsed() const override;
[[nodiscard]] const char* name() const override;
};
// Partition size getter function
class partitionSizeFunction : public PartitionManager::FunctionBase {
class partitionSizeFunction final : public FunctionBase {
private:
std::vector<std::string> partitions;
bool onlySize = false, asByte = false, asKiloBytes = false, asMega = true, asGiga = false;
public:
CLI::App* cmd = nullptr;
bool init(CLI::App& _app) override;
bool run() override;
const char* name() override;
[[nodiscard]] bool isUsed() const override;
[[nodiscard]] const char* name() const override;
};
// Partition info getter function
class infoFunction final : public FunctionBase {
private:
std::vector<std::string> partitions;
std::string jNamePartition = "name", jNameSize = "size", jNameLogical = "isLogical";
bool jsonFormat = false;
public:
CLI::App* cmd = nullptr;
bool init(CLI::App& _app) override;
bool run() override;
[[nodiscard]] bool isUsed() const override;
[[nodiscard]] const char* name() const override;
};
} // namespace PartitionManager
#endif // #ifndef FUNCTIONS_HPP