Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 62b1ff98d9 | |||
| 7b29059a8e | |||
| 9724bee46e | |||
| 366bb28612 | |||
| 58330fddf4 | |||
| 62b73ac91a | |||
| 20ad64c8c5 | |||
| 6999975f6a | |||
| 54f2a48ffa | |||
| 9391847534 | |||
| bfd5a78863 | |||
| d4703df1a5 | |||
| c3a5e97d41 | |||
| 47382ebf1c | |||
| 7240cca537 | |||
| 6a8fd5854d | |||
| f3732ff158 | |||
| b7f5348b89 | |||
| 235402ed23 | |||
| e17ac42e55 | |||
| 1bc3b5ccef | |||
| c3acd4b370 | |||
| 05f173e895 | |||
| 638ed3017e | |||
| 563e8a583e | |||
| bf0df8cc83 | |||
| 0bc5f70294 | |||
| d74f385a68 | |||
| 23087966d6 | |||
| 7350791d04 | |||
| 5d06c804e3 | |||
| 442155b9f6 | |||
| a1211c91fe | |||
| f33433cfe6 |
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -60,4 +60,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: "Read [Wiki - About Release Types](https://github.com/ShawkTeam/pmt-renovated/wiki/About-Release-Types) for getting more information."
|
||||
|
||||
6
.idea/editor.xml
generated
6
.idea/editor.xml
generated
@@ -117,6 +117,7 @@
|
||||
<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/=CppModulePartitionWithSeveralPartitionUnits/@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" />
|
||||
@@ -243,7 +244,7 @@
|
||||
<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/CppClangFormat/EnableClangFormatSupport/@EntryValue" value="true" 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" />
|
||||
@@ -263,13 +264,12 @@
|
||||
<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/INDENT_STYLE/@EntryValue" value="Space" 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" />
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
# Project info
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
project(pmt VERSION 1.0.0)
|
||||
project(pmt VERSION 1.1.0)
|
||||
|
||||
# Set compiler flags
|
||||
add_compile_options(-Wall -Werror -Wno-deprecated-declarations)
|
||||
|
||||
@@ -19,15 +19,22 @@ 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 doesn’t 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).
|
||||
|
||||
## 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)
|
||||
|
||||
@@ -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 don’t want to worry about missing libraries, **choose the static version** matching your device’s 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 you’re unsure which one to pick, try the **static version** first — it works out of the box on all supported devices.
|
||||
319
USAGE.md
319
USAGE.md
@@ -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**.
|
||||
It’s 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 device’s 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 phone’s 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)
|
||||
@@ -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;
|
||||
|
||||
21
include/LICENSE.nlohmann
Normal file
21
include/LICENSE.nlohmann
Normal 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.
|
||||
@@ -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>
|
||||
@@ -58,9 +58,8 @@ public:
|
||||
class basic_variables final {
|
||||
public:
|
||||
basic_variables();
|
||||
~basic_variables();
|
||||
|
||||
PartitionMap::BuildMap *PartMap;
|
||||
std::unique_ptr<PartitionMap::BuildMap> PartMap;
|
||||
|
||||
std::string searchPath, logFile;
|
||||
bool onLogical;
|
||||
@@ -70,23 +69,12 @@ public:
|
||||
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;
|
||||
extern std::unique_ptr<VariableTable> Variables;
|
||||
|
||||
int Main(int argc, char **argv);
|
||||
|
||||
@@ -111,7 +99,7 @@ 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();
|
||||
|
||||
|
||||
25526
include/nlohmann/json.hpp
Normal file
25526
include/nlohmann/json.hpp
Normal file
File diff suppressed because it is too large
Load Diff
187
include/nlohmann/json_fwd.hpp
Normal file
187
include/nlohmann/json_fwd.hpp
Normal 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_
|
||||
35
manager.sh
35
manager.sh
@@ -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
|
||||
|
||||
@@ -22,9 +22,9 @@ set(PMT_SOURCES
|
||||
${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
|
||||
)
|
||||
|
||||
@@ -39,12 +39,20 @@ 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 (Variables->PartMap->hasPartition(entry) &&
|
||||
Variables->PartMap->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 = Variables->PartMap->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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,45 +16,58 @@
|
||||
|
||||
#include "functions/functions.hpp"
|
||||
#include <PartitionManager/PartitionManager.hpp>
|
||||
#include <unistd.h>
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <csignal>
|
||||
#include <generated/buildInfo.hpp>
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace PartitionManager {
|
||||
variableProtect protector;
|
||||
auto Variables = new VariableTable();
|
||||
|
||||
variableProtect::variableProtect() {
|
||||
__attribute__((constructor))
|
||||
void init() {
|
||||
Helper::LoggingProperties::setLogFile("/sdcard/Documents/last_pmt_logs.log");
|
||||
}
|
||||
variableProtect::~variableProtect() { delete _ptr; }
|
||||
void variableProtect::setVariablePointer(basic_variables *&_ptr) {
|
||||
this->_ptr = _ptr;
|
||||
|
||||
static void sigHandler(const int sig) {
|
||||
// Even if only SIGINT is to be captured for now, this is still a more appropriate code
|
||||
if (sig == SIGINT) println("\n%sInterrupted.%s", YELLOW, STYLE_RESET);
|
||||
exit(sig);
|
||||
}
|
||||
|
||||
basic_variables::~basic_variables() { delete PartMap; }
|
||||
auto Variables = std::make_unique<VariableTable>();
|
||||
|
||||
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 &) {
|
||||
}
|
||||
}
|
||||
|
||||
int Main(int argc, char **argv) {
|
||||
try {
|
||||
// try-catch start
|
||||
if (argc < 2) {
|
||||
println(
|
||||
"Usage: %s [OPTIONS] [SUBCOMMAND]\nUse --help for more information.",
|
||||
argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
signal(SIGINT, sigHandler);
|
||||
|
||||
CLI::App AppMain{"Partition Manager Tool"};
|
||||
protector.setVariablePointer(Variables);
|
||||
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\nThis project "
|
||||
"licensed under "
|
||||
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
|
||||
@@ -62,7 +75,7 @@ int Main(int argc, char **argv) {
|
||||
"Set partition search path")
|
||||
->check([&](const std::string &val) {
|
||||
if (val.find("/block") == std::string::npos)
|
||||
throw CLI::ValidationError(
|
||||
return std::string(
|
||||
"Partition search path is unexpected! Couldn't find "
|
||||
"'block' in input path!");
|
||||
return std::string();
|
||||
@@ -80,13 +93,6 @@ int Main(int argc, char **argv) {
|
||||
AppMain.add_flag("-v,--version", Variables->viewVersion,
|
||||
"Print version and exit");
|
||||
|
||||
if (argc < 2) {
|
||||
println(
|
||||
"Usage: %s [OPTIONS] [SUBCOMMAND]\nUse --help for more information.",
|
||||
argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
FuncManager.registerFunction(std::make_unique<backupFunction>(), AppMain);
|
||||
FuncManager.registerFunction(std::make_unique<flashFunction>(), AppMain);
|
||||
FuncManager.registerFunction(std::make_unique<eraseFunction>(), AppMain);
|
||||
@@ -94,10 +100,10 @@ int Main(int argc, char **argv) {
|
||||
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);
|
||||
FuncManager.registerFunction(std::make_unique<memoryTestFunction>(),
|
||||
AppMain);
|
||||
|
||||
CLI11_PARSE(AppMain, argc, argv);
|
||||
|
||||
@@ -115,7 +121,9 @@ int Main(int argc, char **argv) {
|
||||
"(--search-path)");
|
||||
|
||||
if (!Helper::hasSuperUser()) {
|
||||
if (!(FuncManager.isUsed("rebootFunction") && Helper::hasAdbPermissions()))
|
||||
if (!((FuncManager.isUsed("rebootFunction") &&
|
||||
Helper::hasAdbPermissions()) ||
|
||||
FuncManager.isUsed("memoryTestFunction")))
|
||||
throw Error(
|
||||
"Partition Manager Tool is requires super-user privileges!\n");
|
||||
}
|
||||
|
||||
@@ -28,7 +28,8 @@
|
||||
|
||||
namespace PartitionManager {
|
||||
pair backupFunction::runAsync(const std::string &partitionName,
|
||||
const std::string &outputName, int bufferSize) {
|
||||
const std::string &outputName,
|
||||
const uint64_t bufferSize) {
|
||||
if (!Variables->PartMap->hasPartition(partitionName))
|
||||
return {format("Couldn't find partition: %s", partitionName.data()), false};
|
||||
|
||||
@@ -53,7 +54,6 @@ pair backupFunction::runAsync(const std::string &partitionName,
|
||||
outputName.data()),
|
||||
false};
|
||||
|
||||
setupBufferSize(bufferSize, partitionName);
|
||||
LOGN(BFUN, INFO) << "Using buffer size (for back upping " << partitionName
|
||||
<< "): " << bufferSize << std::endl;
|
||||
|
||||
@@ -76,7 +76,7 @@ pair backupFunction::runAsync(const std::string &partitionName,
|
||||
|
||||
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);
|
||||
|
||||
@@ -94,7 +94,7 @@ 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"
|
||||
@@ -115,9 +115,10 @@ 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;
|
||||
}
|
||||
@@ -131,13 +132,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;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,8 @@ Copyright 2025 Yağız Zengin
|
||||
#define EFUN "eraseFunction"
|
||||
|
||||
namespace PartitionManager {
|
||||
pair eraseFunction::runAsync(const std::string &partitionName, int bufferSize) {
|
||||
pair eraseFunction::runAsync(const std::string &partitionName,
|
||||
const uint64_t bufferSize) {
|
||||
if (!Variables->PartMap->hasPartition(partitionName))
|
||||
return {format("Couldn't find partition: %s", partitionName.data()), false};
|
||||
|
||||
@@ -42,7 +43,6 @@ pair eraseFunction::runAsync(const std::string &partitionName, int bufferSize) {
|
||||
false};
|
||||
}
|
||||
|
||||
setupBufferSize(bufferSize, partitionName);
|
||||
LOGN(EFUN, INFO) << "Using buffer size: " << bufferSize;
|
||||
|
||||
// Automatically close file descriptors and delete allocated memories (arrays)
|
||||
@@ -63,7 +63,7 @@ pair eraseFunction::runAsync(const std::string &partitionName, int bufferSize) {
|
||||
|
||||
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);
|
||||
|
||||
@@ -94,15 +94,19 @@ bool eraseFunction::init(CLI::App &_app) {
|
||||
->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() {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,8 @@ Copyright 2025 Yağız Zengin
|
||||
|
||||
namespace PartitionManager {
|
||||
pair flashFunction::runAsync(const std::string &partitionName,
|
||||
const std::string &imageName, int bufferSize) {
|
||||
const std::string &imageName,
|
||||
const uint64_t bufferSize) {
|
||||
if (!Helper::fileIsExists(imageName))
|
||||
return {format("Couldn't find image file: %s", imageName.data()), false};
|
||||
if (!Variables->PartMap->hasPartition(partitionName))
|
||||
@@ -52,8 +53,7 @@ pair flashFunction::runAsync(const std::string &partitionName,
|
||||
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;
|
||||
@@ -74,7 +74,7 @@ pair flashFunction::runAsync(const std::string &partitionName,
|
||||
|
||||
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);
|
||||
|
||||
@@ -100,8 +100,10 @@ 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)");
|
||||
|
||||
@@ -115,13 +117,17 @@ bool flashFunction::run() {
|
||||
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));
|
||||
LOGN(FFUN, INFO) << "Created thread for flashing image to " << partitions[i]
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ Copyright 2025 Yağız Zengin
|
||||
#include <cerrno>
|
||||
#include <cstdlib>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#define IFUN "infoFunction"
|
||||
|
||||
@@ -36,13 +36,20 @@ bool infoFunction::init(CLI::App &_app) {
|
||||
->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_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;
|
||||
}
|
||||
|
||||
@@ -59,6 +66,7 @@ bool infoFunction::run() {
|
||||
partitions.push_back(name);
|
||||
}
|
||||
|
||||
std::vector<PartitionMap::Partition_t> jParts;
|
||||
for (const auto &partition : partitions) {
|
||||
if (!Variables->PartMap->hasPartition(partition))
|
||||
throw Error("Couldn't find partition: %s", partition.data());
|
||||
@@ -75,14 +83,9 @@ 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,
|
||||
{Variables->PartMap->sizeOf(partition),
|
||||
Variables->PartMap->isLogical(partition)}});
|
||||
else
|
||||
#ifdef __LP64__
|
||||
println("partition=%s size=%lu isLogical=%s",
|
||||
@@ -93,6 +96,18 @@ bool infoFunction::run() {
|
||||
Variables->PartMap->isLogical(partition) ? "true" : "false");
|
||||
}
|
||||
|
||||
if (jsonFormat) {
|
||||
nlohmann::json j;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
130
src/functions/MemoryTestFunction.cpp
Normal file
130
src/functions/MemoryTestFunction.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
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"
|
||||
|
||||
namespace PartitionManager {
|
||||
|
||||
bool memoryTestFunction::init(CLI::App &_app) {
|
||||
LOGN(MTFUN, INFO) << "Initializing variables of memory test function."
|
||||
<< std::endl;
|
||||
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;
|
||||
}
|
||||
|
||||
bool memoryTestFunction::run() {
|
||||
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);
|
||||
std::mt19937 rng(std::random_device{}());
|
||||
std::uniform_int_distribution dist(0, 255);
|
||||
|
||||
for (size_t i = 0; i < bufferSize; i++)
|
||||
buffer[i] = static_cast<char>(dist(rng));
|
||||
|
||||
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\n", strerror(errno));
|
||||
|
||||
LOGN(MTFUN, INFO) << "Sequential write test started!" << std::endl;
|
||||
const auto startWrite = std::chrono::high_resolution_clock::now();
|
||||
ssize_t bytesWritten = 0;
|
||||
while (bytesWritten < testFileSize) {
|
||||
const ssize_t ret = write(wfd, buffer, bufferSize);
|
||||
if (ret < 0) throw Error("Can't write to test file: %s\n", strerror(errno));
|
||||
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\n", 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;
|
||||
}
|
||||
|
||||
bool memoryTestFunction::isUsed() const { return cmd->parsed(); }
|
||||
|
||||
const char *memoryTestFunction::name() const { return MTFUN; }
|
||||
|
||||
} // namespace PartitionManager
|
||||
@@ -36,16 +36,21 @@ bool partitionSizeFunction::init(CLI::App &_app) {
|
||||
->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(false);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -27,6 +27,7 @@ bool realPathFunction::init(CLI::App &_app) {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -46,7 +47,10 @@ bool realPathFunction::run() {
|
||||
partition.data());
|
||||
}
|
||||
|
||||
println("%s", Variables->PartMap->getRealPathOf(partition).data());
|
||||
if (realLinkPath)
|
||||
println("%s", Variables->PartMap->getRealLinkPathOf(partition).data());
|
||||
else
|
||||
println("%s", Variables->PartMap->getRealPathOf(partition).data());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -27,11 +27,15 @@ bool typeFunction::init(CLI::App &_app) {
|
||||
->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;
|
||||
}
|
||||
|
||||
@@ -52,7 +56,7 @@ bool typeFunction::run() {
|
||||
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))) {
|
||||
|
||||
@@ -29,7 +29,7 @@ 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;
|
||||
@@ -37,7 +37,7 @@ public:
|
||||
bool init(CLI::App &_app) override;
|
||||
bool run() override;
|
||||
static pair runAsync(const std::string &partitionName,
|
||||
const std::string &outputName, int bufferSize);
|
||||
const std::string &outputName, uint64_t bufferSize);
|
||||
|
||||
[[nodiscard]] bool isUsed() const override;
|
||||
[[nodiscard]] const char *name() const override;
|
||||
@@ -48,7 +48,7 @@ class flashFunction final : public FunctionBase {
|
||||
private:
|
||||
std::vector<std::string> partitions, imageNames;
|
||||
std::string rawPartitions, rawImageNames, imageDirectory;
|
||||
int bufferSize = 4096;
|
||||
uint64_t bufferSize = 0;
|
||||
|
||||
public:
|
||||
CLI::App *cmd = nullptr;
|
||||
@@ -56,7 +56,7 @@ public:
|
||||
bool init(CLI::App &_app) override;
|
||||
bool run() override;
|
||||
static pair runAsync(const std::string &partitionName,
|
||||
const std::string &imageName, int bufferSize);
|
||||
const std::string &imageName, uint64_t bufferSize);
|
||||
|
||||
[[nodiscard]] bool isUsed() const override;
|
||||
[[nodiscard]] const char *name() const override;
|
||||
@@ -66,14 +66,14 @@ public:
|
||||
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);
|
||||
static pair runAsync(const std::string &partitionName, uint64_t bufferSize);
|
||||
|
||||
[[nodiscard]] bool isUsed() const override;
|
||||
[[nodiscard]] const char *name() const override;
|
||||
@@ -100,8 +100,8 @@ public:
|
||||
class infoFunction final : public FunctionBase {
|
||||
private:
|
||||
std::vector<std::string> partitions;
|
||||
std::string jNamePartition = "name", jNameSize = "size",
|
||||
jNameLogical = "isLogical";
|
||||
std::string jNamePartition, jNameSize, jNameLogical;
|
||||
int jIndentSize = 2;
|
||||
bool jsonFormat = false;
|
||||
|
||||
public:
|
||||
@@ -117,20 +117,7 @@ public:
|
||||
class realPathFunction 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;
|
||||
};
|
||||
|
||||
class realLinkPathFunction final : public FunctionBase {
|
||||
private:
|
||||
std::vector<std::string> partitions;
|
||||
bool realLinkPath = false;
|
||||
|
||||
public:
|
||||
CLI::App *cmd = nullptr;
|
||||
@@ -146,7 +133,7 @@ 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;
|
||||
@@ -171,6 +158,23 @@ public:
|
||||
[[nodiscard]] bool isUsed() const override;
|
||||
[[nodiscard]] const char *name() const override;
|
||||
};
|
||||
|
||||
class memoryTestFunction final : public FunctionBase {
|
||||
private:
|
||||
uint64_t bufferSize = MB(4), /* bufferSizeRandom = KB(4),*/ testFileSize = 0;
|
||||
std::string testPath;
|
||||
bool doNotReadTest = false;
|
||||
|
||||
public:
|
||||
CLI::App *cmd = nullptr;
|
||||
|
||||
bool init(CLI::App &_app) override;
|
||||
bool run() override;
|
||||
|
||||
[[nodiscard]] bool isUsed() const override;
|
||||
[[nodiscard]] const char *name() const override;
|
||||
};
|
||||
|
||||
} // namespace PartitionManager
|
||||
|
||||
#endif // #ifndef FUNCTIONS_HPP
|
||||
|
||||
@@ -81,12 +81,14 @@ private:
|
||||
std::vector<uint8_t *> _ptrs_u;
|
||||
std::vector<FILE *> _fps;
|
||||
std::vector<int> _fds;
|
||||
std::vector<std::string> _files;
|
||||
|
||||
public:
|
||||
~garbageCollector();
|
||||
|
||||
void delAfterProgress(char *&_ptr);
|
||||
void delAfterProgress(uint8_t *&_ptr);
|
||||
void delFileAfterProgress(const std::string& path);
|
||||
void closeAfterProgress(FILE *&_fp);
|
||||
void closeAfterProgress(int _fd);
|
||||
};
|
||||
@@ -151,6 +153,7 @@ std::string runCommandWithOutput(std::string_view cmd);
|
||||
std::string pathJoin(std::string base, std::string relative);
|
||||
std::string pathBasename(std::string_view entry);
|
||||
std::string pathDirname(std::string_view entry);
|
||||
uint64_t getRandomOffset(uint64_t size, uint64_t bufferSize);
|
||||
|
||||
// Android
|
||||
std::string getProperty(std::string_view prop);
|
||||
|
||||
@@ -95,6 +95,8 @@ garbageCollector::~garbageCollector() {
|
||||
close(fd);
|
||||
for (const auto &fp : _fps)
|
||||
fclose(fp);
|
||||
for (const auto &file : _files)
|
||||
eraseEntry(file);
|
||||
}
|
||||
|
||||
void garbageCollector::delAfterProgress(char *&_ptr) {
|
||||
@@ -103,6 +105,9 @@ void garbageCollector::delAfterProgress(char *&_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);
|
||||
}
|
||||
|
||||
@@ -216,5 +216,11 @@ bool reboot(const std::string_view arg) {
|
||||
return android_reboot(cmd, 0, arg.empty() ? nullptr : arg.data()) != -1;
|
||||
}
|
||||
|
||||
uint64_t getRandomOffset(const uint64_t size, const uint64_t bufferSize) {
|
||||
if (size <= bufferSize) return 0;
|
||||
const uint64_t maxOffset = size - bufferSize;
|
||||
return rand() % maxOffset;
|
||||
}
|
||||
|
||||
std::string getLibVersion() { MKVERSION("libhelper"); }
|
||||
} // namespace Helper
|
||||
|
||||
@@ -42,7 +42,7 @@ struct _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();
|
||||
|
||||
@@ -118,6 +118,7 @@ public:
|
||||
[[nodiscard]] constant_iterator cend() const;
|
||||
};
|
||||
|
||||
using Partition_t = _entry;
|
||||
using Map_t = basic_partition_map;
|
||||
|
||||
class basic_partition_map_builder final {
|
||||
@@ -282,6 +283,12 @@ public:
|
||||
* Build map with input path. Implementation of readDirectory().
|
||||
*/
|
||||
bool operator()(std::string_view path);
|
||||
|
||||
/**
|
||||
* Get Map_t object reference
|
||||
*/
|
||||
Map_t &operator*();
|
||||
const Map_t &operator*() const;
|
||||
};
|
||||
|
||||
using Error = Helper::Error;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -47,7 +47,7 @@ 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) {
|
||||
Map_t map;
|
||||
std::vector<std::filesystem::directory_entry> entries{
|
||||
std::filesystem::directory_iterator(path),
|
||||
@@ -251,5 +251,11 @@ 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;
|
||||
}
|
||||
|
||||
std::string getLibVersion() { MKVERSION("libpartition_map"); }
|
||||
} // namespace PartitionMap
|
||||
|
||||
Reference in New Issue
Block a user