Compare commits

..

88 Commits

Author SHA1 Message Date
7405083815 Revert "README: Fix wrong URLs."
This reverts commit eda1b3d50c.
2025-11-02 23:06:03 +03:00
9a1af981d9 pmt: Set version as release candicate 2025-11-02 22:54:27 +03:00
eda1b3d50c README: Fix wrong URLs. 2025-10-28 12:02:31 +03:00
0c48c13852 Cleanup idea files, etc. 2025-10-28 11:42:35 +03:00
7ab20f1c99 .github/workflows/build.yml Güncelle 2025-10-28 11:15:15 +03:00
a45b7332cc build.sh: Stop thread allocation on dual-threaded devices 2025-10-28 11:03:47 +03:00
caff1510f9 .github/workflows/build.yml Güncelle 2025-10-28 10:54:22 +03:00
876674726d revert 4b1c1607ed
revert build.yml: use local server for builds
2025-10-28 10:16:55 +03:00
4b1c1607ed build.yml: use local server for builds 2025-10-28 09:21:34 +03:00
6a25a663e7 revert 1545511859
revert build.yml: Adapt with local git server

Signed-off-by: YZBruh <yagizzengin73@gmail.com>
2025-10-28 09:20:47 +03:00
1545511859 build.yml: Adapt with local git server
Signed-off-by: YZBruh <yagizzengin73@gmail.com>
2025-10-28 08:43:05 +03:00
798cad275c pmt: Improve libhelper, etc. 2025-09-30 21:07:11 +03:00
066080c999 pmt: Add new type (class) to libhelper, etc.
- Add Helper::Capsule.
 - Fix some compilation errors.
2025-09-28 21:45:40 +03:00
397b95466d pmt: reformat code, etc. 2025-09-24 22:14:25 +03:00
0ff94cc4b9 pmt: improve PureTuple class and improve function manager. 2025-09-23 14:13:36 +03:00
b60c5c023f pmt: improve PureTuple class. 2025-09-22 20:16:18 +03:00
17f2fb5660 pmt: cleanup PureTuple class. 2025-09-21 21:19:02 +03:00
6e8931bd68 libhelper: created new type (class) PureTuple (vector-like tuple) 2025-09-21 21:17:23 +03:00
7aca7792ae pmt: add random number generator class (compile-time, with templates) 2025-09-17 00:28:26 +03:00
318739adc8 pmt: add stdin parsing support, etc. 2025-09-15 00:01:52 +03:00
398b119cb4 pmt: improve libhelper, etc. 2025-09-13 11:36:29 +03:00
b99f20c6a1 pmt: fixup manager.sh 2025-09-11 10:59:39 +03:00
37dc3ac94b pmt: reformat code and improve workflow 2025-09-11 10:58:14 +03:00
83c56c795e pmt: update latest release date 2025-09-11 10:13:31 +03:00
de1cb5dd5a pmt: Fixup backup function 2025-09-07 21:55:53 +03:00
9625bf6df0 pmt: Improve libhelper and libpartition_map, etc. 2025-09-07 21:54:35 +03:00
77760bd1d4 pmt: Improve libpartition_map types and some functions.
- Add new operators to Map_t.
 - Add new flags to info function.
 - Move some local pmt function(s) to libhelper.
 - Etc...
2025-09-07 11:56:12 +03:00
1984825dec pmt: add [] operators to Map_t and builder 2025-09-07 10:53:59 +03:00
ab35740fb6 pmt: remove non-signal exit code catching. 2025-09-06 12:12:49 +03:00
08e51c4a15 pmt: start working on 1.3.0
- Add log cleaner function.
 - Introduce function flag structure.
 - Some improvements.
2025-09-06 12:10:46 +03:00
063d62fd85 pmt: fix workflow 2025-09-05 11:38:16 +03:00
2615ddd127 pmt: Last commit for 1.2.0 version
- Major changes for developers.
 - Some changes to flash and sizeof functions.
 - Some minor changes.
2025-09-05 11:31:46 +03:00
51ae72aba1 pmt: add control for -l flag 2025-09-04 21:35:16 +03:00
deab481fd7 pmt: reformat code, etc. 2025-09-04 20:42:50 +03:00
e1dc7132ee pmt: Add documentation to libhelper functions, etc. 2025-09-02 19:20:11 +03:00
360959381b pmt: Improve libraries
- Tests have been improved.
 - Some functions and classes in libhelper have been improved for better results.
2025-09-02 12:41:09 +03:00
0832b57828 pmt: Improve libpartition_map and tests
- Change doFor*** function return types as bool.
 - Add catching of doFor*** function test results.
 - Use std::ios_base_failure for catch std::fstream errors on tests
2025-09-01 01:35:45 +03:00
e7baf4f5bc pmt: Improve pmt & libpartition_map
- Change some operator returnn types.
 - Use std::map instead of std::unordered on magic number maps.
 - Some improvements.
2025-09-01 01:21:06 +03:00
fea9c834fc pmt: reformat code 2025-08-31 15:40:35 +03:00
025ccf3acb pmt: Improve libpartition_map
- Add new operators to Map_t and builder.
 - Some improvements.
2025-08-31 15:36:26 +03:00
d19343d644 pmt: Minor changes.
- Add build instruction.
 - Improve function lambdas.
2025-08-29 13:40:03 +03:00
1a9b4ff5ad pmt: Introduce, fixup
- Fix pstderr file pointer.
 - Improve and add more functions on libpartition_map.
 - Improve functions.
2025-08-28 23:13:52 +03:00
d7bd11165d clean idea config 2025-08-27 22:50:54 +03:00
c2a41b6365 build.sh: Gift two threads to the user... 2025-08-27 22:28:32 +03:00
bfd3324558 pmt: reformat code 2025-08-27 22:24:50 +03:00
41336609fa pmt: switch builder to ninja. And some extra improvements 2025-08-27 22:04:06 +03:00
e0f0b5b484 pmt: Improvements for developers
- Android.bp was written to be included in ROMs/recoveries etc. in Android build system.
 - Macros have been added to simplify feature creation.
 - Some bug fixes (for JSON and pmt).
2025-08-27 15:50:40 +03:00
631c735a9a pmt: reformat code 2025-08-25 13:20:21 +03:00
80bcc0268d pmt: Improve, etc.
- Added custom file descriptors for better print status handling.
 - Added macro to be used for adding functions to make things easier.
 - Duplicate function protection added.
2025-08-25 13:12:46 +03:00
853d2c97b3 Start working for 1.2.0 2025-08-24 16:21:42 +03:00
753d9d8ad2 Cleanup 2025-08-24 16:19:15 +03:00
1d1d6e98ce Reapply "Improve build system, etc..."
This reverts commit 705f529f55.
2025-08-24 16:17:41 +03:00
705f529f55 Revert "Improve build system, etc..."
This reverts commit 249b44a81a.
2025-08-24 16:17:12 +03:00
249b44a81a Improve build system, etc... 2025-08-24 16:16:30 +03:00
62b1ff98d9 change release date 2025-08-21 09:54:23 +03:00
7b29059a8e fixup manager 2025-08-18 23:06:39 +03:00
9724bee46e pmt: change latest release date 2025-08-18 22:29:07 +03:00
366bb28612 pmt: add interrupt signal handler etc. 2025-08-18 22:24:42 +03:00
58330fddf4 pmt: use smart pointers for more safe memory 2025-08-16 20:14:05 +03:00
62b73ac91a fix looping memory test function 2025-08-15 22:47:13 +03:00
20ad64c8c5 manager: set new release date 2025-08-15 22:09:21 +03:00
6999975f6a Revert "fix memory leak"
This reverts commit 47382ebf1c.
2025-08-15 20:04:25 +03:00
54f2a48ffa Reapply "fix memory leak"
This reverts commit c3a5e97d41.
2025-08-15 20:02:45 +03:00
9391847534 Reapply "pmt: use constructor/destructor attributes insetad of class"
This reverts commit d4703df1a5.
2025-08-15 20:02:29 +03:00
bfd5a78863 noo 2025-08-15 20:02:28 +03:00
d4703df1a5 Revert "pmt: use constructor/destructor attributes insetad of class"
This reverts commit 7240cca537.
2025-08-15 17:29:28 +03:00
c3a5e97d41 Revert "fix memory leak"
This reverts commit 47382ebf1c.
2025-08-15 17:29:10 +03:00
47382ebf1c fix memory leak 2025-08-15 17:22:04 +03:00
7240cca537 pmt: use constructor/destructor attributes insetad of class 2025-08-15 16:31:09 +03:00
6a8fd5854d Add bugg report info 2025-08-15 15:53:35 +03:00
f3732ff158 Move documentation to wiki page 2025-08-15 15:30:01 +03:00
b7f5348b89 Write a installing and usage etc. 2025-08-15 12:45:28 +03:00
235402ed23 Write a installing and usage etc. 2025-08-15 12:45:15 +03:00
e17ac42e55 manager: set release date 2025-08-15 12:00:53 +03:00
1bc3b5ccef pmt: CLeanup unnecessary function: real-link-path
- real-link-path function is removed.
 - Added --real-link-path flag to real-path function for as real-link-path.
2025-08-15 11:52:03 +03:00
c3acd4b370 usage: add --json-indent-size option to usages 2025-08-14 19:50:02 +03:00
05f173e895 pmt: improve usage.md :/ 2025-08-14 19:41:41 +03:00
638ed3017e pmt: add memory test documentation 2025-08-14 19:36:16 +03:00
563e8a583e pmt: fix memory leaks, and improve info function
- Removed --no-write-test argument of memory test function
 - Fixed memory leak of memory test function
 - Improved info function with using nlohmann/json header-only library
 - Some other improvents
2025-08-14 12:56:29 +03:00
bf0df8cc83 pmt: add memory test function and some new functions to libhelper 2025-08-13 10:58:48 +03:00
0bc5f70294 pmt: reformat code and improve 2025-08-13 09:54:11 +03:00
d74f385a68 pmt: dont include new memoryTestFunction 2025-08-13 09:42:37 +03:00
23087966d6 pmt: start working for 1.1.0, first: add * operator to libpartition_map 2025-08-13 09:41:27 +03:00
7350791d04 Update manager.sh 2025-08-11 14:26:47 +03:00
5d06c804e3 Update manager.sh 2025-08-11 14:13:46 +03:00
442155b9f6 manager: fix downloading and unexpected operator error 2025-08-11 14:07:56 +03:00
a1211c91fe manager: configure as only for termux 2025-08-11 12:50:02 +03:00
f33433cfe6 manager: fix typos 2025-08-11 12:43:28 +03:00
47 changed files with 27921 additions and 1492 deletions

View File

@@ -5,7 +5,7 @@ on: [workflow_dispatch]
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: write
@@ -23,7 +23,7 @@ jobs:
run: |
sudo apt update
sudo apt upgrade -y
sudo apt install make cmake extra-cmake-modules zip -y
sudo apt install make ninja-build cmake extra-cmake-modules zip -y
- name: Setup Android NDK
id: setup-ndk
@@ -35,7 +35,7 @@ jobs:
- name: Build And Prepare For Release
id: build
run: |
git clone https://github.com/ShawkTeam/pmt-renovated -b main ./pmt && cd pmt
git clone https://git.yzbruh.space/${{ github.repository }} -b main ./pmt && cd pmt
export ANDROID_NDK="${{ github.workspace }}/android-ndk-r28c"
bash build.sh clean
bash build.sh build -DCMAKE_BUILD_TYPE=Release
@@ -49,6 +49,9 @@ jobs:
zip pmt-static-armeabi-v7a.zip pmt_static
echo "BUILD_DATE=$(date +%Y%m%d)" >> $GITHUB_ENV
echo "BUILD=${{ github.workspace }}/pmt" >> $GITHUB_ENV
cd ..
echo -e "Read [Wiki - About Release Types](https://git.yzbruh.space/${{ github.repository }}/wiki/About-Release-Types) for getting more information.\n\n### Changes\n" > release.txt
git log --since="2025-08-21" --pretty=format:" * %ad | [%s](https://git.yzbruh.space/${{ github.repository }}/commit/%H)" --date=short | sed 's/ -.*//' | grep -v cleanup >> release.txt
working-directory: ${{ github.workspace }}
- name: Upload To GitHub Releases
@@ -60,4 +63,4 @@ jobs:
${{ env.BUILD }}/build_armeabi-v7a/*.zip
name: Partition Manager Tool Release ${{ env.BUILD_DATE }}
tag_name: ${{ env.BUILD_DATE }}
body: "Read [RELEASE-TYPES.md](https://github.com/ShawkTeam/pmt-renovated/blob/main/RELEASE-TYPES.md) for getting more information."
body_path: ${{ env.BUILD }}/release.txt

3
.gitignore vendored
View File

@@ -7,8 +7,7 @@ cmake-build-*
include/generated
# Dont't add build directories
build_arm64-v8a
build_armeabi-v7a
build_*
# Don't add generated objects and libs
*.o

1
.idea/.name generated
View File

@@ -1 +0,0 @@
pmt

2
.idea/1.0.0.iml generated
View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="CMake" type="CPP_MODULE" version="4" />

344
.idea/editor.xml generated
View File

@@ -1,344 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="BackendCodeEditorSettings">
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CDeclarationWithImplicitIntType/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CommentTypo/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConstevalIfIsAlwaysConstant/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractClassWithoutSpecifier/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractFinalClass/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractVirtualFunctionCallInCtor/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAccessSpecifierWithNoDeclarations/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAwaiterTypeIsNotClass/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBooleanIncrementExpression/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatBadCode/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatLegacyCode/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatMixedArgs/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatTooFewArgs/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatTooManyArgs/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCStyleCast/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCVQualifierCanNotBeAppliedToReference/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassCanBeFinal/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassIsIncomplete/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassNeedsConstructorBecauseOfUninitializedMember/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCompileTimeConstantCanBeReplacedWithBooleanConstant/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConceptNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConditionalExpressionCanBeSimplified/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConstParameterInDeclaration/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConstValueFunctionReturnType/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCoroutineCallResolveError/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAArrayIndexOutOfBounds/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantConditions/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantFunctionResult/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantParameter/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFADeletedPointer/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAEndlessLoop/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAInfiniteRecursion/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAInvalidatedMemory/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALocalValueEscapesFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALocalValueEscapesScope/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALoopConditionNotUpdated/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAMemoryLeak/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFANotInitializedField/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFANullDereference/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFATimeOver/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreachableCode/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreachableFunctionCall/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreadVariable/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnusedValue/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationHidesLocal/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationHidesUncapturedLocal/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationSpecifierWithoutDeclarators/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorDisambiguatedAsFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorUsedBeforeInitialization/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultCaseNotHandledInSwitchStatement/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultInitializationWithNoUserConstructor/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultIsUsedAsIdentifier/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultedSpecialMemberFunctionIsImplicitlyDeleted/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeletingVoidPointer/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDependentTemplateWithoutTemplateKeyword/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDependentTypeWithoutTypenameKeyword/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeprecatedEntity/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeprecatedOverridenMethod/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeprecatedRegisterStorageClassSpecifier/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDereferenceOperatorLimitExceeded/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDiscardedPostfixOperatorResult/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenSyntaxError/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenUndocumentedParameter/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenUnresolvedReference/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEmptyDeclaration/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceCVQualifiersOrder/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceCVQualifiersPlacement/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceDoStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceForStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceFunctionDeclarationStyle/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceIfStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceNestedNamespacesStyle/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceOverridingDestructorStyle/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceOverridingFunctionStyle/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceTypeAliasCodeStyle/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceWhileStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEntityAssignedButNoRead/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEntityUsedOnlyInUnevaluatedContext/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnumeratorNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEqualOperandsInBinaryExpression/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEvaluationFailure/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppExplicitSpecializationInNonNamespaceScope/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppExpressionWithoutSideEffects/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFinalFunctionInFinalClass/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFinalNonOverridingVirtualFunction/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppForLoopCanBeReplacedWithWhile/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppForwardEnumDeclarationWithoutUnderlyingType/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionDoesntReturnValue/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionIsNotImplemented/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionResultShouldBeUsed/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionalStyleCast/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHeaderHasBeenAlreadyIncluded/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHiddenFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHidingFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIdenticalOperandsInBinaryExpression/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIfCanBeReplacedByConstexprIf/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppImplicitDefaultConstructorNotAvailable/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIncompatiblePointerConversion/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIncompleteSwitchStatement/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppInconsistentNaming/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIntegralToPointerConversion/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppInvalidLineContinuation/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppJoinDeclarationAndAssignment/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLambdaCaptureNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableMayBeConst/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableMightNotBeInitialized/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableWithNonTrivialDtorIsNeverUsed/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLongFloat/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberFunctionMayBeConst/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberFunctionMayBeStatic/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberInitializersOrder/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMismatchedClassTags/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMissingIncludeGuard/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMissingKeywordThrow/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtAddressOfClassRValue/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtBindingRValueToLvalueReference/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtCopyElisionInCopyInitDeclarator/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtDoubleUserConversionInCopyInit/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtNotInitializedStaticConstLocalVar/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtReinterpretCastFromNullptr/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMultiCharacterLiteral/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMultiCharacterWideLiteral/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMustBePublicVirtualToImplementInterface/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMutableSpecifierOnReferenceMember/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNoDiscardExpression/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNodiscardFunctionWithoutReturnValue/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExceptionSafeResourceAcquisition/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExplicitConversionOperator/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExplicitConvertingConstructor/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonInlineFunctionDefinitionInHeaderFile/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonInlineVariableDefinitionInHeaderFile/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNotAllPathsReturnValue/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppObjectMemberMightNotBeInitialized/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppOutParameterMustBeWritten/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterMayBeConst/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterMayBeConstPtrOrRef/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterNamesMismatch/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterNeverUsed/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPassValueParameterByConstReference/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPointerConversionDropsQualifiers/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPointerToIntegralConversion/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPolymorphicClassWithNonVirtualPublicDestructor/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyErroneousEmptyStatements/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyUninitializedMember/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyUnintendedObjectSlicing/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrecompiledHeaderIsNotIncluded/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrecompiledHeaderNotFound/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfBadFormat/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfExtraArg/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfMissedArg/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfRiskyFormat/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrivateSpecialMemberFunctionIsNotImplemented/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRangeBasedForIncompatibleReference/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedefinitionOfDefaultArgumentInOverrideFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantAccessSpecifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBaseClassAccessSpecifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBaseClassInitializer/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBooleanExpressionArgument/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantCastExpression/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantComplexityInComparison/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantConditionalExpression/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantConstSpecifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantControlFlowJump/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantDereferencingAndTakingAddress/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElaboratedTypeSpecifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElseKeyword/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElseKeywordInsideCompoundStatement/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantEmptyDeclaration/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantEmptyStatement/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantExportKeyword/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantFwdClassOrEnumSpecifier/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantInlineSpecifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantLambdaParameterList/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantMemberInitializer/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantNamespaceDefinition/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantParentheses/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantQualifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantQualifierADL/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantStaticSpecifierOnMemberAllocationFunction/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantStaticSpecifierOnThreadLocalLocalVariable/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTemplateArguments/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTemplateKeyword/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTypenameKeyword/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantVoidArgumentList/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantZeroInitializerInAggregateInitialization/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReinterpretCastFromVoidPtr/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRemoveRedundantBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReplaceMemsetWithZeroInitialization/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReplaceTieWithStructuredBinding/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReturnNoValueInNonVoidFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSmartPointerVsMakeFunction/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSomeObjectMembersMightNotBeInitialized/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSpecialFunctionWithoutNoexceptSpecification/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticAssertFailure/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticDataMemberInUnnamedStruct/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticSpecifierOnAnonymousNamespaceMember/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStringLiteralToCharPointerConversion/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTabsAreDisallowed/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateArgumentsCanBeDeduced/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateParameterNeverUsed/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateParameterShadowing/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppThrowExpressionCanBeReplacedWithRethrow/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTooWideScope/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTooWideScopeInitStatement/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTypeAliasNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUninitializedDependentBaseClass/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUninitializedNonStaticDataMember/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnionMemberOfReferenceType/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnmatchedPragmaEndRegionDirective/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnmatchedPragmaRegionDirective/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnnamedNamespaceInHeaderFile/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnnecessaryWhitespace/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnsignedZeroComparison/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnusedIncludeDirective/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAlgorithmWithCount/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAssociativeContains/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAuto/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAutoForNumeric/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseElementsView/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseEraseAlgorithm/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseFamiliarTemplateSyntaxForGenericLambdas/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseRangeAlgorithm/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseStdSize/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseStructuredBinding/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseTypeTraitAlias/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUserDefinedLiteralSuffixDoesNotStartWithUnderscore/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUsingResultOfAssignmentAsCondition/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVariableCanBeMadeConstexpr/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVirtualFunctionCallInsideCtor/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVirtualFunctionInFinalClass/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVolatileParameterInDeclaration/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWarningDirective/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWrongIncludesOrder/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWrongSlashesInIncludeDirective/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppZeroConstantCanBeReplacedWithNullptr/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppZeroValuedExpressionUsedAsNullPointer/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=IdentifierTypo/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=IfStdIsConstantEvaluatedCanBeReplaced/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=StdIsConstantEvaluatedWillAlwaysEvaluateToConstant/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=StringLiteralTypo/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppClangFormat/EnableClangFormatSupport/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_ARGUMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_BINARY_EXPRESSIONS_CHAIN/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_CALLS_CHAIN/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXPRESSION/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXTENDS_LIST/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_FOR_STMT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_PARAMETER/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_ARGUMENT/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_PARAMETER/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTIPLE_DECLARATION/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_TERNARY/@EntryValue" value="ALIGN_ALL" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_CLASS_DEFINITION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_DECLARATIONS/@EntryValue" value="0" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DECLARATION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DEFINITION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BREAK_TEMPLATE_DECLARATION/@EntryValue" value="LINE_BREAK" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CASE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CONTINUOUS_LINE_INDENT/@EntryValue" value="Double" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/FREE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_ACCESS_SPECIFIERS_FROM_CLASS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CASE_FROM_SWITCH/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CLASS_MEMBERS_FROM_ACCESS_SPECIFIERS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_COMMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_SIZE/@EntryValue" value="4" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_STYLE/@EntryValue" value="Tab" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INITIALIZER_BRACES/@EntryValue" value="END_OF_LINE_NO_SPACE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INT_ALIGN_EQ/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INVOCABLE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_CODE/@EntryValue" value="2" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue" value="2" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_USER_LINEBREAKS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/LINE_BREAK_AFTER_COLON_IN_MEMBER_INITIALIZER_LISTS/@EntryValue" value="ON_SINGLE_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/MEMBER_INITIALIZER_LIST_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_INDENTATION/@EntryValue" value="All" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/OTHER_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_CATCH_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_ELSE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_NAMESPACE_DEFINITIONS_ON_SAME_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_WHILE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SIMPLE_BLOCK_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_PARAMS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_COLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_SEMICOLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_METHOD/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_NESTED_DECLARATOR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_METHOD/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_UNARY_OPERATOR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_COLON/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_SEMICOLON/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_METHOD/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_METHOD/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BETWEEN_CLOSING_ANGLE_BRACKETS_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_ARRAY_ACCESS_BRACKETS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_DECLARATION_PARENTHESES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_BLOCKS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_METHOD_PARENTHESES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPECIAL_ELSE_IF_TREATMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TAB_WIDTH/@EntryValue" value="4" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TYPE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_BINARY_OPSIGN/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_ARGUMENTS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_RPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_RPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_TERNARY_OPSIGNS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_PARAMETERS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
<option name="/Default/CodeStyle/EditorConfig/EnableClangFormatSupport/@EntryValue" value="false" type="bool" />
</component>
</project>

8
.idea/misc.xml generated
View File

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakePythonSetting">
<option name="pythonIntegrationState" value="YES" />
</component>
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
<component name="WestSettings"><![CDATA[{}]]></component>
</project>

8
.idea/modules.xml generated
View File

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/1.0.0.iml" filepath="$PROJECT_DIR$/.idea/1.0.0.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml generated
View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

110
Android.bp Normal file
View File

@@ -0,0 +1,110 @@
//
// 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.
//
// Partition manager tool source list
filegroup {
name: "pmt_srcs",
srcs: [
"src/FunctionManager.cpp",
"src/Main.cpp",
"src/PartitionManager.cpp",
"src/functions/BackupFunction.cpp",
"src/functions/EraseFunction.cpp",
"src/functions/FlashFunction.cpp",
"src/functions/InfoFunction.cpp",
"src/functions/MemoryTestFunction.cpp",
"src/functions/PartitionSizeFunction.cpp",
"src/functions/RealPathFunction.cpp",
"src/functions/RebootFunction.cpp",
"src/functions/TypeFunction.cpp",
],
}
// libhelper source list
filegroup {
name: "libhelper_srcs",
srcs: [
"srclib/libhelper/src/Checkers.cpp",
"srclib/libhelper/src/Classes.cpp",
"srclib/libhelper/src/FileUtil.cpp",
"srclib/libhelper/src/Sha256.cpp",
"srclib/libhelper/src/Utilities.cpp",
],
}
// libpartition_map source list
filegroup {
name: "libpartition_map_srcs",
srcs: [
"srclib/libpartition_map/src/Getters.cpp",
"srclib/libpartition_map/src/Magic.cpp",
"srclib/libpartition_map/src/PartitionMap.cpp",
"srclib/libpartition_map/src/Type.cpp",
],
}
// Default configurations of pmt
cc_defaults {
name: "pmt_defaults",
recovery_available: true,
cflags: [
"-Wall",
"-Werror",
"-Wno-deprecated-declarations",
"-Os",
"-fexceptions",
"-DANDROID_BUILD",
],
ldflags: ["-Wl,-s"],
local_include_dirs: [
"include",
"srclib/libhelper/include",
"srclib/libpartition_map/include",
],
export_include_dirs: [
"include",
"srclib/libhelper/include",
"srclib/libpartition_map/include",
],
shared_libs: ["libbase"],
}
// libhelper library target
cc_library_shared {
name: "libhelper",
defaults: ["pmt_defaults"],
srcs: [":libhelper_srcs"],
}
// libpartition_map library target
cc_library_shared {
name: "libpartition_map",
defaults: ["pmt_defaults"],
srcs: [":libpartition_map_srcs"],
shared_libs: ["libhelper"],
static_libs: ["libc++fs"],
}
// pmt executable target
cc_binary {
name: "pmt",
defaults: ["pmt_defaults"],
srcs: [":pmt_srcs"],
shared_libs: [
"libhelper",
"libpartition_map",
],
}

View File

@@ -16,7 +16,7 @@
# Project info
cmake_minimum_required(VERSION 3.10)
project(pmt VERSION 1.0.0)
project(pmt VERSION 1.3.0-rc1)
# Set compiler flags
add_compile_options(-Wall -Werror -Wno-deprecated-declarations)
@@ -29,7 +29,7 @@ else()
endif()
# Add pmt's CMake module(s)
include(cmake/generate_headers.cmake)
include(build/cmake/generate_headers.cmake)
# Generate header(s)
get_property(FLAGS DIRECTORY PROPERTY COMPILE_OPTIONS)

View File

@@ -19,15 +19,23 @@ PMT is designed for developers, technicians, and Android enthusiasts who need fi
- **Reboot** the device into multiple modes (normal, recovery, etc.).
- **Asynchronous processing** for speed — each partition runs in its own thread.
- **Error isolation** so one failing operation doesnt cancel the rest. For back upping, flashing and erasing.
- **Test** sequential read/write speed of your memory.
---
## Documentation
Detailed usage instructions and option references can be found in the [USAGE.md](./USAGE.md) file.
For all information about PMT, see the [wiki](https://github.com/ShawkTeam/pmt-renovated/wiki).\
Read [Wiki - Using PMT via Termux or ADB](https://github.com/ShawkTeam/pmt-renovated/wiki/Using-PMT-via-Termux-or-ADB) for learn how to use PMT via Termux or ADB.\
Detailed usage instructions and option references can be found in the [Wiki - Usage](https://github.com/ShawkTeam/pmt-renovated/wiki/Usage).\
See [Wiki - How To Build](https://github.com/ShawkTeam/pmt-renovated/wiki/How-To-Build) to learn how to build.
## Bug Reporting
Please submit bugs at [Issues](https://github.com/ShawkTeam/pmt-renovated/issues) page.
---
## Credits
- [CLI11: Command line parser for C++11](https://github.com/CLIUtils/CLI11)
- [PicoSHA2: A header-file-only, SHA256 hash generator in C++](https://github.com/okdshin/PicoSHA2)
- [nlohmann/json: JSON for Modern C++](https://github.com/nlohmann/json)

View File

@@ -1,65 +0,0 @@
# Release Types
This project provides four different release packages, each tailored for specific Android device architectures and usage preferences.
---
## The Four Release Files
| File Name | Architecture | Bitness | Library Type | Description |
|---------------------------|-----------------|---------|----------------|----------------------------------------------------------|
| `pmt-arm64-v8a.zip` | ARM64 (ARMv8-A) | 64-bit | Dynamic (.so) | For 64-bit devices, uses dynamic libraries. Requires accompanying `.so` files (`libhelper` and `libpartition_map`). |
| `pmt-static-arm64-v8a.zip`| ARM64 (ARMv8-A) | 64-bit | Static (.a) | Fully static build for 64-bit devices. No external dependencies. Great for general use and ADB environments. |
| `pmt-armeabi-v7a.zip` | ARM (ARMv7) | 32-bit | Dynamic (.so) | For 32-bit devices, uses dynamic libraries. Requires `.so` files (`libhelper` and `libpartition_map`). |
| `pmt-static-armeabi-v7a.zip`| ARM (ARMv7) | 32-bit | Static (.a) | Fully static build for 32-bit devices. No external dependencies. Great for general use and ADB environments. |
---
## Architecture & Bitness Explained
- **ARM64 (arm64-v8a)**:
This is a 64-bit architecture used by newer Android devices. It can handle larger amounts of memory and generally runs faster for heavy tasks.
- **ARM (armeabi-v7a)**:
This is a 32-bit architecture common on older or less powerful Android devices. It has some limitations compared to 64-bit but is still widely supported.
---
## Dynamic vs Static Libraries
The project relies on two helper libraries:
- **libhelper**
- **libpartition_map**
### Dynamic Versions (`.so` files)
- In the non-static (`pmt-arm64-v8a.zip` and `pmt-armeabi-v7a.zip`) packages, these libraries are **compiled as shared objects (`.so` files)**.
- This means that the main program (`pmt`) **depends on these libraries being present** on the device or alongside the executable to run correctly.
- If these libraries are missing, the program will fail to start.
- These builds are mostly for developers or users who want to customize or work closely with the libraries.
### Static Versions (`.a` files)
- The static packages (`pmt-static-arm64-v8a.zip` and `pmt-static-armeabi-v7a.zip`) **include these libraries inside the main executable** by linking them statically.
- This means the `pmt` binary is **completely self-contained** and **does not require any external `.so` files**.
- These versions are ideal for general users and especially convenient for ADB usage, where installing separate `.so` files might be cumbersome.
---
## Which Should You Use?
- If you want a hassle-free experience and dont want to worry about missing libraries, **choose the static version** matching your devices architecture.
- If you are a developer or want to experiment with the libraries separately, or save space by sharing `.so` files between multiple programs, the **dynamic version** is the way to go.
---
## Summary
| Release Type | Architecture | Dependencies | Best For |
|--------------|--------------|-----------------------|---------------------------|
| Static | 32-bit / 64-bit | None (fully standalone) | General users, ADB usage |
| Dynamic | 32-bit / 64-bit | Requires `.so` libs | Developers, advanced users |
---
If youre unsure which one to pick, try the **static version** first — it works out of the box on all supported devices.

319
USAGE.md
View File

@@ -1,319 +0,0 @@
# Partition Manager Tool (PMT)
**Partition Manager Tool** is a powerful command-line utility for **Android** devices, designed to perform various operations on partitions quickly, reliably, and efficiently.
This is the **renovated version** of PMT, rewritten in C++ for improved performance, stability, and usability compared to its older variant.
It supports **asynchronous operations**, allowing multiple partitions to be processed in parallel, and includes safety measures to prevent a single error from breaking the entire operation batch.
---
## Features
- **Backup** partitions to files (with optional permissions fix for non-root access).
- **Flash** image files directly to partitions.
- **Erase** partitions by filling them with zero bytes.
- **Get** partition sizes in various units.
- **Display** partition information in plain text or JSON format.
- **Retrieve** real paths and symbolic link paths of partitions.
- **Identify** file system or image types by checking magic numbers.
- **Reboot** the device into different modes.
---
## Usage
Don't forget to check out how to use it with **ADB**!
```bash
pmt [OPTIONS] [SUBCOMMAND]
```
### Global Options
| Option | Long Option | Description |
|--------|------------------------|-------------|
| `-h` | `--help` | Print basic help message and exit. |
| | `--help-all` | Print full help message and exit. |
| `-S` | `--search-path TEXT` | Set the partition search path. |
| `-L` | `--log-file TEXT` | Set log file path. |
| `-f` | `--force` | Force the process to be executed even if checks fail. |
| `-l` | `--logical` | Specify that the target partition is **dynamic**. |
| `-q` | `--quiet` | Suppress output. |
| `-V` | `--verbose` | Enable detailed logs during execution. |
| `-v` | `--version` | Print version and exit. |
**Example usages for global options:**\
`pmt [SUBCOMMAND ...] --quiet`\
`pmt [SUBCOMMAND ...] -S /dev/block/platform/bootdevice/by-name`\
`pmt [SUBCOMMAND ...] [GLOBAL OPTIONS ...]`
---
## Subcommands
### 1. `backup`
Backup partitions to files. General syntax:
```bash
pmt backup partition(s) [output(s)] [OPTIONS]
```
**Options:**
- `-b`, `--buffer-size SIZE` → Set buffer size (in bytes) for read/write operations.
- `-O`, `--output-directory DIR` → Specify an output directory for backups.
**Notes:**
- Partition names are separated by commas.
- If custom output names are provided, they must match the number of partitions.
- Automatically adjusts permissions so backup files can be read/written without root.
**Example usages:**\
`pmt backup boot`\
`pmt backup boot boot_backup.img`\
`pmt backup boot,recovery,vendor`\
`pmt backup boot`\
`pmt backup boot,recovery -O /sdcard`\
`pmt backup system,vendor --buffer-size=8192 # '=' is not mandatory`
---
### 2. `flash`
Flash an image or multiple images to partitions. general syntax:
```bash
pmt flash partition(s) image(s) [OPTIONS]
```
**Options:**
- `-b`, `--buffer-size SIZE` → Set buffer size (in bytes).
- `-I`, `--image-directory DIR` → Directory containing image files.
**Notes:**
- Multiple partitions and images are separated by commas.
- **Example usages:**\
`pmt flash boot boot_backup.img`\
`pmt flash boot,recovery /sdcard/backups/boot_backup.img,/sdcard/backups/recovery_backup.img`\
`pmt flash boot boot_backup.img,recovery_backup.img -I /sdcard/backups`\
`pmt flash system,vendor system_backup.img,vendor_backup.img -I /sdcard/backups --buffer-size=8192`
---
### 3. `erase`
Fill partition(s) with zero bytes (like `dd if=/dev/zero of=/dev/block/by-name/<partition>`). General syntax:
```bash
pmt erase partition(s) [OPTIONS]
```
**Options:**
- `-b`, `--buffer-size SIZE` → Set buffer size.
**Example usages (DO NOT USE FOR TRYING!!!):**\
`pmt erase boot`\
`pmt erase nvdata,nvram`\
`pmt erase system,vendor --buffer-size=8192`
---
### 4. `sizeof`
Show the size of partition(s). General syntax:
```bash
pmt sizeof partition(s) [OPTIONS]
```
**Options:**
- `--as-byte` → Show size in bytes.
- `--as-kilobyte` → Show size in KB.
- `--as-megabyte` → Show size in MB (default).
- `--as-gigabyte` → Show size in GB.
- `--only-size` → Output only the numeric value (no partition name).
**Example usages:**\
`pmt sizeof boot` - Example output: `boot: 64MB`\
`pmt sizeof boot --as-byte` - Example output: `64`\
`pmt sizeof boot --as-<write type here> --only-size` - Example output (for `--as-kilobyte`): `98304`
---
### 5. `info`
Show partition name, size, and dynamic status. General syntax:
```bash
pmt info partition(s) [OPTIONS]
```
**Options:**
- `-J`, `--json` → Output in JSON format.
- `--json-partition-name NAME` → Custom JSON key for partition name.
- `--json-size-name NAME` → Custom JSON key for size.
- `--json-logical-name NAME` → Custom JSON key for dynamic status.
**Example usages:**\
`pmt info boot` - Example output: `partition=boot size=100663296 isLogical=false`\
`pmt info boot -J` - Example output: `{"name": "boot", "size": 100663296, "isLogical": false}`\
`pmt info boot -J --json-partition-name=partitionName` - Example output: `{"partitionName": "boot", "size": 100663296, "isLogical": false}`
---
### 6. `real-path`
Show the **absolute block device path** for each partition. General syntax:
```bash
pmt real-path partition(s) [OPTIONS]
```
**Example usages:**\
`pmt real-path boot` - Example output: `/dev/block/sda25`
---
### 7. `real-linkpath`
Show the **symbolic link path** for each partition (e.g., `/dev/block/by-name/boot`). General syntax:
```bash
pmt real-link-path partition(s) [OPTIONS]
```
---
### 8. `type`
Check magic numbers to determine file system or other types of partition(s) or image(s). General syntax:
```bash
pmt type partition(s) [OPTIONS]
```
**Options:**
- `-b`, `--buffer-size SIZE` → Set buffer size.
- `--only-check-android-magics` → Check only Android-related magic numbers.
- `--only-check-filesystem-magic` → Check only file system magic numbers.
**Example usages:**\
`pmt type boot` - Example output: `boot contains Android Boot Image magic (0x2144494F52444241)`\
`pmt type vendor_boot.img` - Example output: `vendor_boot.img contains Android Vendor Boot Image magic (0x544F4F4252444E56)`
---
### 9. `reboot`
Reboot the device. Default reboot target is normal. If you are using it via ADB terminal, you **DO NOT** need root to use this feature. General syntax:
```bash
pmt reboot [rebootTarget] [OPTIONS]
```
**Example usages:**\
`pmt reboot`
`pmt reboot recovery`
`pmt reboot download`
## Additional Notes
- **Comma-separated inputs**: All commands (except `reboot`) require multiple inputs to be separated by commas.
- **Asynchronous execution**: For `backup`, `flash`, and `erase`, each partition is processed in a separate thread for maximum speed.
- **Error isolation**: A failure in processing one partition will not cancel the others. Only for `backup`, `flash` and `erase` functions.
- **Automatic diagnostics**: By default, whether a partition is dynamic or regular is determined automatically. With global options, you only specify precision.
- **Root access**: Root access is required if operations are to be performed on partitions.
## Extra Note: Comma Usage
In **Partition Manager Tool**, whenever you provide **multiple partitions**, **multiple image files**, or **multiple output file names**, they **must** be separated by commas (`,`), without spaces.
**Correct:**\
`pmt backup boot,recovery`\
`pmt flash boot,recovery boot.img,recovery.img`
**Incorrect:**\
`pmt backup boot recovery`\
`pmt flash boot recovery boot.img recovery.img`
The **number of items must match** when providing both input and output lists.
For example, if you specify 3 partitions, you must also provide 3 output file names.
This rule applies to **all commands except `reboot`**, since `reboot` only takes one optional argument.
---
## Using `pmt-static` via ADB
This guide will show you how to use the **static** version of Partition Manager Tool (`pmt-static`) on your Android device through **ADB**.
Its written for beginners — no advanced knowledge needed.
---
## 📦 Why Static Version?
The **static** build of PMT contains everything it needs inside one single file.
This means you can run it directly on your Android device **without** installing extra libraries.
Perfect for quick tasks via ADB.
---
## 📋 Requirements
- **ADB installed** on your computer
(Part of the Android SDK Platform Tools — [Download here](https://developer.android.com/studio/releases/platform-tools))
- **USB Debugging enabled** on your phone
(Settings → Developer options → Enable USB debugging)
- Your **phone connected via USB** and recognized by ADB
---
## 🚀 Step-by-Step Usage
### 1⃣ Get the Correct Binary
Download the **`pmt-static`** file that matches your devices architecture:
- **`pmt-static-arm64-v8a`** → For 64-bit devices
- **`pmt-static-armeabi-v7a`** → For 32-bit devices
Unzip the downloaded `.zip` file — you should now have a `pmt` binary.
---
### 2⃣ Push the Binary to Your Device
Use ADB to copy the `pmt` file to your phones temporary folder:
```bash
# Rename for more easily usage
mv pmt_static pmt
adb push pmt /data/local/tmp/pmt
```
### 3⃣ Open an ADB Shell
Access your device shell:
```bash
adb shell
```
### 4⃣ Change to the Directory
Move into the temporary directory where pmt is stored:
```bash
cd /data/local/tmp
```
### 5⃣ Give Execute Permission
Allow the binary to be executed:
```bash
chmod 755 pmt
```
### 6⃣ Run PMT
You can now run PMT directly from this directory:
```bash
# Open root terminal
su
./pmt --help
```
Example — Back up the boot partition:
```bash
./pmt backup boot
```
### 💡 Tips
Commands must be run from /data/local/tmp unless you move pmt elsewhere.\
The /data/local/tmp folder is cleared when you reboot your device.\
Static builds are completely standalone — no missing library issues.
---
## License
Partition Manager Tool is licensed under the **Apache 2.0 License**.
Copyright © YZBruh.
---
## Bug Reports
Please submit issues at:
[https://github.com/ShawkTeam/pmt-renovated/issues](https://github.com/ShawkTeam/pmt-renovated/issues)

View File

@@ -15,74 +15,68 @@
# limitations under the License.
#
set -e
BUILD_64="build_arm64-v8a"
BUILD_32="build_armeabi-v7a"
THIS="$(basename $0)"
TARGET_ABI_LIST=("arm64-v8a" "armeabi-v7a")
echo() { command echo "[$THIS]: $@"; }
checks()
{
checks() {
if [ -z "$ANDROID_NDK" ]; then
echo "Please set ANDROID_NDK variable as your NDK path."
exit 1
fi
if [ ! -f /usr/bin/cmake ] && [ ! -f /bin/cmake ]; then
if ! which cmake &>/dev/null; then
echo "Please verify your CMake installation."
exit 1
fi
if ! which ninja &>/dev/null; then
echo "Please verify your Ninja installation."
exit 1
fi
}
clean()
{
clean() {
echo "Cleaning workspace."
rm -rf $BUILD_32 $BUILD_64 \
include/generated \
for a in ${TARGET_ABI_LIST[@]}; do rm -rf build_$a; done
rm -rf include/generated \
srclib/libhelper/tests/dir \
srclib/libhelper/tests/linkdir \
srclib/libhelper/tests/file.txt
}
build()
{
mkdir -p $BUILD_64 $BUILD_32
build() {
set -e
command echo -e "BUILD INFO:
ARCHS: arm64-v8a armeabi-v7a
ARCHS: ${TARGET_ABI_LIST[@]}
ANDROID_PLATFORM: $ANDROID_PLATFORM
ANDROID_TOOLCHAIN_FILE: $ANDROID_NDK/build/cmake/android.toolchain.cmake\n"
echo "Configuring for arm64-v8a..."
cmake -B $BUILD_64 -S . $1 \
-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=arm64-v8a \
-DANDROID_PLATFORM=$ANDROID_PLATFORM \
-DANDROID_STL=c++_static
for a in ${TARGET_ABI_LIST[@]}; do
echo "Configuring for $a..."
mkdir -p build_$a
cmake -B build_$a -G Ninja -S . $1 \
-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=$a \
-DANDROID_PLATFORM=$ANDROID_PLATFORM \
-DANDROID_STL=c++_static
done
echo "Configuring for armeabi-v7a..."
cmake -B $BUILD_32 -S . $1 \
-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=armeabi-v7a \
-DANDROID_PLATFORM=$ANDROID_PLATFORM \
-DANDROID_STL=c++_static
CORES=$(($(nproc --all) - 2))
[ $CORES -eq 0 ] && CORES=2
echo "Building arm64-v8a artifacts..."
cmake --build $BUILD_64
echo "arm64-v8a build complete, artifacts: $PWD/$BUILD_64"
echo "Building armeabi-v7a artifacts..."
cmake --build $BUILD_32
echo "armeabi-v7a build complete, artifacts: $PWD/$BUILD_32"
for a in ${TARGET_ABI_LIST[@]}; do
echo "Building $a artifacts... Using $CORES thread."
cmake --build build_$a -j$CORES
echo "$a build complete, artifacts: $PWD/build_$a"
done
}
if [ $# -eq 0 ]; then
command echo "Usage: $0 build|rebuild|clean [EXTRA_CMAKE_FLAGS] [ANDROID_PLATFORM=SELECTED_ANDROID_PLATFORM]"
command echo -e "Usage: $0 build|rebuild|clean [EXTRA_CMAKE_FLAGS]\n HINT: Export ANDROID_PLATFORM if you set min Android target.\n HINT: Change TARGET_ABI_LIST array in build.sh if you build other archs."
exit 1
fi
if [ -z $ANDROID_PLATFORM ]; then ANDROID_PLATFORM="android-21"; fi
[ -z $ANDROID_PLATFORM ] && ANDROID_PLATFORM="android-21"
checks
case $1 in

View File

@@ -3902,9 +3902,9 @@ get_default_flag_values(const std::string &str);
/// Get a vector of short names, one of long names, and a single name
CLI11_INLINE
std::tuple<std::vector<std::string>, std::vector<std::string>, std::string>
get_names(const std::vector<std::string> &input,
bool allow_non_standard = false);
std::tuple<std::vector<std::string>, std::vector<std::string>, std::string>
get_names(const std::vector<std::string> &input,
bool allow_non_standard = false);
} // namespace detail
@@ -3995,8 +3995,8 @@ get_default_flag_values(const std::string &str) {
}
CLI11_INLINE
std::tuple<std::vector<std::string>, std::vector<std::string>, std::string>
get_names(const std::vector<std::string> &input, bool allow_non_standard) {
std::tuple<std::vector<std::string>, std::vector<std::string>, std::string>
get_names(const std::vector<std::string> &input, bool allow_non_standard) {
std::vector<std::string> short_names;
std::vector<std::string> long_names;

View File

@@ -17,9 +17,9 @@
#ifndef LIBPMT_LIB_HPP
#define LIBPMT_LIB_HPP
#include <CLI/CLI11.hpp>
#include <libhelper/lib.hpp>
#include <libpartition_map/lib.hpp>
#include <CLI/CLI11.hpp>
#include <memory>
#include <string>
#include <vector>
@@ -28,76 +28,18 @@
#define PMTE "pmt"
#define PMTF "libpmt-function-manager"
// Quick access to variables.
#define VARS (*Variables)
// Quick access to partition map.
#define PART_MAP (*VARS.PartMap)
namespace PartitionManager {
// All function classes must inherit from this class.
class basic_function {
public:
CLI::App *cmd = nullptr;
virtual bool init(CLI::App &_app) = 0;
virtual bool run() = 0;
[[nodiscard]] virtual bool isUsed() const = 0;
[[nodiscard]] virtual const char *name() const = 0;
virtual ~basic_function() = default;
};
// A class for function management.
class basic_function_manager final {
private:
std::vector<std::unique_ptr<basic_function>> _functions;
public:
void registerFunction(std::unique_ptr<basic_function> _func, CLI::App &_app);
[[nodiscard]] bool isUsed(std::string name) const;
[[nodiscard]] bool handleAll() const;
};
class basic_variables final {
public:
basic_variables();
~basic_variables();
PartitionMap::BuildMap *PartMap;
std::string searchPath, logFile;
bool onLogical;
bool quietProcess;
bool verboseMode;
bool viewVersion;
bool forceProcess;
};
class variableProtect final {
private:
basic_variables *_ptr = nullptr;
public:
variableProtect();
~variableProtect();
void setVariablePointer(basic_variables *&_ptr);
};
using FunctionBase = basic_function;
using FunctionManager = basic_function_manager;
using VariableTable = basic_variables;
using Error = Helper::Error;
extern VariableTable *Variables;
int Main(int argc, char **argv);
// Print messages if not using quiet mode
__attribute__((format(printf, 1, 2))) void print(const char *format, ...);
__attribute__((format(printf, 1, 2))) void println(const char *format, ...);
// Format it input and return as std::string
__attribute__((format(printf, 1, 2))) std::string format(const char *format,
...);
// If there is a delimiter in the string, CLI::detail::split returns; if not, an
// empty vector is returned. And checks duplicate arguments.
std::vector<std::string> splitIfHasDelim(const std::string &s, char delim,
@@ -111,12 +53,118 @@ void processCommandLine(std::vector<std::string> &vec1,
bool checkForBadUsage = false);
// Setting ups buffer size
void setupBufferSize(int &size, const std::string &partition);
void setupBufferSize(uint64_t &size, const std::string &entry);
std::string getLibVersion();
std::string getAppVersion(); // Not Android app version (an Android app is
// planned!), tells pmt version.
enum basic_function_flags {
NO_SU = 1,
NO_MAP_CHECK = 2,
ADB_SUFFICIENT = 3,
};
// All function classes must inherit from this class.
class basic_function {
public:
CLI::App *cmd = nullptr;
std::vector<int> flags = {};
virtual bool init(CLI::App &_app) = 0;
virtual bool run() = 0;
[[nodiscard]] virtual bool isUsed() const = 0;
[[nodiscard]] virtual const char *name() const = 0;
virtual ~basic_function() = default;
};
// A class for function management.
template <class _Type> class basic_manager {
private:
std::vector<std::unique_ptr<_Type>> _functions;
public:
void registerFunction(std::unique_ptr<_Type> _func, CLI::App &_app) {
LOGN(PMTF, INFO) << "registering: " << _func->name() << std::endl;
for (const auto &f : _functions) {
if (std::string(_func->name()) == std::string(f->name())) {
LOGN(PMTF, INFO) << "Is already registered: " << _func->name()
<< ". Skipping." << std::endl;
return;
}
}
if (!_func->init(_app))
throw Helper::Error("Cannot init: %s", _func->name());
_functions.push_back(std::move(_func));
LOGN(PMTF, INFO) << _functions.back()->name() << " successfully registered."
<< std::endl;
}
[[nodiscard]] bool hasFlagOnUsedFunction(int flag) const {
for (const auto &func : _functions) {
if (func->isUsed()) {
std::for_each(func->flags.begin(), func->flags.end(), [&](const int x) {
LOGN(PMTF, INFO) << "Used flag " << x << " on " << func->name()
<< std::endl;
});
return std::find(func->flags.begin(), func->flags.end(), flag) !=
func->flags.end();
}
}
return false;
}
[[nodiscard]] bool isUsed(const std::string &name) const {
if (_functions.empty()) return false;
for (const auto &func : _functions) {
if (func->name() == name) return func->isUsed();
}
return false;
}
[[nodiscard]] bool handleAll() const {
LOGN(PMTF, INFO) << "running caught 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;
println("Target progress is not specified. Specify a progress.");
return false;
}
};
class basic_variables final {
public:
basic_variables();
std::unique_ptr<PartitionMap::BuildMap> PartMap;
std::string searchPath, logFile;
bool onLogical;
bool quietProcess;
bool verboseMode;
bool viewVersion;
bool forceProcess;
};
using FunctionBase = basic_function;
using FunctionManager = basic_manager<FunctionBase>;
using FunctionFlags = basic_function_flags;
using VariableTable = basic_variables;
using Error = Helper::Error;
extern std::unique_ptr<VariableTable> Variables;
extern FILE *pstdout, *pstderr;
} // namespace PartitionManager
#endif // #ifndef LIBPMT_LIB_HPP

21
include/nlohmann/LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2013-2025 Niels Lohmann
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

25521
include/nlohmann/json.hpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,187 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
#include <cstdint> // int64_t, uint64_t
#include <map> // map
#include <memory> // allocator
#include <string> // string
#include <vector> // vector
// #include <nlohmann/detail/abi_macros.hpp>
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
// This file contains all macro definitions affecting or depending on the ABI
#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
#if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
#if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 12 || NLOHMANN_JSON_VERSION_PATCH != 0
#warning "Already included a different version of the library!"
#endif
#endif
#endif
#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum)
#define NLOHMANN_JSON_VERSION_MINOR 12 // NOLINT(modernize-macro-to-enum)
#define NLOHMANN_JSON_VERSION_PATCH 0 // NOLINT(modernize-macro-to-enum)
#ifndef JSON_DIAGNOSTICS
#define JSON_DIAGNOSTICS 0
#endif
#ifndef JSON_DIAGNOSTIC_POSITIONS
#define JSON_DIAGNOSTIC_POSITIONS 0
#endif
#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
#endif
#if JSON_DIAGNOSTICS
#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
#else
#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
#endif
#if JSON_DIAGNOSTIC_POSITIONS
#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS _dp
#else
#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS
#endif
#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
#define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
#else
#define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
#endif
#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
#define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
#endif
// Construct the namespace ABI tags component
#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c) json_abi ## a ## b ## c
#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b, c) \
NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c)
#define NLOHMANN_JSON_ABI_TAGS \
NLOHMANN_JSON_ABI_TAGS_CONCAT( \
NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON, \
NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS)
// Construct the namespace version component
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
_v ## major ## _ ## minor ## _ ## patch
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
#define NLOHMANN_JSON_NAMESPACE_VERSION
#else
#define NLOHMANN_JSON_NAMESPACE_VERSION \
NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
NLOHMANN_JSON_VERSION_MINOR, \
NLOHMANN_JSON_VERSION_PATCH)
#endif
// Combine namespace components
#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
#ifndef NLOHMANN_JSON_NAMESPACE
#define NLOHMANN_JSON_NAMESPACE \
nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
NLOHMANN_JSON_ABI_TAGS, \
NLOHMANN_JSON_NAMESPACE_VERSION)
#endif
#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
#define NLOHMANN_JSON_NAMESPACE_BEGIN \
namespace nlohmann \
{ \
inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
NLOHMANN_JSON_ABI_TAGS, \
NLOHMANN_JSON_NAMESPACE_VERSION) \
{
#endif
#ifndef NLOHMANN_JSON_NAMESPACE_END
#define NLOHMANN_JSON_NAMESPACE_END \
} /* namespace (inline namespace) NOLINT(readability/namespace) */ \
} // namespace nlohmann
#endif
/*!
@brief namespace for Niels Lohmann
@see https://github.com/nlohmann
@since version 1.0.0
*/
NLOHMANN_JSON_NAMESPACE_BEGIN
/*!
@brief default JSONSerializer template argument
This serializer ignores the template arguments and uses ADL
([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
for serialization.
*/
template<typename T = void, typename SFINAE = void>
struct adl_serializer;
/// a class to store JSON values
/// @sa https://json.nlohmann.me/api/basic_json/
template<template<typename U, typename V, typename... Args> class ObjectType =
std::map,
template<typename U, typename... Args> class ArrayType = std::vector,
class StringType = std::string, class BooleanType = bool,
class NumberIntegerType = std::int64_t,
class NumberUnsignedType = std::uint64_t,
class NumberFloatType = double,
template<typename U> class AllocatorType = std::allocator,
template<typename T, typename SFINAE = void> class JSONSerializer =
adl_serializer,
class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
class CustomBaseClass = void>
class basic_json;
/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
/// @sa https://json.nlohmann.me/api/json_pointer/
template<typename RefStringType>
class json_pointer;
/*!
@brief default specialization
@sa https://json.nlohmann.me/api/json/
*/
using json = basic_json<>;
/// @brief a minimal map-like container that preserves insertion order
/// @sa https://json.nlohmann.me/api/ordered_map/
template<class Key, class T, class IgnoredLess, class Allocator>
struct ordered_map;
/// @brief specialization that maintains the insertion order of object keys
/// @sa https://json.nlohmann.me/api/ordered_json/
using ordered_json = basic_json<nlohmann::ordered_map>;
NLOHMANN_JSON_NAMESPACE_END
#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_

View File

@@ -1,4 +1,3 @@
#!/data/data/com.termux/files/usr/bin/env bash
#
# Copyright 2025 Yağız Zengin
#
@@ -16,7 +15,7 @@
#
THIS="$(basename $0)"
RELEASE="20250811"
RELEASE="20250821"
echo() { command echo "[$THIS]: $@"; }
@@ -37,26 +36,25 @@ select_variant()
{
LINK=""; ARCH=""; VARIANT=""
if getprop ro.product.cpu.abi | grep "arm64-v8a" &>/dev/null; then ARCH="arm64-v8a";
if getprop ro.product.cpu.abi | grep "arm64-v8a" &>/dev/null; then ARCH="arm64-v8a"
else ARCH="armeabi-v7a"
fi
[ $1 == "static" ] && VARIANT="static-"
if grep "static" <<< $1 &>/dev/null; then VARIANT="static-"; fi
LINK="https://github.com/ShawkTeam/pmt-renovated/releases/download/${RELEASE}/pmt-${VARIANT}${ARCH}.zip"
LINK="https://github.com/ShawkTeam/pmt-renovated/releases/download/${RELEASE}/pmt-${VARIANT}${ARCH}.zip"
}
download()
{
mkdir -p $PREFIX/tmp
echo "Downloading pmt-${VARIANT}${ARCH}.zip (${RELEASE})"
if ! wget -o $PREFIX/tmp/pmt.zip "${LINK}" &>/dev/null; then
if ! wget -O $PREFIX/tmp/pmt.zip "${LINK}" &>/dev/null; then
echo "Download failed! LINK=${LINK}"
rm $PREFIX/tmp/*.zip
exit 1
fi
echo "Extracting..."
if ! unzip -d $PREFIX/tmp $PREFIX/tmp/pmt.zip &>/dev/null; then
if ! unzip -o -d $PREFIX/tmp $PREFIX/tmp/pmt.zip &>/dev/null; then
echo "Extraction failed!"
exit 1
fi
@@ -64,7 +62,7 @@ download()
setup()
{
[ -f $PREFIX/tmp/pmt_static ]; mv $PREFIX/tmp/pmt_static $PREFIX/tmp/pmt
[ -f $PREFIX/tmp/pmt_static ] && mv $PREFIX/tmp/pmt_static $PREFIX/tmp/pmt
set -e
install -t $PREFIX/bin $PREFIX/tmp/pmt
if [ -f $PREFIX/tmp/libhelper.so ]; then
@@ -76,7 +74,7 @@ setup()
uninstall()
{
rm -f $PREFIX/bin7pmt $PREFIX/lib/libhelper* $PREFIX/lib/libpartition_map* &>/dev/null
rm -f $PREFIX/bin/pmt $PREFIX/lib/libhelper* $PREFIX/lib/libpartition_map* &>/dev/null
}
is_installed()
@@ -97,11 +95,16 @@ if [ $# -eq 0 ]; then
exit 1
fi
if ! basename -a ${PREFIX}/bin/* | grep "termux" &>/dev/null; then
echo "This script only for termux!"
exit 1
fi
case $1 in
"install")
is_installed
checks
select_variant $([ "$2" == "--static" ] && echo static)
select_variant $(grep "static" <<< $2 &>/dev/null && command echo static)
download
setup
;;
@@ -109,13 +112,13 @@ case $1 in
uninstall && echo "Uninstalled successfully."
;;
"reinstall")
uninstall
checks
select_variant $([ "$2" == "--static" ] && echo static)
uninstall
checks
select_variant $(grep "static" <<< $2 &>/dev/null && command echo static)
download
setup
;;
*)
command echo "$0: Unknown argument: $1"
exit 1 ;;
command echo "$0: Unknown argument: $1"
exit 1 ;;
esac

View File

@@ -19,18 +19,20 @@ set(PMT_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/PartitionManager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Main.cpp
${CMAKE_CURRENT_SOURCE_DIR}/functions/BackupFunction.cpp
${CMAKE_CURRENT_SOURCE_DIR}/functions/CleanLogFunction.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/MemoryTestFunction.cpp
${CMAKE_CURRENT_SOURCE_DIR}/functions/PartitionSizeFunction.cpp
${CMAKE_CURRENT_SOURCE_DIR}/functions/RealPathFunction.cpp
${CMAKE_CURRENT_SOURCE_DIR}/functions/RealLinkPathFunction.cpp
${CMAKE_CURRENT_SOURCE_DIR}/functions/RebootFunction.cpp
${CMAKE_CURRENT_SOURCE_DIR}/functions/TypeFunction.cpp
)
# Add pmt
add_executable(pmt ${PMT_SOURCES})
add_executable(pmt ${PMT_SOURCES}
functions/CleanLogFunction.cpp)
add_executable(pmt_static ${PMT_SOURCES})
# Set linker options

View File

@@ -15,6 +15,7 @@
*/
#include <PartitionManager/PartitionManager.hpp>
#include <algorithm>
#include <fcntl.h>
#include <memory>
#include <string>
@@ -39,12 +40,19 @@ std::vector<std::string> splitIfHasDelim(const std::string &s, const char delim,
return vec;
}
void setupBufferSize(int &size, const std::string &partition) {
if (Variables->PartMap->sizeOf(partition) % size != 0) {
print("%sWARNING%s: Specified buffer size is invalid! Using 1 byte as "
"buffer size.",
YELLOW, STYLE_RESET);
size = 1;
void setupBufferSize(uint64_t &size, const std::string &entry) {
if (PART_MAP.hasPartition(entry) && PART_MAP.sizeOf(entry) % size != 0) {
println("%sWARNING%s: Specified buffer size is invalid for %s! Using "
"different buffer size for %s.",
YELLOW, STYLE_RESET, entry.data(), entry.data());
size = PART_MAP.sizeOf(entry) % 4096 == 0 ? 4096 : 1;
} else if (Helper::fileIsExists(entry)) {
if (Helper::fileSize(entry) % size != 0) {
println("%sWARNING%s: Specified buffer size is invalid for %s! using "
"different buffer size for %s.",
YELLOW, STYLE_RESET, entry.data(), entry.data());
size = Helper::fileSize(entry) % 4096 == 0 ? 4096 : 1;
}
}
}
@@ -58,40 +66,4 @@ void processCommandLine(std::vector<std::string> &vec1,
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) << _functions.back()->name() << " successfully registered."
<< std::endl;
}
bool basic_function_manager::isUsed(const std::string name) const {
if (_functions.empty()) return false;
for (const auto &func : _functions) {
if (func->name() == name) return func->isUsed();
}
return false;
}
bool basic_function_manager::handleAll() const {
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;
println("Target progress is not specified. Specify a progress.");
return false;
}
} // namespace PartitionManager

View File

@@ -18,6 +18,5 @@
int main(int argc, char **argv) {
// Call integrated main function in library
Helper::LoggingProperties::setProgramName(PMTE);
return PartitionManager::Main(argc, argv);
}

View File

@@ -16,69 +16,88 @@
#include "functions/functions.hpp"
#include <PartitionManager/PartitionManager.hpp>
#include <csignal>
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#ifndef ANDROID_BUILD
#include <generated/buildInfo.hpp>
#endif
#include <string>
#include <unistd.h>
namespace PartitionManager {
variableProtect protector;
auto Variables = new VariableTable();
variableProtect::variableProtect() {
Helper::LoggingProperties::setLogFile("/sdcard/Documents/last_pmt_logs.log");
}
variableProtect::~variableProtect() { delete _ptr; }
void variableProtect::setVariablePointer(basic_variables *&_ptr) {
this->_ptr = _ptr;
}
/**
* Register functions. Uses ready 'FuncManager' variable.
*
* Usage: REGISTER_FUNCTION(FUNCTION_CLASS);
*/
#define REGISTER_FUNCTION(cls) \
FuncManager.registerFunction(std::make_unique<cls>(), AppMain)
basic_variables::~basic_variables() { delete PartMap; }
basic_variables::basic_variables()
: logFile("/sdcard/Documents/last_pmt_logs.log"), onLogical(false),
: logFile(Helper::LoggingProperties::FILE), onLogical(false),
quietProcess(false), verboseMode(false), viewVersion(false),
forceProcess(false) {
try { PartMap = new PartitionMap::BuildMap(); }
catch (std::exception&) {}
try {
PartMap = std::make_unique<PartitionMap::BuildMap>();
} catch (std::exception &) {
}
}
__attribute__((constructor)) void init() {
Helper::LoggingProperties::setProgramName(PMTE);
Helper::LoggingProperties::setLogFile("/sdcard/Documents/last_pmt_logs.log");
}
static void sigHandler(const int sig) {
if (sig == SIGINT) println("\n%sInterrupted.%s", YELLOW, STYLE_RESET);
if (sig == SIGABRT) println("\n%sAborted.%s", RED, STYLE_RESET);
exit(sig);
}
static int write(void *cookie, const char *buf, const int size) {
auto *real = static_cast<FILE *>(cookie);
if (!VARS.quietProcess) {
const int ret = fwrite(buf, 1, static_cast<size_t>(size), real);
fflush(real);
return ret;
} else return size;
}
static FILE *make_fp(FILE *real) {
return funopen(real, nullptr, write, nullptr, nullptr);
}
auto Variables = std::make_unique<VariableTable>();
FILE *pstdout = make_fp(stdout);
FILE *pstderr = make_fp(stderr);
static Helper::garbageCollector collector;
int Main(int argc, char **argv) {
try {
// try-catch start
CLI::App AppMain{"Partition Manager Tool"};
protector.setVariablePointer(Variables);
FunctionManager FuncManager;
Helper::LoggingProperties::setProgramName(argv[0]);
collector.closeAfterProgress(pstdout);
collector.closeAfterProgress(pstderr);
AppMain.fallthrough(true);
AppMain.set_help_all_flag("--help-all", "Print full help message and exit");
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");
signal(SIGINT, sigHandler);
signal(SIGABRT, sigHandler);
if (!isatty(fileno(stdin))) {
char buf[128];
while (fgets(buf, sizeof(buf), stdin) != nullptr) {
buf[strcspn(buf, "\n")] = 0;
const char *token = strtok(buf, " \t");
while (token != nullptr) {
argv[argc] = strdup(token);
argc++;
token = strtok(nullptr, " \t");
}
}
}
if (argc < 2) {
println(
@@ -87,46 +106,92 @@ int Main(int argc, char **argv) {
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);
FuncManager.registerFunction(std::make_unique<realPathFunction>(), AppMain);
FuncManager.registerFunction(std::make_unique<realLinkPathFunction>(),
AppMain);
FuncManager.registerFunction(std::make_unique<typeFunction>(), AppMain);
FuncManager.registerFunction(std::make_unique<rebootFunction>(), AppMain);
CLI::App AppMain{"Partition Manager Tool"};
FunctionManager FuncManager;
AppMain.fallthrough(true);
AppMain.set_help_all_flag("--help-all", "Print full help message and exit");
AppMain.footer("Partition Manager Tool is written by YZBruh\n"
"This project licensed under "
"Apache 2.0 license\nReport "
"bugs to https://github.com/ShawkTeam/pmt-renovated/issues");
AppMain
.add_option("-S,--search-path", VARS.searchPath,
"Set partition search path")
->check([&](const std::string &val) {
if (val.find("/block") == std::string::npos)
return std::string(
"Partition search path is unexpected! Couldn't find "
"'block' in input path!");
return std::string();
});
AppMain.add_option("-L,--log-file", VARS.logFile, "Set log file");
AppMain.add_flag("-f,--force", VARS.forceProcess,
"Force process to be processed");
AppMain.add_flag("-l,--logical", VARS.onLogical,
"Specify that the target partition is dynamic");
AppMain.add_flag("-q,--quiet", VARS.quietProcess, "Quiet process");
AppMain.add_flag("-V,--verbose", VARS.verboseMode,
"Detailed information is written on the screen while the "
"transaction is "
"being carried out");
AppMain.add_flag("-v,--version", VARS.viewVersion,
"Print version and exit");
REGISTER_FUNCTION(backupFunction);
REGISTER_FUNCTION(cleanLogFunction);
REGISTER_FUNCTION(flashFunction);
REGISTER_FUNCTION(eraseFunction);
REGISTER_FUNCTION(partitionSizeFunction);
REGISTER_FUNCTION(infoFunction);
REGISTER_FUNCTION(realPathFunction);
REGISTER_FUNCTION(typeFunction);
REGISTER_FUNCTION(rebootFunction);
REGISTER_FUNCTION(memoryTestFunction);
CLI11_PARSE(AppMain, argc, argv);
if (Variables->verboseMode) Helper::LoggingProperties::setPrinting(YES);
if (Variables->viewVersion) {
if (VARS.verboseMode) Helper::LoggingProperties::setPrinting<YES>();
if (VARS.viewVersion) {
println("%s", 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)");
if (FuncManager.hasFlagOnUsedFunction(NO_MAP_CHECK)) {
if (!VARS.searchPath.empty())
WARNING("-S (--search-path) flag is ignored. Because, don't needed "
"partition map by your used function.\n");
if (VARS.onLogical)
WARNING("-l (--logical) flag ignored. Because, partition type don't "
"needed by your used function.\n");
} else {
if (!VARS.searchPath.empty()) (PART_MAP)(VARS.searchPath);
if (!VARS.PartMap && VARS.searchPath.empty())
throw Error("No default search entries were found. Specify a search "
"directory with -S "
"(--search-path)");
if (!Helper::hasSuperUser()) {
if (!(FuncManager.isUsed("rebootFunction") && Helper::hasAdbPermissions()))
throw Error(
"Partition Manager Tool is requires super-user privileges!\n");
if (VARS.onLogical) {
if (!PART_MAP.hasLogicalPartitions())
throw Error(
"This device doesn't contains logical partitions. But you "
"used -l (--logical) flag.");
}
}
if (!Helper::hasSuperUser() && !FuncManager.hasFlagOnUsedFunction(NO_SU)) {
if (!(FuncManager.hasFlagOnUsedFunction(ADB_SUFFICIENT) &&
Helper::hasAdbPermissions())) {
throw Error("This function is requires super-user privileges!");
}
}
return FuncManager.handleAll() == true ? EXIT_SUCCESS : EXIT_FAILURE;
} catch (Helper::Error &error) {
// catch Helper::Error
if (!Variables->quietProcess)
fprintf(stderr, "%s%sERROR(S) OCCURRED:%s\n%s", RED, BOLD, STYLE_RESET,
error.what());
fprintf(pstderr, "%s%sERROR(S) OCCURRED:%s\n%s\n", RED, BOLD, STYLE_RESET,
error.what());
return EXIT_FAILURE;
} catch (CLI::Error &error) {
// catch CLI::Error
@@ -140,29 +205,18 @@ int Main(int argc, char **argv) {
void print(const char *format, ...) {
va_list args;
va_start(args, format);
if (!Variables->quietProcess) vfprintf(stdout, format, args);
vfprintf(pstdout, format, args);
va_end(args);
}
void println(const char *format, ...) {
va_list args;
va_start(args, format);
if (!Variables->quietProcess) {
vfprintf(stdout, format, args);
print("\n");
}
vfprintf(pstdout, format, args);
print("\n");
va_end(args);
}
std::string format(const char *format, ...) {
va_list args;
va_start(args, format);
char str[1024];
vsnprintf(str, sizeof(str), format, args);
va_end(args);
return str;
}
std::string getLibVersion() { MKVERSION(PMT); }
std::string getAppVersion() { MKVERSION(PMTE); }

View File

@@ -25,35 +25,36 @@
#include <unistd.h>
#define BFUN "backupFunction"
#define FUNCTION_CLASS backupFunction
namespace PartitionManager {
pair backupFunction::runAsync(const std::string &partitionName,
const std::string &outputName, int bufferSize) {
if (!Variables->PartMap->hasPartition(partitionName))
return {format("Couldn't find partition: %s", partitionName.data()), false};
RUN_ASYNC(const std::string &partitionName, const std::string &outputName,
const uint64_t bufferSize) {
if (!PART_MAP.hasPartition(partitionName))
return {Helper::format("Couldn't find partition: %s", partitionName.data()),
false};
LOGN(BFUN, INFO) << "back upping " << partitionName << " as " << outputName
LOGN(BFUN, INFO) << "Back upping " << partitionName << " as " << outputName
<< std::endl;
if (Variables->onLogical && !Variables->PartMap->isLogical(partitionName)) {
if (Variables->forceProcess)
if (VARS.onLogical && !PART_MAP.isLogical(partitionName)) {
if (VARS.forceProcess)
LOGN(BFUN, WARNING)
<< "Partition " << partitionName
<< " is exists but not logical. Ignoring (from --force, -f)."
<< std::endl;
else
return {
format("Used --logical (-l) flag but is not logical partition: %s",
partitionName.data()),
false};
return {Helper::format(
"Used --logical (-l) flag but is not logical partition: %s",
partitionName.data()),
false};
}
if (Helper::fileIsExists(outputName) && !Variables->forceProcess)
return {format("%s is exists. Remove it, or use --force (-f) flag.",
outputName.data()),
if (Helper::fileIsExists(outputName) && !VARS.forceProcess)
return {Helper::format("%s is exists. Remove it, or use --force (-f) flag.",
outputName.data()),
false};
setupBufferSize(bufferSize, partitionName);
LOGN(BFUN, INFO) << "Using buffer size (for back upping " << partitionName
<< "): " << bufferSize << std::endl;
@@ -61,22 +62,22 @@ pair backupFunction::runAsync(const std::string &partitionName,
Helper::garbageCollector collector;
const int pfd = Helper::openAndAddToCloseList(
Variables->PartMap->getRealPathOf(partitionName), collector, O_RDONLY);
PART_MAP.getRealPathOf(partitionName), collector, O_RDONLY);
if (pfd < 0)
return {format("Can't open partition: %s: %s", partitionName.data(),
strerror(errno)),
return {Helper::format("Can't open partition: %s: %s", partitionName.data(),
strerror(errno)),
false};
const int ffd = Helper::openAndAddToCloseList(
outputName, collector, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (ffd < 0)
return {format("Can't create/open output file %s: %s", outputName.data(),
strerror(errno)),
return {Helper::format("Can't create/open output file %s: %s",
outputName.data(), strerror(errno)),
false};
LOGN(BFUN, INFO) << "Writing partition " << partitionName
<< " to file: " << outputName << std::endl;
auto *buffer = new char[bufferSize];
auto *buffer = new (std::nothrow) char[bufferSize];
collector.delAfterProgress(buffer);
memset(buffer, 0x00, bufferSize);
@@ -84,8 +85,8 @@ pair backupFunction::runAsync(const std::string &partitionName,
while ((bytesRead = read(pfd, buffer, bufferSize)) > 0) {
if (const ssize_t bytesWritten = write(ffd, buffer, bytesRead);
bytesWritten != bytesRead)
return {format("Can't write partition to output file %s: %s",
outputName.data(), strerror(errno)),
return {Helper::format("Can't write partition to output file %s: %s",
outputName.data(), strerror(errno)),
false};
}
@@ -94,18 +95,18 @@ pair backupFunction::runAsync(const std::string &partitionName,
<< outputName
<< ". Access problems maybe occur in non-root mode"
<< std::endl;
if (!Helper::changeMode(outputName, 0660))
if (!Helper::changeMode(outputName, 0664))
LOGN(BFUN, WARNING) << "Failed to change mode of output file as 660: "
<< outputName
<< ". Access problems maybe occur in non-root mode"
<< std::endl;
return {format("%s partition successfully back upped to %s",
partitionName.data(), outputName.data()),
return {Helper::format("%s partition successfully back upped to %s",
partitionName.data(), outputName.data()),
true};
}
bool backupFunction::init(CLI::App &_app) {
INIT {
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)")
@@ -115,14 +116,15 @@ bool backupFunction::init(CLI::App &_app) {
cmd->add_option("-O,--output-directory", outputDirectory,
"Directory to save the partition image(s)")
->check(CLI::ExistingDirectory);
cmd->add_option(
"-b,--buffer-size", bufferSize,
"Buffer size for reading partition(s) and writing to file(s)");
cmd->add_option("-b,--buffer-size", bufferSize,
"Buffer size for reading partition(s) and writing to file(s)")
->transform(CLI::AsSizeValue(false))
->default_val("4KB");
return true;
}
bool backupFunction::run() {
RUN {
processCommandLine(partitions, outputNames, rawPartitions, rawOutputNames,
',', true);
if (!outputNames.empty() && partitions.size() != outputNames.size())
@@ -131,13 +133,15 @@ bool backupFunction::run() {
std::vector<std::future<pair>> futures;
for (size_t i = 0; i < partitions.size(); i++) {
uint64_t buf = bufferSize;
std::string partitionName = partitions[i];
std::string outputName =
outputNames.empty() ? partitionName + ".img" : outputNames[i];
if (!outputDirectory.empty()) outputName.insert(0, outputDirectory + '/');
setupBufferSize(buf, partitionName);
futures.push_back(std::async(std::launch::async, runAsync, partitionName,
outputName, bufferSize));
outputName, buf));
LOGN(BFUN, INFO) << "Created thread backup upping " << partitionName
<< std::endl;
}
@@ -158,7 +162,7 @@ bool backupFunction::run() {
return endResult;
}
bool backupFunction::isUsed() const { return cmd->parsed(); }
IS_USED_COMMON_BODY
const char *backupFunction::name() const { return BFUN; }
NAME { return BFUN; }
} // namespace PartitionManager

View File

@@ -0,0 +1,42 @@
/*
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 "functions.hpp"
#include <PartitionManager/PartitionManager.hpp>
#define CFUN "cleanLogFunction"
#define FUNCTION_CLASS cleanLogFunction
namespace PartitionManager {
INIT {
LOGN(CFUN, INFO) << "Initializing variables of clean log function."
<< std::endl;
flags = {FunctionFlags::NO_MAP_CHECK, FunctionFlags::NO_SU};
cmd = _app.add_subcommand("clean-logs", "Clean PMT logs.");
return true;
}
RUN {
LOGN(CFUN, INFO) << "Removing log file: " << VARS.logFile << std::endl;
Helper::LoggingProperties::setLoggingState<YES>(); // eraseEntry writes log!
return Helper::eraseEntry(VARS.logFile);
}
IS_USED_COMMON_BODY
NAME { return CFUN; }
} // namespace PartitionManager

View File

@@ -17,58 +17,60 @@ Copyright 2025 Yağız Zengin
#include "functions.hpp"
#include <PartitionManager/PartitionManager.hpp>
#include <cerrno>
#include <cstdlib>
#include <fcntl.h>
#include <future>
#include <unistd.h>
#define EFUN "eraseFunction"
#define FUNCTION_CLASS eraseFunction
namespace PartitionManager {
pair eraseFunction::runAsync(const std::string &partitionName, int bufferSize) {
if (!Variables->PartMap->hasPartition(partitionName))
return {format("Couldn't find partition: %s", partitionName.data()), false};
RUN_ASYNC(const std::string &partitionName, const uint64_t bufferSize) {
if (!PART_MAP.hasPartition(partitionName))
return {Helper::format("Couldn't find partition: %s", partitionName.data()),
false};
if (Variables->onLogical && !Variables->PartMap->isLogical(partitionName)) {
if (Variables->forceProcess)
if (VARS.onLogical && !PART_MAP.isLogical(partitionName)) {
if (VARS.forceProcess)
LOGN(EFUN, WARNING)
<< "Partition " << partitionName
<< " is exists but not logical. Ignoring (from --force, -f)."
<< std::endl;
else
return {
format("Used --logical (-l) flag but is not logical partition: %s",
partitionName.data()),
false};
return {Helper::format(
"Used --logical (-l) flag but is not logical partition: %s",
partitionName.data()),
false};
}
setupBufferSize(bufferSize, partitionName);
LOGN(EFUN, INFO) << "Using buffer size: " << bufferSize;
// Automatically close file descriptors and delete allocated memories (arrays)
Helper::garbageCollector collector;
const int pfd = Helper::openAndAddToCloseList(
Variables->PartMap->getRealPathOf(partitionName), collector, O_WRONLY);
PART_MAP.getRealPathOf(partitionName), collector, O_WRONLY);
if (pfd < 0)
return {format("Can't open partition: %s: %s", partitionName.data(),
strerror(errno)),
return {Helper::format("Can't open partition: %s: %s", partitionName.data(),
strerror(errno)),
false};
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!");
if (!VARS.forceProcess) {
if (!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!"))
throw Error("Operation canceled.");
}
LOGN(EFUN, INFO) << "Writing zero bytes to partition: " << partitionName
<< std::endl;
auto *buffer = new char[bufferSize];
auto *buffer = new (std::nothrow) char[bufferSize];
collector.delAfterProgress(buffer);
memset(buffer, 0x00, bufferSize);
ssize_t bytesWritten = 0;
const uint64_t partitionSize = Variables->PartMap->sizeOf(partitionName);
const uint64_t partitionSize = PART_MAP.sizeOf(partitionName);
while (bytesWritten < partitionSize) {
size_t toWrite = sizeof(buffer);
@@ -76,33 +78,37 @@ pair eraseFunction::runAsync(const std::string &partitionName, int bufferSize) {
toWrite = partitionSize - bytesWritten;
if (const ssize_t result = write(pfd, buffer, toWrite); result == -1)
return {format("Can't write zero bytes to partition: %s: %s",
partitionName.data(), strerror(errno)),
return {Helper::format("Can't write zero bytes to partition: %s: %s",
partitionName.data(), strerror(errno)),
false};
else bytesWritten += result;
}
return {format("Successfully wrote zero bytes to the %s partition\n",
partitionName.data()),
return {Helper::format("Successfully wrote zero bytes to the %s partition",
partitionName.data()),
true};
}
bool eraseFunction::init(CLI::App &_app) {
INIT {
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)");
"Buffer size for writing zero bytes to partition(s)")
->transform(CLI::AsSizeValue(false))
->default_val("4KB");
return true;
}
bool eraseFunction::run() {
RUN {
std::vector<std::future<pair>> futures;
for (const auto &partitionName : partitions) {
uint64_t buf = bufferSize;
setupBufferSize(buf, partitionName);
futures.push_back(
std::async(std::launch::async, runAsync, partitionName, bufferSize));
std::async(std::launch::async, runAsync, partitionName, buf));
LOGN(EFUN, INFO) << "Created thread for writing zero bytes to "
<< partitionName << std::endl;
}
@@ -123,7 +129,7 @@ bool eraseFunction::run() {
return endResult;
}
bool eraseFunction::isUsed() const { return cmd->parsed(); }
IS_USED_COMMON_BODY
const char *eraseFunction::name() const { return EFUN; }
NAME { return EFUN; }
} // namespace PartitionManager

View File

@@ -23,58 +23,59 @@ Copyright 2025 Yağız Zengin
#include <unistd.h>
#define FFUN "flashFunction"
#define FUNCTION_CLASS flashFunction
namespace PartitionManager {
pair flashFunction::runAsync(const std::string &partitionName,
const std::string &imageName, int bufferSize) {
RUN_ASYNC(const std::string &partitionName, const std::string &imageName,
const uint64_t bufferSize, const bool deleteAfterProgress) {
if (!Helper::fileIsExists(imageName))
return {format("Couldn't find image file: %s", imageName.data()), false};
if (!Variables->PartMap->hasPartition(partitionName))
return {format("Couldn't find partition: %s", partitionName.data()), false};
if (Helper::fileSize(imageName) > Variables->PartMap->sizeOf(partitionName))
return {format("%s is larger than %s partition size!", imageName.data(),
partitionName.data()),
return {Helper::format("Couldn't find image file: %s", imageName.data()),
false};
if (!PART_MAP.hasPartition(partitionName))
return {Helper::format("Couldn't find partition: %s", partitionName.data()),
false};
if (Helper::fileSize(imageName) > PART_MAP.sizeOf(partitionName))
return {Helper::format("%s is larger than %s partition size!",
imageName.data(), partitionName.data()),
false};
LOGN(FFUN, INFO) << "flashing " << imageName << " to " << partitionName
<< std::endl;
if (Variables->onLogical && !Variables->PartMap->isLogical(partitionName)) {
if (Variables->forceProcess)
if (VARS.onLogical && !PART_MAP.isLogical(partitionName)) {
if (VARS.forceProcess)
LOGN(FFUN, WARNING)
<< "Partition " << partitionName
<< " is exists but not logical. Ignoring (from --force, -f)."
<< std::endl;
else
return {
format("Used --logical (-l) flag but is not logical partition: %s",
partitionName.data()),
false};
return {Helper::format(
"Used --logical (-l) flag but is not logical partition: %s",
partitionName.data()),
false};
}
setupBufferSize(bufferSize, imageName);
LOGN(FFUN, INFO) << "Using buffer size: " << bufferSize;
LOGN(FFUN, INFO) << "Using buffer size: " << bufferSize << std::endl;
// Automatically close file descriptors and delete allocated memories (arrays)
Helper::garbageCollector collector;
const int ffd = Helper::openAndAddToCloseList(imageName, collector, O_RDONLY);
if (ffd < 0)
return {format("Can't open image file %s: %s", imageName.data(),
strerror(errno)),
return {Helper::format("Can't open image file %s: %s", imageName.data(),
strerror(errno)),
false};
const int pfd = Helper::openAndAddToCloseList(
Variables->PartMap->getRealPathOf(partitionName), collector,
O_RDWR | O_TRUNC);
PART_MAP.getRealPathOf(partitionName), collector, O_RDWR | O_TRUNC);
if (pfd < 0)
return {format("Can't open partition: %s: %s", partitionName.data(),
strerror(errno)),
return {Helper::format("Can't open partition: %s: %s", partitionName.data(),
strerror(errno)),
false};
LOGN(FFUN, INFO) << "Writing image " << imageName
<< " to partition: " << partitionName << std::endl;
auto *buffer = new char[bufferSize];
auto *buffer = new (std::nothrow) char[bufferSize];
collector.delAfterProgress(buffer);
memset(buffer, 0x00, bufferSize);
@@ -82,17 +83,24 @@ pair flashFunction::runAsync(const std::string &partitionName,
while ((bytesRead = read(ffd, buffer, bufferSize)) > 0) {
if (const ssize_t bytesWritten = write(pfd, buffer, bytesRead);
bytesWritten != bytesRead)
return {format("Can't write partition to output file %s: %s",
imageName.data(), strerror(errno)),
return {Helper::format("Can't write partition to output file %s: %s",
imageName.data(), strerror(errno)),
false};
}
return {format("%s is successfully wrote to %s partition", imageName.data(),
partitionName.data()),
if (deleteAfterProgress) {
LOGN(FFUN, INFO) << "Deleting flash file: " << imageName << std::endl;
if (!Helper::eraseEntry(imageName) && !VARS.quietProcess)
WARNING(
std::string("Cannot erase flash file: " + imageName + "\n").data());
}
return {Helper::format("%s is successfully wrote to %s partition",
imageName.data(), partitionName.data()),
true};
}
bool flashFunction::init(CLI::App &_app) {
INIT {
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)")
@@ -100,28 +108,38 @@ bool flashFunction::init(CLI::App &_app) {
cmd->add_option("imageFile(s)", rawImageNames, "Name(s) of image file(s)")
->required();
cmd->add_option(
"-b,--buffer-size", bufferSize,
"Buffer size for reading image(s) and writing to partition(s)");
"-b,--buffer-size", bufferSize,
"Buffer size for reading image(s) and writing to partition(s)")
->transform(CLI::AsSizeValue(false))
->default_val("4KB");
cmd->add_option("-I,--image-directory", imageDirectory,
"Directory to find image(s) and flash to partition(s)");
cmd->add_flag("-d,--delete", deleteAfterProgress,
"Delete flash file(s) after progress.")
->default_val(false);
return true;
}
bool flashFunction::run() {
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++) {
if (!imageDirectory.empty()) imageNames[i].insert(0, imageDirectory + '/');
}
std::vector<std::future<pair>> futures;
for (size_t i = 0; i < partitions.size(); i++) {
std::string imageName = imageNames[i];
if (!imageDirectory.empty()) imageName.insert(0, imageDirectory + '/');
uint64_t buf = bufferSize;
setupBufferSize(buf, imageNames[i]);
futures.push_back(std::async(std::launch::async, runAsync, partitions[i],
imageName, bufferSize));
imageNames[i], bufferSize,
deleteAfterProgress));
LOGN(FFUN, INFO) << "Created thread for flashing image to " << partitions[i]
<< std::endl;
}
@@ -142,7 +160,7 @@ bool flashFunction::run() {
return endResult;
}
bool flashFunction::isUsed() const { return cmd->parsed(); }
IS_USED_COMMON_BODY
const char *flashFunction::name() const { return FFUN; }
NAME { return FFUN; }
} // namespace PartitionManager

View File

@@ -19,52 +19,62 @@ Copyright 2025 Yağız Zengin
#include <cerrno>
#include <cstdlib>
#include <fcntl.h>
#include <unistd.h>
#include <nlohmann/json.hpp>
#define IFUN "infoFunction"
#define FUNCTION_CLASS infoFunction
namespace PartitionManager {
bool infoFunction::init(CLI::App &_app) {
INIT {
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 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(',');
cmd->add_flag("-J,--json", jsonFormat,
"Print info(s) as JSON body. The body of each partition will "
"be written separately");
"be written separately")
->default_val(false);
cmd->add_flag("--as-byte", asByte, "View sizes as byte.")->default_val(true);
cmd->add_flag("--as-kilobyte", asKiloBytes, "View sizes as kilobyte.")
->default_val(false);
cmd->add_flag("--as-megabyte", asMega, "View sizes as megabyte.")
->default_val(false);
cmd->add_flag("--as-gigabyte", asGiga, "View sizes as gigabyte.")
->default_val(false);
cmd->add_option("--json-partition-name", jNamePartition,
"Speficy partition name element for JSON body");
"Specify partition name element for JSON body")
->default_val("name");
cmd->add_option("--json-size-name", jNameSize,
"Speficy size element name for JSON body");
"Specify size element name for JSON body")
->default_val("size");
cmd->add_option("--json-logical-name", jNameLogical,
"Speficy logical element name for JSON body");
"Specify logical element name for JSON body")
->default_val("isLogical");
cmd->add_option("--json-indent-size", jIndentSize,
"Set JSON indent size for printing to screen")
->default_val(2);
return true;
}
bool infoFunction::run() {
if (partitions.back() == "get-all" || partitions.back() == "getvar-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());
RUN {
std::vector<PartitionMap::Partition_t> jParts;
sizeCastTypes multiple;
if (asByte) multiple = B;
if (asKiloBytes) multiple = KB;
if (asMega) multiple = MB;
if (asGiga) multiple = GB;
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)
auto func = [this, &jParts, &multiple] COMMON_LAMBDA_PARAMS -> bool {
if (VARS.onLogical && !props.isLogical) {
if (VARS.forceProcess)
LOGN(IFUN, WARNING)
<< "Partition " << partition
<< " is exists but not logical. Ignoring (from --force, -f)."
@@ -75,28 +85,43 @@ bool infoFunction::run() {
}
if (jsonFormat)
#ifdef __LP64__
println("{\"%s\": \"%s\", \"%s\": %lu, \"%s\": %s}",
#else
println("{\"%s\": \"%s\", \"%s\": %llu, \"%s\": %s}",
#endif
jNamePartition.data(), partition.data(), jNameSize.data(),
Variables->PartMap->sizeOf(partition), jNameLogical.data(),
Variables->PartMap->isLogical(partition) ? "true" : "false");
jParts.push_back(
{partition,
{static_cast<uint64_t>(Helper::convertTo(props.size, multiple)),
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");
println("partition=%s size=%d isLogical=%s", partition.data(),
Helper::convertTo(props.size, multiple),
props.isLogical ? "true" : "false");
return true;
};
if (partitions.back() == "get-all" || partitions.back() == "getvar-all")
PART_MAP.doForAllPartitions(func);
else if (partitions.back() == "get-logicals")
PART_MAP.doForLogicalPartitions(func);
else if (partitions.back() == "get-physicals")
PART_MAP.doForPhysicalPartitions(func);
else PART_MAP.doForPartitionList(partitions, func);
if (jsonFormat) {
nlohmann::json j;
j["multipleType"] = Helper::multipleToString(multiple);
j["partitions"] = nlohmann::json::array();
for (const auto &[name, props] : jParts) {
j["partitions"].push_back({{jNamePartition, name},
{jNameSize, props.size},
{jNameLogical, props.isLogical}});
}
println("%s", j.dump(jIndentSize).data());
}
return true;
}
bool infoFunction::isUsed() const { return cmd->parsed(); }
IS_USED_COMMON_BODY
const char *infoFunction::name() const { return IFUN; };
NAME { return IFUN; };
} // namespace PartitionManager

View File

@@ -0,0 +1,132 @@
/*
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 "functions.hpp"
#include <PartitionManager/PartitionManager.hpp>
#include <chrono>
#include <cstdlib>
#include <cstring>
#include <fcntl.h>
#include <random>
#include <unistd.h>
#define MTFUN "memoryTestFunction"
#define FUNCTION_CLASS memoryTestFunction
namespace PartitionManager {
INIT {
LOGN(MTFUN, INFO) << "Initializing variables of memory test function."
<< std::endl;
flags = {FunctionFlags::NO_MAP_CHECK, FunctionFlags::ADB_SUFFICIENT};
cmd = _app.add_subcommand("memtest", "Test your write/read speed of device.");
cmd->add_option("testDirectory", testPath, "Path to test directory")
->default_val("/data/local/tmp")
->check([&](const std::string &val) {
if (val.find("/sdcard") != std::string::npos ||
val.find("/storage") != std::string::npos)
return std::string(
"Sequential read tests on FUSE-mounted paths do not give correct "
"results, so its use is prohibited (by pmt)!");
if (val != "/data/local/tmp" && !Helper::directoryIsExists(val))
return std::string("Couldn't find directory: " + val +
", no root? Try executing in ADB shell.");
return std::string();
});
cmd->add_option("-s,--file-size", testFileSize, "File size of test file")
->transform(CLI::AsSizeValue(false))
->default_val("1GB");
cmd->add_flag("--no-read-test", doNotReadTest,
"Don't read test data from disk")
->default_val(false);
return true;
}
RUN {
if (testFileSize > GB(2) && !VARS.forceProcess)
throw Error(
"File size is more than 2GB! Sizes over 2GB may not give accurate "
"results in the write test. Use -f (--force) for skip this error.");
LOGN(MTFUN, INFO) << "Starting memory test on " << testPath << std::endl;
Helper::garbageCollector collector;
const std::string test = Helper::pathJoin(testPath, "test.bin");
LOGN(MTFUN, INFO) << "Generating random data for testing" << std::endl;
auto *buffer = new (std::nothrow) char[bufferSize];
collector.delAfterProgress(buffer);
for (size_t i = 0; i < bufferSize; i++)
buffer[i] = static_cast<char>(Helper::Random<1024>::getNumber());
collector.delFileAfterProgress(test);
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", 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", strerror(errno));
bytesWritten += ret;
}
const auto endWrite = std::chrono::high_resolution_clock::now();
const double writeTime =
std::chrono::duration<double>(endWrite - startWrite).count();
println("Sequential write speed: %3.f MB/s",
(static_cast<double>(testFileSize) / (1024.0 * 1024.0)) / writeTime);
LOGN(MTFUN, INFO) << "Sequential write test done!" << std::endl;
if (!doNotReadTest) {
auto *rawBuffer = new char[bufferSize + 4096];
collector.delAfterProgress(rawBuffer);
auto *bufferRead = reinterpret_cast<char *>(
(reinterpret_cast<uintptr_t>(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", strerror(errno));
LOGN(MTFUN, INFO) << "Sequential read test started!" << std::endl;
const auto startRead = std::chrono::high_resolution_clock::now();
size_t total = 0;
ssize_t bytesRead;
while ((bytesRead = read(rfd, bufferRead, bufferSize)) > 0) {
total += bytesRead;
}
const auto endRead = std::chrono::high_resolution_clock::now();
const double read_time =
std::chrono::duration<double>(endRead - startRead).count();
println("Sequential read speed: %3.f MB/s",
(static_cast<double>(total) / (1024.0 * 1024.0)) / read_time);
LOGN(MTFUN, INFO) << "Sequential read test done!" << std::endl;
}
return true;
}
IS_USED_COMMON_BODY
NAME { return MTFUN; }
} // namespace PartitionManager

View File

@@ -18,44 +18,51 @@ Copyright 2025 Yağız Zengin
#include <PartitionManager/PartitionManager.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);
}
#define FUNCTION_CLASS partitionSizeFunction
namespace PartitionManager {
bool partitionSizeFunction::init(CLI::App &_app) {
INIT {
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 = _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.\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(',');
cmd->add_flag("--as-byte", asByte,
"Tell input size of partition list as byte.");
"Tell input size of partition list as byte.")
->default_val(false);
cmd->add_flag("--as-kilobyte", asKiloBytes,
"Tell input size of partition list as kilobyte.");
"Tell input size of partition list as kilobyte.")
->default_val(false);
cmd->add_flag("--as-megabyte", asMega,
"Tell input size of partition list as megabyte.");
"Tell input size of partition list as megabyte.")
->default_val(true);
cmd->add_flag("--as-gigabyte", asGiga,
"Tell input size of partition list as gigabyte.");
"Tell input size of partition list as gigabyte.")
->default_val(false);
cmd->add_flag("--only-size", onlySize,
"Tell input size of partition list as not printing multiple "
"and partition name.");
"and partition name.")
->default_val(false);
return true;
}
bool partitionSizeFunction::run() {
for (const auto &partition : partitions) {
if (!Variables->PartMap->hasPartition(partition))
throw Error("Couldn't find partition: %s", partition.data());
RUN {
sizeCastTypes multiple = {};
if (asByte) multiple = B;
if (asKiloBytes) multiple = KB;
if (asMega) multiple = MB;
if (asGiga) multiple = GB;
if (Variables->onLogical && !Variables->PartMap->isLogical(partition)) {
if (Variables->forceProcess)
auto func = [this, &multiple] COMMON_LAMBDA_PARAMS -> bool {
if (VARS.onLogical && !props.isLogical) {
if (VARS.forceProcess)
LOGN(SFUN, WARNING)
<< "Partition " << partition
<< " is exists but not logical. Ignoring (from --force, -f)."
@@ -65,26 +72,27 @@ bool partitionSizeFunction::run() {
partition.data());
}
std::string multiple = "MB";
if (asByte) multiple = "B";
if (asKiloBytes) multiple = "KB";
if (asMega) multiple = "MB";
if (asGiga) multiple = "GB";
if (onlySize)
println(
"%s",
convertTo(Variables->PartMap->sizeOf(partition), multiple).data());
if (onlySize) println("%d", Helper::convertTo(props.size, multiple));
else
println("%s: %s%s", partition.data(),
convertTo(Variables->PartMap->sizeOf(partition), multiple).data(),
multiple.data());
}
println("%s: %d%s", partition.data(),
Helper::convertTo(props.size, multiple),
Helper::multipleToString(multiple).data());
return true;
};
if (partitions.back() == "get-all" || partitions.back() == "getvar-all")
PART_MAP.doForAllPartitions(func);
else if (partitions.back() == "get-logicals")
PART_MAP.doForLogicalPartitions(func);
else if (partitions.back() == "get-physicals")
PART_MAP.doForPhysicalPartitions(func);
else PART_MAP.doForPartitionList(partitions, func);
return true;
}
bool partitionSizeFunction::isUsed() const { return cmd->parsed(); }
IS_USED_COMMON_BODY
const char *partitionSizeFunction::name() const { return SFUN; }
NAME { return SFUN; }
} // namespace PartitionManager

View File

@@ -1,59 +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 "functions.hpp"
#include <PartitionManager/PartitionManager.hpp>
#define RLPFUN "realPathFunction"
namespace PartitionManager {
bool realLinkPathFunction::init(CLI::App &_app) {
LOGN(RLPFUN, INFO) << "Initializing variables of real link path function."
<< std::endl;
cmd = _app.add_subcommand("real-linkpath",
"Tell real link paths of partition(s)");
cmd->add_option("partition(s)", partitions, "Partition name(s)")
->required()
->delimiter(',');
return true;
}
bool realLinkPathFunction::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(RLPFUN, 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());
}
println("%s", Variables->PartMap->getRealPathOf(partition).data());
}
return true;
}
bool realLinkPathFunction::isUsed() const { return cmd->parsed(); }
const char *realLinkPathFunction::name() const { return RLPFUN; }
} // namespace PartitionManager

View File

@@ -18,25 +18,28 @@
#include <PartitionManager/PartitionManager.hpp>
#define RPFUN "realPathFunction"
#define FUNCTION_CLASS realPathFunction
namespace PartitionManager {
bool realPathFunction::init(CLI::App &_app) {
INIT {
LOGN(RPFUN, INFO) << "Initializing variables of real path function."
<< std::endl;
cmd = _app.add_subcommand("real-path", "Tell real paths of partition(s)");
cmd->add_option("partition(s)", partitions, "Partition name(s)")
->required()
->delimiter(',');
cmd->add_flag("--real-link-path", realLinkPath, "Print real link path(s)")
->default_val(false);
return true;
}
bool realPathFunction::run() {
RUN {
for (const auto &partition : partitions) {
if (!Variables->PartMap->hasPartition(partition))
if (!PART_MAP.hasPartition(partition))
throw Error("Couldn't find partition: %s", partition.data());
if (Variables->onLogical && !Variables->PartMap->isLogical(partition)) {
if (Variables->forceProcess)
if (VARS.onLogical && !PART_MAP.isLogical(partition)) {
if (VARS.forceProcess)
LOGN(RPFUN, WARNING)
<< "Partition " << partition
<< " is exists but not logical. Ignoring (from --force, -f)."
@@ -46,13 +49,15 @@ bool realPathFunction::run() {
partition.data());
}
println("%s", Variables->PartMap->getRealPathOf(partition).data());
if (realLinkPath)
println("%s", PART_MAP.getRealLinkPathOf(partition).data());
else println("%s", PART_MAP.getRealPathOf(partition).data());
}
return true;
}
bool realPathFunction::isUsed() const { return cmd->parsed(); }
IS_USED_COMMON_BODY
const char *realPathFunction::name() const { return RPFUN; }
NAME { return RPFUN; }
} // namespace PartitionManager

View File

@@ -18,28 +18,30 @@ Copyright 2025 Yağız Zengin
#include <PartitionManager/PartitionManager.hpp>
#define RFUN "rebootFunction"
#define FUNCTION_CLASS rebootFunction
namespace PartitionManager {
bool rebootFunction::init(CLI::App &_app) {
INIT {
LOGN(RFUN, INFO) << "Initializing variables of reboot function." << std::endl;
flags = {FunctionFlags::NO_MAP_CHECK, FunctionFlags::ADB_SUFFICIENT};
cmd = _app.add_subcommand("reboot", "Reboots device");
cmd->add_option("rebootTarget", rebootTarget,
"Reboot target (default: normal)");
return true;
}
bool rebootFunction::run() {
RUN {
LOGN(RFUN, INFO) << "Rebooting device!!! (custom reboot target: "
<< (rebootTarget.empty() ? "none" : rebootTarget)
<< std::endl;
if (Helper::reboot(rebootTarget)) println("Reboot command was sent");
if (Helper::androidReboot(rebootTarget)) println("Reboot command was sent");
else throw Error("Cannot reboot device");
return true;
}
bool rebootFunction::isUsed() const { return cmd->parsed(); }
IS_USED_COMMON_BODY
const char *rebootFunction::name() const { return RFUN; }
NAME { return RFUN; }
} // namespace PartitionManager

View File

@@ -16,27 +16,33 @@
#include "functions.hpp"
#include <PartitionManager/PartitionManager.hpp>
#include <map>
#define TFUN "typeFunction"
#define FUNCTION_CLASS typeFunction
namespace PartitionManager {
bool typeFunction::init(CLI::App &_app) {
INIT {
LOGN(TFUN, INFO) << "Initializing variables of type function." << std::endl;
cmd = _app.add_subcommand("type", "Get type of the partition(s) or image(s)");
cmd->add_option("content(s)", contents, "Content(s)")
->required()
->delimiter(',');
cmd->add_option("-b,--buffer-size", bufferSize,
"Buffer size for max seek depth");
"Buffer size for max seek depth")
->transform(CLI::AsSizeValue(false))
->default_val("4KB");
cmd->add_flag("--only-check-android-magics", onlyCheckAndroidMagics,
"Only check Android magic values.");
"Only check Android magic values.")
->default_val(false);
cmd->add_flag("--only-check-filesystem-magics", onlyCheckFileSystemMagics,
"Only check filesystem magic values.");
"Only check filesystem magic values.")
->default_val(false);
return true;
}
bool typeFunction::run() {
std::unordered_map<uint64_t, std::string> magics;
RUN {
std::map<uint64_t, std::string> magics;
if (onlyCheckAndroidMagics)
magics.merge(PartitionMap::Extras::AndroidMagicMap);
else if (onlyCheckFileSystemMagics)
@@ -44,18 +50,16 @@ bool typeFunction::run() {
else magics.merge(PartitionMap::Extras::MagicMap);
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());
if (!PART_MAP.hasPartition(content) && !Helper::fileIsExists(content))
throw Error("Couldn't find partition or image file: %s", content.data());
bool found = false;
for (const auto &[magic, name] : magics) {
if (PartitionMap::Extras::hasMagic(
magic, bufferSize,
magic, static_cast<ssize_t>(bufferSize),
Helper::fileIsExists(content)
? content
: Variables->PartMap->getRealPathOf(content))) {
: PART_MAP.getRealPathOf(content))) {
println("%s contains %s magic (%s)", content.data(), name.data(),
PartitionMap::Extras::formatMagic(magic).data());
found = true;
@@ -64,15 +68,15 @@ bool typeFunction::run() {
}
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?)" : "");
}
return true;
}
bool typeFunction::isUsed() const { return cmd->parsed(); }
IS_USED_COMMON_BODY
const char *typeFunction::name() const { return TFUN; }
NAME { return TFUN; }
} // namespace PartitionManager

View File

@@ -21,6 +21,25 @@
#include <utility>
#include <vector>
#define INIT bool FUNCTION_CLASS::init(CLI::App &_app)
#define RUN bool FUNCTION_CLASS::run()
#define RUN_ASYNC pair FUNCTION_CLASS::runAsync
#define IS_USED bool FUNCTION_CLASS::isUsed() const
#define IS_USED_COMMON_BODY \
bool FUNCTION_CLASS::isUsed() const { return cmd->parsed(); }
#define NAME const char *FUNCTION_CLASS::name() const
/**
* Please define FUNCTION_CLASS before using these macros!!! (INIT etc.)
*/
#define COMMON_FUNCTION_BODY() \
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 {
using pair = std::pair<std::string, bool>;
@@ -29,18 +48,12 @@ class backupFunction final : public FunctionBase {
private:
std::vector<std::string> partitions, outputNames;
std::string rawPartitions, rawOutputNames, outputDirectory;
int bufferSize = 4096;
uint64_t bufferSize = 0;
public:
CLI::App *cmd = nullptr;
bool init(CLI::App &_app) override;
bool run() override;
COMMON_FUNCTION_BODY();
static pair runAsync(const std::string &partitionName,
const std::string &outputName, int bufferSize);
[[nodiscard]] bool isUsed() const override;
[[nodiscard]] const char *name() const override;
const std::string &outputName, uint64_t bufferSize);
};
// Image flasher function
@@ -48,35 +61,25 @@ class flashFunction final : public FunctionBase {
private:
std::vector<std::string> partitions, imageNames;
std::string rawPartitions, rawImageNames, imageDirectory;
int bufferSize = 4096;
uint64_t bufferSize = 0;
bool deleteAfterProgress = false;
public:
CLI::App *cmd = nullptr;
bool init(CLI::App &_app) override;
bool run() override;
COMMON_FUNCTION_BODY();
static pair runAsync(const std::string &partitionName,
const std::string &imageName, int bufferSize);
[[nodiscard]] bool isUsed() const override;
[[nodiscard]] const char *name() const override;
const std::string &imageName, uint64_t bufferSize,
bool deleteAfterProgress);
};
// Eraser function (writes zero bytes to partition)
class eraseFunction final : public FunctionBase {
private:
std::vector<std::string> partitions;
int bufferSize = 4096;
uint64_t bufferSize = 0;
public:
CLI::App *cmd = nullptr;
bool init(CLI::App &_app) override;
bool run() override;
static pair runAsync(const std::string &partitionName, int bufferSize);
[[nodiscard]] bool isUsed() const override;
[[nodiscard]] const char *name() const override;
COMMON_FUNCTION_BODY();
static pair runAsync(const std::string &partitionName, uint64_t bufferSize);
};
// Partition size getter function
@@ -87,75 +90,39 @@ private:
asGiga = 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;
COMMON_FUNCTION_BODY();
};
// 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;
std::string jNamePartition, jNameSize, jNameLogical;
int jIndentSize = 2;
bool jsonFormat = false, asByte = true, asKiloBytes = false, asMega = false,
asGiga = 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;
COMMON_FUNCTION_BODY();
};
class realPathFunction final : public FunctionBase {
private:
std::vector<std::string> partitions;
bool realLinkPath = 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;
};
class realLinkPathFunction final : public FunctionBase {
private:
std::vector<std::string> partitions;
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;
COMMON_FUNCTION_BODY();
};
class typeFunction final : public FunctionBase {
private:
std::vector<std::string> contents;
bool onlyCheckAndroidMagics = false, onlyCheckFileSystemMagics = false;
int bufferSize = 4096;
uint64_t bufferSize = 0;
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;
COMMON_FUNCTION_BODY();
};
class rebootFunction final : public FunctionBase {
@@ -163,14 +130,24 @@ private:
std::string rebootTarget;
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;
COMMON_FUNCTION_BODY();
};
class memoryTestFunction final : public FunctionBase {
private:
uint64_t bufferSize = MB(4), /* bufferSizeRandom = KB(4),*/ testFileSize = 0;
std::string testPath;
bool doNotReadTest = false;
public:
COMMON_FUNCTION_BODY();
};
class cleanLogFunction final : public FunctionBase {
public:
COMMON_FUNCTION_BODY();
};
} // namespace PartitionManager
#endif // #ifndef FUNCTIONS_HPP

View File

@@ -18,13 +18,25 @@
#define LIBHELPER_LIB_HPP
#include <cstdint>
#include <dirent.h>
#include <exception>
#include <functional>
#include <optional>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <string_view>
#include <vector>
#define KB(x) (static_cast<uint64_t>(x) * 1024) // KB(8) = 8192 (8 * 1024)
#define MB(x) (KB(x) * 1024) // MB(4) = 4194304 (KB(4) * 1024)
#define GB(x) (MB(x) * 1024) // GB(1) = 1073741824 (MB(1) * 1024)
#define TO_KB(x) (x / 1024) // TO_KB(1024) = 1
#define TO_MB(x) (TO_KB(x) / 1024) // TO_MB(2048) (2048 / 1024)
#define TO_GB(x) (TO_MB(x) / 1024) // TO_GB(1048576) (TO_MB(1048576) / 1024)
#ifndef ONLY_HELPER_MACROS
enum LogLevels {
@@ -34,6 +46,13 @@ enum LogLevels {
ABORT = static_cast<int>('A')
};
enum sizeCastTypes {
B = static_cast<int>('B'),
KB = static_cast<int>('K'),
MB = static_cast<int>('M'),
GB = static_cast<int>('G')
};
constexpr mode_t DEFAULT_FILE_PERMS = 0644;
constexpr mode_t DEFAULT_EXTENDED_FILE_PERMS = 0755;
constexpr mode_t DEFAULT_DIR_PERMS = 0755;
@@ -41,17 +60,29 @@ constexpr int YES = 1;
constexpr int NO = 0;
namespace Helper {
// Throwable error class
class Error final : public std::exception {
private:
std::string _message;
std::ostringstream _oss;
public:
__attribute__((format(printf, 2, 3))) explicit Error(const char *format, ...);
[[nodiscard]] const char *what() const noexcept override;
};
// Logging
class Logger final {
private:
LogLevels _level;
std::ostringstream _oss;
const char *_funcname, *_logFile, *_program_name, *_file;
const char *_function_name, *_logFile, *_program_name, *_file;
int _line;
public:
Logger(LogLevels level, const char *func, const char *file, const char *name,
const char *sfile, int line);
const char *source_file, int line);
~Logger();
@@ -63,34 +94,467 @@ public:
Logger &operator<<(std::ostream &(*msg)(std::ostream &));
};
// Throwable error class
class Error final : public std::exception {
private:
std::string _message;
public:
__attribute__((format(printf, 2, 3))) explicit Error(const char *format, ...);
[[nodiscard]] const char *what() const noexcept override;
};
// Close file descriptors and delete allocated array memory
class garbageCollector {
private:
std::vector<char *> _ptrs_c;
std::vector<uint8_t *> _ptrs_u;
std::vector<std::function<void()>> _cleaners;
std::vector<FILE *> _fps;
std::vector<DIR *> _dps;
std::vector<int> _fds;
std::vector<std::string> _files;
public:
~garbageCollector();
void delAfterProgress(char *&_ptr);
void delAfterProgress(uint8_t *&_ptr);
void closeAfterProgress(FILE *&_fp);
template <typename T> void delAfterProgress(T *_ptr) {
_cleaners.push_back([_ptr] { delete[] _ptr; });
}
void delFileAfterProgress(const std::string &_path);
void closeAfterProgress(FILE *_fp);
void closeAfterProgress(DIR *_dp);
void closeAfterProgress(int _fd);
};
template <int max = 100, int start = 0, int count = 10, int d = 0>
class Random {
static_assert(max > start, "max is larger than start");
static_assert(count > 1, "count is larger than 1");
static_assert(count <= max - start, "count is greater than max-start");
public:
static std::set<int> get() {
std::set<int> set;
std::random_device rd;
std::mt19937 gen(rd());
if constexpr (d > 0) {
std::uniform_int_distribution<> dist(0, (max - start - 1) / d);
while (set.size() < count)
set.insert(start + dist(gen) * d);
} else {
std::uniform_int_distribution<> dist(start, max - 1);
while (set.size() < count)
set.insert(dist(gen));
}
return set;
}
static int getNumber() {
std::random_device rd;
std::mt19937 gen(rd());
int ret;
if constexpr (d > 0) {
std::uniform_int_distribution<> dist(0, (max - start - 1) / d);
ret = start + dist(gen) * d;
} else {
std::uniform_int_distribution<> dist(start, max - 1); // max exclusive
ret = dist(gen);
}
return ret;
}
};
template <typename _Type1, typename _Type2, typename _Type3> class PureTuple {
private:
void expand_if_needed() {
if (count == capacity) {
capacity *= 2;
Data *data = new Data[capacity];
for (size_t i = 0; i < count; i++)
data[i] = tuple_data[i];
delete[] tuple_data;
tuple_data = data;
}
}
public:
struct Data {
_Type1 first;
_Type2 second;
_Type3 third;
bool
operator==(const std::tuple<_Type1, _Type2, _Type3> &t) const noexcept {
return first == std::get<0>(t) && second == std::get<1>(t) &&
third == std::get<2>(t);
}
bool operator==(const Data &other) const noexcept {
return first == other.first && second == other.second &&
third == other.third;
}
bool operator!=(const Data &other) const noexcept {
return !(*this == other);
}
explicit operator bool() const noexcept {
return first != _Type1{} || second != _Type2{} || third != _Type3{};
}
bool operator!() const noexcept { return !bool{*this}; }
void operator()(const std::tuple<_Type1, _Type2, _Type3> &t) {
first = std::get<0>(t);
second = std::get<1>(t);
third = std::get<2>(t);
}
Data &operator=(const std::tuple<_Type1, _Type2, _Type3> &t) {
first = std::get<0>(t);
second = std::get<1>(t);
third = std::get<2>(t);
return *this;
}
};
Data *tuple_data = nullptr;
Data tuple_data_type = {_Type1{}, _Type2{}, _Type3{}};
size_t capacity{}, count{};
PureTuple() : tuple_data(new Data[20]), capacity(20), count(0) {}
~PureTuple() { delete[] tuple_data; }
PureTuple(std::initializer_list<Data> val)
: tuple_data(new Data[20]), capacity(20), count(0) {
for (const auto &v : val)
insert(v);
}
PureTuple(PureTuple &other)
: tuple_data(new Data[other.capacity]), capacity(other.capacity),
count(other.count) {
std::copy(other.tuple_data, other.tuple_data + count, tuple_data);
}
PureTuple(PureTuple &&other) noexcept
: tuple_data(new Data[other.capacity]), capacity(other.capacity),
count(other.count) {
std::copy(other.tuple_data, other.tuple_data + count, tuple_data);
other.clear();
}
class iterator {
private:
Data *it;
public:
using iterator_category = std::random_access_iterator_tag;
using value_type = Data;
using difference_type = std::ptrdiff_t;
using pointer = Data *;
using reference = Data &;
explicit iterator(Data *ptr) : it(ptr) {}
pointer operator->() const { return it; }
reference operator*() { return *it; }
iterator &operator++() {
++it;
return *this;
}
iterator operator++(int) {
iterator tmp = *this;
++(*this);
return tmp;
}
iterator &operator--() {
--it;
return *this;
}
iterator operator--(int) {
iterator tmp = *this;
--(*this);
return tmp;
}
iterator &operator+=(difference_type n) {
it += n;
return *this;
}
iterator operator+(difference_type n) const { return iterator(it + n); }
iterator &operator-=(difference_type n) {
it -= n;
return *this;
}
iterator operator-(difference_type n) const { return iterator(it - n); }
difference_type operator-(const iterator &other) const {
return it - other.it;
}
reference operator[](difference_type n) const { return it[n]; }
bool operator<(const iterator &other) const { return it < other.it; }
bool operator>(const iterator &other) const { return it > other.it; }
bool operator<=(const iterator &other) const { return it <= other.it; }
bool operator>=(const iterator &other) const { return it >= other.it; }
bool operator!=(const iterator &other) const { return it != other.it; }
bool operator==(const iterator &other) const { return it == other.it; }
};
bool find(const Data &data) const noexcept {
for (size_t i = 0; i < count; i++)
if (data == tuple_data[i]) return true;
return false;
}
template <typename T = std::tuple<_Type1, _Type2, _Type3>>
std::enable_if_t<std::is_same_v<T, std::tuple<_Type1, _Type2, _Type3>>, bool>
find(const std::tuple<_Type1, _Type2, _Type3> &t) const noexcept {
for (size_t i = 0; i < count; i++)
if (tuple_data[i] == t) return true;
return false;
}
bool find(const _Type1 &val, const _Type2 &val2,
const _Type3 &val3) const noexcept {
for (size_t i = 0; i < count; i++)
if (tuple_data[i] == std::make_tuple(val, val2, val3)) return true;
return false;
}
void insert(const Data &val) noexcept {
expand_if_needed();
if (!find(val)) tuple_data[count++] = val;
}
template <typename T = std::tuple<_Type1, _Type2, _Type3>>
std::enable_if_t<std::is_same_v<T, std::tuple<_Type1, _Type2, _Type3>>, void>
insert(const std::tuple<_Type1, _Type2, _Type3> &t) noexcept {
expand_if_needed();
if (!find(t))
tuple_data[count++] =
Data{std::get<0>(t), std::get<1>(t), std::get<2>(t)};
}
void insert(const _Type1 &val, const _Type2 &val2,
const _Type3 &val3) noexcept {
expand_if_needed();
if (!find(val, val2, val3)) tuple_data[count++] = Data{val, val2, val3};
}
void merge(const PureTuple &other) noexcept {
for (const auto &v : other)
insert(v);
}
void pop_back() noexcept {
if (count > 0) --count;
}
void pop(const Data &data) noexcept {
for (size_t i = 0; i < count; i++) {
if (tuple_data[i] == data) {
for (size_t j = i; j < count - 1; j++)
tuple_data[j] = tuple_data[j + 1];
--count;
break;
}
}
}
void pop(const size_t i) noexcept {
if (i >= count) return;
for (size_t x = 0; x < count; x++) {
if (i == x) {
for (size_t j = i; j < count - 1; j++)
tuple_data[j] = tuple_data[j + 1];
--count;
break;
}
}
}
void pop(const _Type1 &val, const _Type2 &val2, const _Type3 &val3) noexcept {
for (size_t i = 0; i < count; i++) {
if (tuple_data[i] == std::make_tuple(val, val2, val3)) {
for (size_t j = i; j < count - 1; j++)
tuple_data[j] = tuple_data[j + 1];
--count;
break;
}
}
}
template <typename T = std::tuple<_Type1, _Type2, _Type3>>
std::enable_if_t<std::is_same_v<T, std::tuple<_Type1, _Type2, _Type3>>, void>
pop(const std::tuple<_Type1, _Type2, _Type3> &t) noexcept {
for (size_t i = 0; i < count; i++) {
if (tuple_data[i] == t) {
for (size_t j = i; j < count - 1; j++)
tuple_data[j] = tuple_data[j + 1];
--count;
break;
}
}
}
void clear() noexcept {
delete[] tuple_data;
count = 0;
capacity = 20;
tuple_data = new Data[capacity];
}
Data back() const noexcept {
return (count > 0) ? tuple_data[count - 1] : Data{};
}
Data top() const noexcept { return (count > 0) ? tuple_data[0] : Data{}; }
Data at(size_t i) const noexcept {
if (i >= count) return Data{};
return tuple_data[i];
}
void foreach (std::function<void(_Type1, _Type2, _Type3)> func) {
for (size_t i = 0; i < count; i++)
func(tuple_data[i].first, tuple_data[i].second, tuple_data[i].third);
}
void foreach (std::function<void(std::tuple<_Type1, _Type2, _Type3>)> func) {
for (size_t i = 0; i < count; i++)
func(std::make_tuple(tuple_data[i].first, tuple_data[i].second,
tuple_data[i].third));
}
[[nodiscard]] size_t size() const noexcept { return count; }
[[nodiscard]] bool empty() const noexcept { return count == 0; }
iterator begin() const noexcept { return iterator(tuple_data); }
iterator end() const noexcept { return iterator(tuple_data + count); }
explicit operator bool() const noexcept { return count > 0; }
bool operator!() const noexcept { return count == 0; }
bool operator==(const PureTuple &other) const noexcept {
if (this->count != other.count || this->capacity != other.capacity)
return false;
for (size_t i = 0; i < this->count; i++)
if (tuple_data[i] != other.tuple_data[i]) return false;
return true;
}
bool operator!=(const PureTuple &other) const noexcept {
return !(*this == other);
}
Data operator[](size_t i) const noexcept {
if (i >= count) return Data{};
return tuple_data[i];
}
explicit operator int() const noexcept { return count; }
PureTuple &operator=(const PureTuple &other) {
if (this != &other) {
delete[] tuple_data;
capacity = other.capacity;
count = other.count;
tuple_data = new Data[capacity];
std::copy(other.tuple_data, other.tuple_data + count, tuple_data);
}
return *this;
}
PureTuple &operator<<(const std::tuple<_Type1, _Type2, _Type3> &t) noexcept {
insert(t);
return *this;
}
friend PureTuple &operator>>(const std::tuple<_Type1, _Type2, _Type3> &t,
PureTuple &tuple) noexcept {
tuple.insert(t);
return tuple;
}
};
// Provides a capsule structure to store variable references and values.
template <typename _Type> class Capsule : public garbageCollector {
public:
_Type &value;
// The value to be stored is taken as a reference as an argument
explicit Capsule(_Type &value) noexcept : value(value) {}
// Set the value.
void set(const _Type &_value) noexcept { this->value = _value; }
void set(_Type &_value) noexcept { this->value = _value; }
// Get reference of the value.
_Type &get() noexcept { return this->value; }
const _Type &get() const noexcept { return this->value; }
// You can get the reference of the stored value in the input type (casting is
// required).
operator _Type &() noexcept { return this->value; }
operator const _Type &() const noexcept { return this->value; }
explicit operator _Type *() noexcept { return &this->value; }
// The value of another capsule is taken.
Capsule &operator=(const Capsule &other) noexcept {
this->value = other.value;
return *this;
}
// Assign another value.
Capsule &operator=(const _Type &_value) noexcept {
this->value = _value;
return *this;
}
// Check if this capsule and another capsule hold the same data.
bool operator==(const Capsule &other) const noexcept {
return this->value == other.value;
}
// Check if this capsule value and another capsule value hold the same data.
bool operator==(const _Type &_value) const noexcept {
return this->value == _value;
}
// Check that this capsule and another capsule do not hold the same data.
bool operator!=(const Capsule &other) const noexcept {
return !(*this == other);
}
// Check that this capsule value and another capsule value do not hold the
// same data.
bool operator!=(const _Type &_value) const noexcept {
return !(*this == _value);
}
// Check if the current held value is actually empty.
explicit operator bool() const noexcept { return this->value != _Type{}; }
// Check that the current held value is actually empty.
bool operator!() const noexcept { return this->value == _Type{}; }
// Change the value with the input operator.
friend Capsule &operator>>(const _Type &_value, Capsule &_capsule) noexcept {
_capsule.value = _value;
return _capsule;
}
// Get the reference of the value held.
_Type &operator()() noexcept { return value; }
const _Type &operator()() const noexcept { return value; }
// Set the value.
void operator()(const _Type &_value) noexcept { this->value = _value; }
};
namespace LoggingProperties {
extern std::string_view FILE, NAME;
extern bool PRINT, DISABLE;
@@ -98,89 +562,307 @@ extern bool PRINT, DISABLE;
void set(std::string_view name, std::string_view file);
void setProgramName(std::string_view name);
void setLogFile(std::string_view file);
void setPrinting(int state);
void setLoggingState(int state); // Disable/enable logging
template <int state> void setPrinting() {
if (state == 1 || state == 0) PRINT = state;
else PRINT = NO;
}
template <int state> void setLoggingState() {
if (state == 1 || state == 0) DISABLE = state;
else DISABLE = NO;
}
void reset();
} // namespace LoggingProperties
// Checkers
// -------------------------------
// Checkers - not throws Helper::Error
// -------------------------------
/**
* It is checked whether the user ID used is equivalent to AID_ROOT.
* See include/private/android_filesystem_config.h
*/
bool hasSuperUser();
/**
* It is checked whether the user ID used is equivalent to AID_SHELL.
* See include/private/android_filesystem_config.h
*/
bool hasAdbPermissions();
/**
* Checks whether the file/directory exists.
*/
bool isExists(std::string_view entry);
/**
* Checks whether the file exists.
*/
bool fileIsExists(std::string_view file);
/**
* Checks whether the directory exists.
*/
bool directoryIsExists(std::string_view directory);
/**
* Checks whether the link (symbolic or hard) exists.
*/
bool linkIsExists(std::string_view entry);
/**
* Checks if the entry is a symbolic link.
*/
bool isLink(std::string_view entry);
/**
* Checks if the entry is a symbolic link.
*/
bool isSymbolicLink(std::string_view entry);
/**
* Checks if the entry is a hard link.
*/
bool isHardLink(std::string_view entry);
/**
* Checks whether entry1 is linked to entry2.
*/
bool areLinked(std::string_view entry1, std::string_view entry2);
// File I/O
// -------------------------------
// File I/O - not throws Helper::Error
// -------------------------------
/**
* Writes given text into file.
* If file does not exist, it is automatically created.
* Returns true on success.
*/
bool writeFile(std::string_view file, std::string_view text);
/**
* Reads file content into string.
* On success returns file content.
* On error returns std::nullopt.
*/
std::optional<std::string> readFile(std::string_view file);
// -------------------------------
// Creators
// -------------------------------
/**
* Create directory.
*/
bool makeDirectory(std::string_view path);
/**
* Create recursive directory.
*/
bool makeRecursiveDirectory(std::string_view paths);
/**
* Create file.
*/
bool createFile(std::string_view path);
/**
* Symlink entry1 to entry2.
*/
bool createSymlink(std::string_view entry1, std::string_view entry2);
// Removers
// -------------------------------
// Removers - not throws Helper::Error
// -------------------------------
/**
* Remove file or empty directory.
*/
bool eraseEntry(std::string_view entry);
/**
* Remove directory and all directory contents recursively.
*/
bool eraseDirectoryRecursive(std::string_view directory);
// Getters
size_t fileSize(std::string_view file);
// -------------------------------
// Getters - not throws Helper::Error
// -------------------------------
/**
* Get file size.
*/
int64_t fileSize(std::string_view file);
/**
* Read symlinks.
*/
std::string readSymlink(std::string_view entry);
// -------------------------------
// SHA-256
// -------------------------------
/**
* Compare SHA-256 values SHA-256 of files.
* Throws Helper::Error on error occurred.
*/
bool sha256Compare(std::string_view file1, std::string_view file2);
/**
* Get SHA-256 of file.
* Throws Helper::Error on error occurred.
*/
std::optional<std::string> sha256Of(std::string_view path);
// Utilities
// -------------------------------
// Utilities - not throws Helper::Error
// -------------------------------
/**
* Copy file to dest.
*/
bool copyFile(std::string_view file, std::string_view dest);
/**
* Run shell command.
*/
bool runCommand(std::string_view cmd);
/**
* Shows message and asks for y/N from user.
*/
bool confirmPropt(std::string_view message);
/**
* Change file permissions.
*/
bool changeMode(std::string_view file, mode_t mode);
/**
* Change file owner (user ID and group ID).
*/
bool changeOwner(std::string_view file, uid_t uid, gid_t gid);
/**
* Get current working directory as string.
* Returns empty string on error.
*/
std::string currentWorkingDirectory();
/**
* Get current date as string (format: YYYY-MM-DD).
* Returns empty string on error.
*/
std::string currentDate();
/**
* Get current time as string (format: HH:MM:SS).
* Returns empty string on error.
*/
std::string currentTime();
std::string runCommandWithOutput(std::string_view cmd);
/**
* Run shell command return output as string.
* Returns std::pair<std::string, int>.
*/
std::pair<std::string, int> runCommandWithOutput(std::string_view cmd);
/**
* Joins base path with relative path and returns result.
*/
std::string pathJoin(std::string base, std::string relative);
/**
* Get the filename part of given path.
*/
std::string pathBasename(std::string_view entry);
/**
* Get the directory part of given path.
*/
std::string pathDirname(std::string_view entry);
// Android
std::string getProperty(std::string_view prop);
bool reboot(std::string_view arg);
/**
* Get random offset depending on size and bufferSize.
*/
uint64_t getRandomOffset(uint64_t size, uint64_t bufferSize);
// Library-specif
/**
* Convert input size to input multiple.
*/
int convertTo(uint64_t size, sizeCastTypes type);
/**
* Convert input multiple variable to string.
*/
std::string multipleToString(sizeCastTypes type);
/**
* Format it input and return as std::string.
*/
__attribute__((format(printf, 1, 2))) std::string format(const char *format,
...);
/**
* Convert input size to input multiple
*/
template <uint64_t size> int convertTo(const sizeCastTypes type) {
if (type == KB) return TO_KB(size);
if (type == MB) return TO_MB(size);
if (type == GB) return TO_GB(size);
return static_cast<int>(size);
}
// -------------------------------
// Android - not throws Helper::Error
// -------------------------------
#ifdef __ANDROID__
/**
* Get input property as string (for Android).
*/
std::string getProperty(std::string_view prop);
/**
* Reboot device to input mode (for Android).
*/
bool androidReboot(std::string_view arg);
#endif
/**
* Get libhelper library version string.
*/
std::string getLibVersion();
// Open input path with flags and add to integrity list. And return file
// descriptor
/**
* Open input path with flags and add to integrity list.
* And returns file descriptor.
*/
[[nodiscard]] int openAndAddToCloseList(const std::string_view &path,
garbageCollector &collector, int flags,
mode_t mode = 0000);
/**
* Open input path with flags and add to integrity list.
* And returns file pointer.
*/
[[nodiscard]] FILE *openAndAddToCloseList(const std::string_view &path,
garbageCollector &collector,
const char *mode);
/**
* Open input directory and add to integrity list.
* And returns directory pointer.
*/
[[nodiscard]] DIR *openAndAddToCloseList(const std::string_view &path,
garbageCollector &collector);
} // namespace Helper
#endif // #ifndef ONLY_HELPER_MACROS
#define HELPER "libhelper"
#define KB(x) (x * 1024) // KB(8) = 8192 (8 * 1024)
#define MB(x) (KB(x) * 1024) // MB(4) = 4194304 (KB(4) * 1024)
#define GB(x) (MB(x) * 1024) // GB(1) = 1073741824 (MB(1) * 1024)
#define TO_KB(x) (x / 1024) // TO_KB(1024) = 1
#define TO_MB(x) (TO_KB(x) / 1024) // TO_MB(2048) (2048 / 1024)
#define TO_GB(x) (TO_MB(x) / 1024) // TO_GB(1048576) (TO_MB(1048576) / 1024)
#define STYLE_RESET "\033[0m"
#define BOLD "\033[1m"
#define FAINT "\033[2m"
@@ -223,6 +905,9 @@ std::string getLibVersion();
#define LOG(level) \
Helper::Logger(level, __func__, Helper::LoggingProperties::FILE.data(), \
Helper::LoggingProperties::NAME.data(), __FILE__, __LINE__)
#define LOGF(file, level) \
Helper::Logger(level, __func__, file, \
Helper::LoggingProperties::NAME.data(), __FILE__, __LINE__)
#define LOGN(name, level) \
Helper::Logger(level, __func__, Helper::LoggingProperties::FILE.data(), \
name, __FILE__, __LINE__)
@@ -233,6 +918,10 @@ std::string getLibVersion();
if (condition) \
Helper::Logger(level, __func__, Helper::LoggingProperties::FILE.data(), \
Helper::LoggingProperties::NAME.data(), __FILE__, __LINE__)
#define LOGF_IF(file, level, condition) \
if (condition) \
Helper::Logger(level, __func__, file, \
Helper::LoggingProperties::NAME.data(), __FILE__, __LINE__)
#define LOGN_IF(name, level, condition) \
if (condition) \
Helper::Logger(level, __func__, Helper::LoggingProperties::FILE.data(), \
@@ -240,6 +929,15 @@ std::string getLibVersion();
#define LOGNF_IF(name, file, level, condition) \
if (condition) Helper::Logger(level, __func__, file, name, __FILE__, __LINE__)
#ifdef ANDROID_BUILD
#define MKVERSION(name) \
char vinfo[512]; \
sprintf(vinfo, \
"%s 1.3.0\nCompiler: clang\n" \
"BuildFlags: -Wall;-Werror;-Wno-deprecated-declarations;-Os", \
name); \
return std::string(vinfo)
#else
#define MKVERSION(name) \
char vinfo[512]; \
sprintf(vinfo, \
@@ -248,5 +946,6 @@ std::string getLibVersion();
name, BUILD_VERSION, BUILD_DATE, BUILD_TIME, BUILD_TYPE, \
BUILD_CMAKE_VERSION, BUILD_COMPILER_VERSION, BUILD_FLAGS); \
return std::string(vinfo)
#endif
#endif // #ifndef LIBHELPER_LIB_HPP

View File

@@ -19,8 +19,10 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <dirent.h>
#include <exception>
#include <fcntl.h>
#include <functional>
#include <libgen.h>
#include <libhelper/lib.hpp>
#include <sstream>
@@ -40,9 +42,9 @@ Error::Error(const char *format, ...) {
const char *Error::what() const noexcept { return _message.data(); }
Logger::Logger(const LogLevels level, const char *func, const char *file,
const char *name, const char *sfile, const int line)
: _level(level), _funcname(func), _logFile(file), _program_name(name),
_file(sfile), _line(line) {}
const char *name, const char *source_file, const int line)
: _level(level), _function_name(func), _logFile(file), _program_name(name),
_file(source_file), _line(line) {}
Logger::~Logger() {
if (LoggingProperties::DISABLE) return;
@@ -50,7 +52,7 @@ Logger::~Logger() {
snprintf(str, sizeof(str), "<%c> [ <prog %s> <on %s:%d> %s %s] %s(): %s",
static_cast<char>(_level), _program_name,
basename(const_cast<char *>(_file)), _line, currentDate().data(),
currentTime().data(), _funcname, _oss.str().data());
currentTime().data(), _function_name, _oss.str().data());
if (!isExists(_logFile)) {
if (const int fd =
@@ -58,11 +60,19 @@ Logger::~Logger() {
fd != -1)
close(fd);
else {
#ifdef ANDROID_BUILD
LoggingProperties::setLogFile("/tmp/last_pmt_logs.log")
#else
LoggingProperties::setLogFile("last_logs.log");
LOGN(HELPER, INFO) << "Cannot create log file: " << _logFile << ": "
<< strerror(errno)
<< " New logging file: last_logs.log (this file)."
<< std::endl;
#endif
LOGN(HELPER, INFO)
<< "Cannot create log file: " << _logFile << ": " << strerror(errno)
#ifdef ANDROID_BUILD
<< " New logging file: /tmp/last_pmt_logs.log (this file)."
#else
<< " New logging file: last_logs.log (this file)."
#endif
<< std::endl;
}
}
@@ -87,24 +97,24 @@ Logger &Logger::operator<<(std::ostream &(*msg)(std::ostream &)) {
}
garbageCollector::~garbageCollector() {
for (const auto &ptr : _ptrs_c)
delete[] ptr;
for (const auto &ptr : _ptrs_u)
delete[] ptr;
for (auto &ptr_func : _cleaners)
ptr_func();
for (const auto &fd : _fds)
close(fd);
for (const auto &fp : _fps)
fclose(fp);
for (const auto &dp : _dps)
closedir(dp);
for (const auto &file : _files)
eraseEntry(file);
}
void garbageCollector::delAfterProgress(char *&_ptr) {
_ptrs_c.push_back(_ptr);
}
void garbageCollector::delAfterProgress(uint8_t *&_ptr) {
_ptrs_u.push_back(_ptr);
void garbageCollector::delFileAfterProgress(const std::string &_path) {
_files.push_back(_path);
}
void garbageCollector::closeAfterProgress(const int _fd) {
_fds.push_back(_fd);
}
void garbageCollector::closeAfterProgress(FILE *&_fp) { _fps.push_back(_fp); }
void garbageCollector::closeAfterProgress(FILE *_fp) { _fps.push_back(_fp); }
void garbageCollector::closeAfterProgress(DIR *_dp) { _dps.push_back(_dp); }
} // namespace Helper

View File

@@ -151,8 +151,9 @@ bool eraseDirectoryRecursive(const std::string_view directory) {
LOGN(HELPER, INFO) << "erase recursive requested: " << directory << std::endl;
struct stat buf{};
dirent *entry;
garbageCollector collector;
DIR *dir = opendir(directory.data());
DIR *dir = openAndAddToCloseList(directory.data(), collector);
if (dir == nullptr) return false;
while ((entry = readdir(dir)) != nullptr) {
@@ -164,25 +165,17 @@ bool eraseDirectoryRecursive(const std::string_view directory) {
snprintf(fullpath, sizeof(fullpath), "%s/%s", directory.data(),
entry->d_name);
if (lstat(fullpath, &buf) == -1) {
closedir(dir);
return false;
}
if (lstat(fullpath, &buf) == -1) return false;
if (S_ISDIR(buf.st_mode)) {
if (!eraseDirectoryRecursive(fullpath)) {
closedir(dir);
return false;
}
if (!eraseDirectoryRecursive(fullpath)) return false;
} else if (S_ISREG(buf.st_mode)) {
if (!eraseEntry(fullpath)) return false;
} else {
if (unlink(fullpath) == -1) {
closedir(dir);
return false;
}
if (unlink(fullpath) == -1) return false;
}
}
closedir(dir);
if (rmdir(directory.data()) == -1) return false;
LOGN(HELPER, INFO) << "\"" << directory << "\" successfully erased."
@@ -203,10 +196,10 @@ std::string readSymlink(const std::string_view entry) {
return target;
}
size_t fileSize(const std::string_view file) {
int64_t fileSize(const std::string_view file) {
LOGN(HELPER, INFO) << "get file size request: " << file << std::endl;
struct stat st{};
if (stat(file.data(), &st) != 0) return false;
return static_cast<size_t>(st.st_size);
if (stat(file.data(), &st) != 0) return -1;
return st.st_size;
}
} // namespace Helper

View File

@@ -19,7 +19,14 @@
#include <ctime>
#include <cutils/android_reboot.h>
#include <fcntl.h>
#ifndef ANDROID_BUILD
#include <generated/buildInfo.hpp>
#include <sys/_system_properties.h>
#else
#include <sys/system_properties.h>
#endif
#include <cstdarg>
#include <cutils/android_reboot.h>
#include <iostream>
#include <libgen.h>
#include <libhelper/lib.hpp>
@@ -30,6 +37,7 @@
#include <sys/stat.h>
#include <unistd.h>
#ifdef __ANDROID__
// From system/core/libcutils/android_reboot.cpp android16-s2-release
int android_reboot(const unsigned cmd, int /*flags*/, const char *arg) {
int ret;
@@ -58,6 +66,7 @@ int android_reboot(const unsigned cmd, int /*flags*/, const char *arg) {
free(prop_value);
return ret;
}
#endif
namespace Helper {
namespace LoggingProperties {
@@ -77,16 +86,6 @@ void set(std::string_view file, std::string_view name) {
void setProgramName(const std::string_view name) { NAME = name; }
void setLogFile(const std::string_view file) { FILE = file; }
void setPrinting(const int state) {
if (state == 1 || state == 0) PRINT = state;
else PRINT = NO;
}
void setLoggingState(const int state) {
if (state == 1 || state == 0) DISABLE = state;
else DISABLE = NO;
}
} // namespace LoggingProperties
bool runCommand(const std::string_view cmd) {
@@ -121,7 +120,7 @@ std::string currentDate() {
return std::string(std::to_string(date->tm_mday) + "/" +
std::to_string(date->tm_mon + 1) + "/" +
std::to_string(date->tm_year + 1900));
return "--/--/----";
return {};
}
std::string currentTime() {
@@ -131,10 +130,10 @@ std::string currentTime() {
return std::string(std::to_string(date->tm_hour) + ":" +
std::to_string(date->tm_min) + ":" +
std::to_string(date->tm_sec));
return "--:--:--";
return {};
}
std::string runCommandWithOutput(const std::string_view cmd) {
std::pair<std::string, int> runCommandWithOutput(const std::string_view cmd) {
LOGN(HELPER, INFO) << "run command and catch out request: " << cmd
<< std::endl;
@@ -149,7 +148,9 @@ std::string runCommandWithOutput(const std::string_view cmd) {
while (fgets(buffer, sizeof(buffer), pipe_holder.get()) != nullptr)
output += buffer;
return output;
FILE *raw = pipe_holder.release();
const int status = pclose(raw);
return {output, (WIFEXITED(status) ? WEXITSTATUS(status) : -1)};
}
std::string pathJoin(std::string base, std::string relative) {
@@ -198,13 +199,21 @@ FILE *openAndAddToCloseList(const std::string_view &path,
return fp;
}
DIR *openAndAddToCloseList(const std::string_view &path,
garbageCollector &collector) {
DIR *dp = opendir(path.data());
collector.closeAfterProgress(dp);
return dp;
}
#ifdef __ANDROID__
std::string getProperty(const std::string_view prop) {
char val[PROP_VALUE_MAX];
const int x = __system_property_get(prop.data(), val);
return x > 0 ? val : "ERROR";
}
bool reboot(const std::string_view arg) {
bool androidReboot(const std::string_view arg) {
LOGN(HELPER, INFO) << "reboot request sent!!!" << std::endl;
unsigned cmd = ANDROID_RB_RESTART2;
@@ -215,6 +224,37 @@ bool reboot(const std::string_view arg) {
return android_reboot(cmd, 0, arg.empty() ? nullptr : arg.data()) != -1;
}
#endif
uint64_t getRandomOffset(const uint64_t size, const uint64_t bufferSize) {
if (size <= bufferSize) return 0;
const uint64_t maxOffset = size - bufferSize;
srand(time(nullptr));
return rand() % maxOffset;
}
int convertTo(const uint64_t size, const sizeCastTypes type) {
if (type == KB) return TO_KB(size);
if (type == MB) return TO_MB(size);
if (type == GB) return TO_GB(size);
return static_cast<int>(size);
}
std::string multipleToString(const sizeCastTypes type) {
if (type == KB) return "KB";
if (type == MB) return "MB";
if (type == GB) return "GB";
return "B";
}
std::string format(const char *format, ...) {
va_list args;
va_start(args, format);
char str[1024];
vsnprintf(str, sizeof(str), format, args);
va_end(args);
return str;
}
std::string getLibVersion() { MKVERSION("libhelper"); }
} // namespace Helper

View File

@@ -28,7 +28,7 @@ std::string test_path(const char *file) {
int main(int argc, char **argv) {
if (argc < 2) return 2;
else TEST_DIR = argv[1];
TEST_DIR = argv[1];
try {
std::cout << "Has super user?; " << std::boolalpha << Helper::hasSuperUser()
@@ -50,11 +50,11 @@ int main(int argc, char **argv) {
<< std::endl;
if (!Helper::writeFile("file.txt", "hello world"))
throw Helper::Error("Cannor write \"hello world\" in 'file.txt'");
throw Helper::Error("Cannot write \"hello world\" in 'file.txt'");
else std::cout << "file.txt writed." << std::endl;
auto content = Helper::readFile("file.txt");
if (!content) throw Helper::Error("Cannot read 'file.txt'");
if (const auto content = Helper::readFile("file.txt"); !content)
throw Helper::Error("Cannot read 'file.txt'");
else std::cout << "'file.txt': " << *content << std::endl;
std::cout << "Making directory 'dir2': " << std::boolalpha
@@ -78,8 +78,8 @@ int main(int argc, char **argv) {
std::cout << "Read link of 'file2lnk.txt': "
<< Helper::readSymlink(test_path("file2lnk.txt")) << std::endl;
auto sha256 = Helper::sha256Of(test_path("file2.txt"));
if (!sha256) throw Helper::Error("Cannot get sha256 of 'file2.txt'");
if (const auto sha256 = Helper::sha256Of(test_path("file2.txt")); !sha256)
throw Helper::Error("Cannot get sha256 of 'file2.txt'");
else std::cout << "SHA256 of 'file2.txt': " << *sha256 << std::endl;
std::cout << "'file2.txt' and 'file2lnk.txt' same? (SHA256): "
@@ -95,7 +95,7 @@ int main(int argc, char **argv) {
<< Helper::runCommand("ls") << std::endl;
std::cout << "Spawn confirm propt..." << std::endl;
bool p = Helper::confirmPropt("Please answer");
const bool p = Helper::confirmPropt("Please answer");
std::cout << "Result of confirm propt: " << std::boolalpha << p
<< std::endl;
@@ -104,7 +104,7 @@ int main(int argc, char **argv) {
std::cout << "Current date: " << Helper::currentDate() << std::endl;
std::cout << "Current time: " << Helper::currentTime() << std::endl;
std::cout << "Output of 'ls' command: "
<< Helper::runCommandWithOutput("ls") << std::endl;
<< Helper::runCommandWithOutput("ls").first << std::endl;
std::cout << "Basename of " << test_path("file2.txt") << ": "
<< Helper::pathBasename(test_path("file2.txt")) << std::endl;
std::cout << "Dirname of " << test_path("file2.txt") << ": "
@@ -119,13 +119,29 @@ int main(int argc, char **argv) {
std::cout << "pathJoin() test 4: " << Helper::pathJoin("mydir", "/dir2")
<< std::endl;
Helper::PureTuple<int, std::string, bool> values = {
{1, "hi", true}, {2, "im", true}, {3, "helper", false}};
values.insert(std::make_tuple(0, "hi", false));
values.insert(2, "im", true);
values.insert({3, "helper", true});
values.pop({3, "helper", true});
values.pop_back();
std::cout << "pure tuple test: " << std::boolalpha
<< static_cast<bool>(values.at(0)) << std::endl;
for (const auto &[x, y, z] : values) {
std::cout << std::boolalpha << "(" << x << ", " << y << ", " << z << ")"
<< std::endl;
}
std::cout << Helper::getLibVersion() << std::endl;
LOG(INFO) << "Info message" << std::endl;
LOG(WARNING) << "Warning message" << std::endl;
LOG(ERROR) << "Error message" << std::endl;
LOG(ABORT) << "Abort message" << std::endl;
} catch (Helper::Error &err) {
} catch (std::exception &err) {
std::cout << err.what() << std::endl;
return 1;
}

View File

@@ -19,13 +19,14 @@
#include <cstdint> // for uint64_t
#include <exception>
#include <functional>
#include <libhelper/lib.hpp>
#include <list>
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <unordered_map>
#include <utility> // for std::pair
namespace PartitionMap {
@@ -38,11 +39,19 @@ struct _entry {
} props;
};
struct _returnable_entry {
uint64_t size;
bool isLogical;
};
using BasicInf = _returnable_entry;
using Info = _entry;
/**
* The main type of the library. The Builder class is designed
* to be easily manipulated and modified only on this class.
*/
class basic_partition_map final {
class basic_partition_map {
private:
void _resize_map();
@@ -52,15 +61,9 @@ public:
_entry *_data;
size_t _count{}, _capacity{};
struct _returnable_entry {
uint64_t size;
bool isLogical;
};
using BasicInf = _returnable_entry;
basic_partition_map(const std::string &name, uint64_t size, bool logical);
basic_partition_map(const basic_partition_map &other);
basic_partition_map(basic_partition_map &&other) noexcept;
basic_partition_map();
~basic_partition_map();
@@ -80,6 +83,14 @@ public:
bool operator==(const basic_partition_map &other) const;
bool operator!=(const basic_partition_map &other) const;
bool operator!() const;
explicit operator bool() const;
Info operator[](int index) const;
BasicInf operator[](const std::string_view &name) const;
explicit operator std::vector<Info>() const;
explicit operator int() const;
class iterator {
public:
@@ -118,6 +129,7 @@ public:
[[nodiscard]] constant_iterator cend() const;
};
using Partition_t = _entry;
using Map_t = basic_partition_map;
class basic_partition_map_builder final {
@@ -147,9 +159,13 @@ public:
*/
explicit basic_partition_map_builder(std::string_view path);
/**
* Move constructor
*/
basic_partition_map_builder(basic_partition_map_builder &&other) noexcept;
/**
* Returns the current list content in Map_t type.
* If no list is created, returns std::nullopt.
*/
[[nodiscard]] Map_t getAll() const;
@@ -211,6 +227,11 @@ public:
*/
[[nodiscard]] bool hasPartition(std::string_view name) const;
/**
* Returns true if the device has dynamic partitions, false otherwise.
*/
[[nodiscard]] bool hasLogicalPartitions() const;
/**
* Returns the bool type status of whether the
* entered partition name is marked as logical in the
@@ -220,11 +241,51 @@ public:
*/
[[nodiscard]] bool isLogical(std::string_view name) const;
/**
* Copy partition list to vec, current vec contents are cleaned
*/
bool copyPartitionsToVector(std::vector<std::string> &vec) const;
/**
* Copy logical partition list to vec, current vec contents are cleaned
*/
bool copyLogicalPartitionsToVector(std::vector<std::string> &vec) const;
/**
* Copy physical partition list to vec, current vec contents are cleaned
*/
bool copyPhysicalPartitionsToVector(std::vector<std::string> &vec) const;
/**
* The created list and the current search index name are cleared.
*/
void clear();
/**
* Do input function (lambda) for all partitions.
*/
bool doForAllPartitions(
const std::function<bool(std::string, BasicInf)> &func) const;
/**
* Do input function (lambda) for physical partitions.
*/
bool doForPhysicalPartitions(
const std::function<bool(std::string, BasicInf)> &func) const;
/**
* Do input function (lambda) for logical partitions.
*/
bool doForLogicalPartitions(
const std::function<bool(std::string, BasicInf)> &func) const;
/**
* Do input function (lambda) for input partition list.
*/
bool doForPartitionList(
const std::vector<std::string> &partitions,
const std::function<bool(std::string, BasicInf)> &func) const;
/**
* The entered path is defined as the new search
* directory and the search is performed in the entered
@@ -282,6 +343,41 @@ public:
* Build map with input path. Implementation of readDirectory().
*/
bool operator()(std::string_view path);
/**
* Get Map_t object reference
*/
Map_t &operator*();
/**
* Get constant Map_t object reference
*/
const Map_t &operator*() const;
/**
* Get Info structure with given index
*/
Info operator[](int index) const;
/**
* Get BasicInfo structure with given index
*/
BasicInf operator[](const std::string_view &name) const;
/**
* Get map contents as vector (PartitionManager::Info type).
*/
[[nodiscard]] explicit operator std::vector<Info>() const;
/**
* Get total partition count in map (int type).
*/
[[nodiscard]] explicit operator int() const;
/**
* Get current working directory.
*/
[[nodiscard]] explicit operator std::string() const;
};
using Error = Helper::Error;
@@ -321,9 +417,9 @@ constexpr uint64_t ELF =
constexpr uint64_t RAW = 0x00000000;
} // namespace AndroidMagic
extern std::unordered_map<uint64_t, std::string> FileSystemMagicMap;
extern std::unordered_map<uint64_t, std::string> AndroidMagicMap;
extern std::unordered_map<uint64_t, std::string> MagicMap;
extern std::map<uint64_t, std::string> FileSystemMagicMap;
extern std::map<uint64_t, std::string> AndroidMagicMap;
extern std::map<uint64_t, std::string> MagicMap;
size_t getMagicLength(uint64_t magic);
bool hasMagic(uint64_t magic, ssize_t buf, const std::string &path);
@@ -333,4 +429,7 @@ std::string formatMagic(uint64_t magic);
#define MAP "libpartition_map"
#define COMMON_LAMBDA_PARAMS \
(const std::string &partition, const PartitionMap::BasicInf props)
#endif // #ifndef LIBPARTITION_MAP_LIB_HPP

View File

@@ -17,15 +17,15 @@
#include <fcntl.h>
#include <libhelper/lib.hpp>
#include <libpartition_map/lib.hpp>
#include <map>
#include <sstream>
#include <string>
#include <unistd.h>
#include <unordered_map>
#include "PartitionManager/PartitionManager.hpp"
namespace PartitionMap::Extras {
std::unordered_map<uint64_t, std::string> FileSystemMagicMap = {
std::map<uint64_t, std::string> FileSystemMagicMap = {
{FileSystemMagic::EXTFS_FS, "EXT2/3/4"},
{FileSystemMagic::F2FS_FS, "F2FS"},
{FileSystemMagic::EROFS_FS, "EROFS"},
@@ -36,7 +36,7 @@ std::unordered_map<uint64_t, std::string> FileSystemMagicMap = {
{FileSystemMagic::NTFS_FS, "NTFS"},
{FileSystemMagic::MSDOS_FS, "MSDOS"}};
std::unordered_map<uint64_t, std::string> AndroidMagicMap = {
std::map<uint64_t, std::string> AndroidMagicMap = {
{AndroidMagic::BOOT_IMAGE, "Android Boot Image"},
{AndroidMagic::VBOOT_IMAGE, "Android Vendor Boot Image"},
{AndroidMagic::LK_IMAGE, "Android LK (Bootloader)"},
@@ -47,7 +47,7 @@ std::unordered_map<uint64_t, std::string> AndroidMagicMap = {
{AndroidMagic::ELF, "ELF"},
{AndroidMagic::RAW, "Raw Data"}};
std::unordered_map<uint64_t, std::string> MagicMap = {
std::map<uint64_t, std::string> MagicMap = {
{AndroidMagic::BOOT_IMAGE, "Android Boot Image"},
{AndroidMagic::VBOOT_IMAGE, "Android Vendor Boot Image"},
{AndroidMagic::LK_IMAGE, "Android LK (Bootloader)"},
@@ -89,7 +89,7 @@ bool hasMagic(const uint64_t magic, const ssize_t buf,
return false;
}
auto *buffer = new uint8_t[buf];
auto *buffer = new (std::nothrow) uint8_t[buf];
collector.delAfterProgress(buffer);
const ssize_t bytesRead = read(fd, buffer, buf);

View File

@@ -20,7 +20,9 @@
#include <cstring>
#include <fcntl.h>
#include <filesystem>
#ifndef ANDROID_BUILD
#include <generated/buildInfo.hpp>
#endif
#include <iostream>
#include <libpartition_map/lib.hpp>
#include <linux/fs.h>
@@ -47,7 +49,13 @@ bool basic_partition_map_builder::_is_real_block_dir(
}
Map_t basic_partition_map_builder::_build_map(std::string_view path,
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;
std::vector<std::filesystem::directory_entry> entries{
std::filesystem::directory_iterator(path),
@@ -57,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::filesystem::directory_entry>)."
<< std::endl;
for (const auto &entry : entries) {
@@ -79,6 +87,9 @@ void basic_partition_map_builder::_insert_logicals(Map_t &&logicals) {
<< "merging created logical partition list to this object's variable."
<< std::endl;
_current_map.merge(logicals);
LOGN(MAP, INFO) << "Cleaning created logical partition because not need more."
<< std::endl;
logicals.clear();
}
void basic_partition_map_builder::_map_build_check() const {
@@ -125,8 +136,7 @@ basic_partition_map_builder::basic_partition_map_builder() {
LOGN(MAP, ERROR) << "Cannot build map by any default search entry."
<< std::endl;
LOGN(MAP, INFO) << "default constructor successfully ended work."
<< std::endl;
LOGN(MAP, INFO) << "default constructor ended work." << std::endl;
_insert_logicals(_build_map("/dev/block/mapper", true));
_map_builded = true;
}
@@ -151,12 +161,29 @@ basic_partition_map_builder::basic_partition_map_builder(
_map_builded = true;
}
basic_partition_map_builder::basic_partition_map_builder(
basic_partition_map_builder &&other) noexcept {
_current_map = Map_t(std::move(other._current_map));
_workdir = std::move(other._workdir);
_any_generating_error = other._any_generating_error;
_map_builded = other._map_builded;
other.clear();
}
bool basic_partition_map_builder::hasPartition(
const std::string_view name) const {
_map_build_check();
return _current_map.find(name);
}
bool basic_partition_map_builder::hasLogicalPartitions() const {
_map_build_check();
for (const auto &[name, props] : _current_map)
if (props.isLogical) return true;
return false;
}
bool basic_partition_map_builder::isLogical(const std::string_view name) const {
_map_build_check();
return _current_map.is_logical(name);
@@ -183,7 +210,7 @@ bool basic_partition_map_builder::readDirectory(const std::string_view path) {
throw Error("Cannot find directory: %s. Cannot build partition map!",
path.data());
LOGN(MAP, INFO) << "read " << path << " successfull." << std::endl;
LOGN(MAP, INFO) << "read " << path << " successfully." << std::endl;
_insert_logicals(_build_map("/dev/block/mapper", true));
_map_builded = true;
return true;
@@ -210,17 +237,148 @@ bool basic_partition_map_builder::readDefaultDirectories() {
LOGN(MAP, ERROR) << "Cannot build map by any default search entry."
<< std::endl;
LOGN(MAP, INFO) << "read default directories successfull." << std::endl;
LOGN(MAP, INFO) << "read default directories successfully." << std::endl;
_insert_logicals(_build_map("/dev/block/mapper", true));
_map_builded = true;
return true;
}
bool basic_partition_map_builder::copyPartitionsToVector(
std::vector<std::string> &vec) const {
if (_current_map.empty()) {
LOGN(MAP, ERROR) << "Current map is empty.";
return false;
}
vec.clear();
for (const auto &[name, props] : _current_map)
vec.push_back(name);
return true;
}
bool basic_partition_map_builder::copyLogicalPartitionsToVector(
std::vector<std::string> &vec) const {
if (_current_map.empty()) {
LOGN(MAP, ERROR) << "Current map is empty.";
return false;
}
std::vector<std::string> vec2;
for (const auto &[name, props] : _current_map)
if (props.isLogical) vec2.push_back(name);
if (vec2.empty()) {
LOGN(MAP, ERROR) << "Cannot find logical partitions in current map.";
return false;
} else vec = vec2;
return true;
}
bool basic_partition_map_builder::copyPhysicalPartitionsToVector(
std::vector<std::string> &vec) const {
if (_current_map.empty()) {
LOGN(MAP, ERROR) << "Current map is empty.";
return false;
}
std::vector<std::string> vec2;
for (const auto &[name, props] : _current_map)
if (!props.isLogical) vec2.push_back(name);
if (vec2.empty()) {
LOGN(MAP, ERROR) << "Cannot find physical partitions in current map.";
return false;
} else vec = vec2;
return true;
}
bool basic_partition_map_builder::empty() const {
_map_build_check();
return _current_map.empty();
}
bool basic_partition_map_builder::doForAllPartitions(
const std::function<bool(std::string, BasicInf)> &func) const {
_map_build_check();
bool err = false;
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 {
err = true;
LOGN(MAP, ERROR) << "Failed progress for " << name << " partition."
<< std::endl;
}
}
return err;
}
bool basic_partition_map_builder::doForPhysicalPartitions(
const std::function<bool(std::string, BasicInf)> &func) const {
_map_build_check();
bool err = false;
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 {
err = true;
LOGN(MAP, ERROR) << "Failed progress for " << name << " partition."
<< std::endl;
}
}
return err;
}
bool basic_partition_map_builder::doForLogicalPartitions(
const std::function<bool(std::string, BasicInf)> &func) const {
_map_build_check();
bool err = false;
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 {
err = true;
LOGN(MAP, ERROR) << "Failed progress for " << name << " partition."
<< std::endl;
}
}
return err;
}
bool basic_partition_map_builder::doForPartitionList(
const std::vector<std::string> &partitions,
const std::function<bool(std::string, BasicInf)> &func) const {
_map_build_check();
bool err = false;
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, _current_map[partition])) {
err = true;
LOGN(MAP, ERROR) << "Failed progress for " << partition << " partition."
<< std::endl;
}
}
return err;
}
uint64_t
basic_partition_map_builder::sizeOf(const std::string_view name) const {
_map_build_check();
@@ -251,5 +409,30 @@ bool basic_partition_map_builder::operator()(const std::string_view path) {
return readDirectory(path);
}
Map_t &basic_partition_map_builder::operator*() { return _current_map; }
const Map_t &basic_partition_map_builder::operator*() const {
return _current_map;
}
Info basic_partition_map_builder::operator[](const int index) const {
return _current_map[index];
}
BasicInf
basic_partition_map_builder::operator[](const std::string_view &name) const {
return _current_map[name];
}
basic_partition_map_builder::operator std::vector<Info>() const {
return static_cast<std::vector<Info>>(_current_map);
}
basic_partition_map_builder::operator int() const {
return static_cast<int>(_current_map);
}
basic_partition_map_builder::operator std::string() const { return _workdir; }
std::string getLibVersion() { MKVERSION("libpartition_map"); }
} // namespace PartitionMap

View File

@@ -116,6 +116,13 @@ basic_partition_map::basic_partition_map(const basic_partition_map &other)
std::copy(other._data, other._data + _count, _data);
}
basic_partition_map::basic_partition_map(basic_partition_map &&other) noexcept
: _data(new _entry[other._capacity]), _count(other._count),
_capacity(other._capacity) {
std::copy(other._data, other._data + _count, _data);
other.clear();
}
basic_partition_map::basic_partition_map() : _capacity(6) {
_data = new _entry[_capacity];
}
@@ -155,7 +162,7 @@ bool basic_partition_map::is_logical(const std::string_view name) const {
return false;
}
basic_partition_map::_returnable_entry
_returnable_entry
basic_partition_map::get_all(const std::string_view name) const {
if (const int pos = _index_of(name); name == _data[pos].name)
return _returnable_entry{_data[pos].props.size, _data[pos].props.isLogical};
@@ -177,13 +184,10 @@ std::string basic_partition_map::find_(const std::string &name) const {
size_t basic_partition_map::size() const { return _count; }
bool basic_partition_map::empty() const {
if (_count > 0) return false;
return true;
}
bool basic_partition_map::empty() const { return _count == 0; }
void basic_partition_map::clear() {
LOGN(MAP, INFO) << "map clean requested. Map is empty now." << std::endl;
LOGN(MAP, INFO) << "map clean requested. Cleaning..." << std::endl;
delete[] _data;
_count = 0;
_capacity = 6;
@@ -222,6 +226,35 @@ bool basic_partition_map::operator!=(const basic_partition_map &other) const {
return !(*this == other);
}
basic_partition_map::operator bool() const { return _count > 0; }
bool basic_partition_map::operator!() const { return _count == 0; }
Info basic_partition_map::operator[](const int index) const {
if (_count == 0 || index >= _count) return {};
return _data[index];
}
BasicInf basic_partition_map::operator[](const std::string_view &name) const {
if (_count == 0) return {};
if (const int i = _index_of(name); name == _data[i].name)
return {_data[i].props.size, _data[i].props.isLogical};
return {};
}
basic_partition_map::operator std::vector<Info>() const {
std::vector<Info> v;
if (_count == 0) return {};
for (size_t i = 0; i < _count; i++)
v.push_back(
{_data[i].name, {_data[i].props.size, _data[i].props.isLogical}});
return v;
}
basic_partition_map::operator int() const { return static_cast<int>(_count); }
basic_partition_map::iterator basic_partition_map::begin() const {
return iterator(_data);
}

View File

@@ -14,6 +14,7 @@
limitations under the License.
*/
#include <fstream>
#include <iostream>
#include <libpartition_map/lib.hpp>
#include <unistd.h>
@@ -54,10 +55,30 @@ int main() {
for (const auto &name : *physicals)
std::cout << " - " << name << std::endl;
if (const std::vector<PartitionMap::Info> parts =
static_cast<std::vector<PartitionMap::Info>>(MyMap);
parts.empty())
throw PartitionMap::Error(
"operator std::vector<PartitionMap::Info>() returned empty vector");
auto func = [](const std::string &partition,
const PartitionMap::BasicInf props) -> bool {
std::ofstream f("parts.txt");
f << "Partition: " << partition << ", size: " << props.size
<< ", logical: " << props.isLogical;
f.exceptions(std::ios_base::failbit | std::ios_base::badbit);
return !f.fail();
};
if (!MyMap.doForAllPartitions(func))
throw PartitionMap::Error("doForAllPartitions() progress failed");
std::cout << "Total partitions count: " << (int)MyMap << std::endl;
std::cout << "Boot: " << MyMap.getRealLinkPathOf("boot") << std::endl;
std::cout << "Boot (realpath): " << MyMap.getRealPathOf("boot")
<< std::endl;
std::cout << "Search dir: " << MyMap.getCurrentWorkDir() << std::endl;
std::cout << "Search dir test 2: " << static_cast<std::string>(MyMap)
<< std::endl;
std::cout << "Has partition cache? = " << MyMap.hasPartition("cache")
<< std::endl;
std::cout << "system partition is logical? = " << MyMap.isLogical("system")
@@ -78,6 +99,9 @@ int main() {
} catch (PartitionMap::Error &error) {
std::cerr << error.what() << std::endl;
return 1;
} catch (std::ios_base::failure &error) {
std::cerr << "fstream error: " << error.what() << std::endl;
return 1;
}
return 0;