pbt: initial 1.4.0 source code (english)
This commit is contained in:
54
binary/include/documentation.h
Normal file
54
binary/include/documentation.h
Normal file
@@ -0,0 +1,54 @@
|
||||
#ifndef _DOCUMENTATION_H_
|
||||
#define _DOCUMENTATION_H_
|
||||
|
||||
/* By YZBruh */
|
||||
|
||||
/*
|
||||
* Copyright 2024 YZBruh - Partition Backupper
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
void licenses() {
|
||||
printf("Copyright 2024 YZBruh - Partition Backupper\n");
|
||||
printf("Licensed under the Apache License, Version 2.0 (the \"License\");\n");
|
||||
printf("you may not use this file except in compliance with the License.\n");
|
||||
printf("You may obtain a copy of the License at\n\n");
|
||||
printf(" http://www.apache.org/licenses/LICENSE-2.0\n\n");
|
||||
printf("Unless required by applicable law or agreed to in writing, software\n");
|
||||
printf("distributed under the License is distributed on an \"AS IS\" BASIS,\n");
|
||||
printf("WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n");
|
||||
printf("See the License for the specific language governing permissions and limitations under the License.\n");
|
||||
}
|
||||
|
||||
void help() {
|
||||
printf("Usage (arguments): \n");
|
||||
printf(" -p, --partition name of the partition to be backed up\n");
|
||||
printf(" -l, --logical know that the partition that will be backed up is logical\n");
|
||||
printf(" -o, --out the output name of the backed-up partition (default: partition name)\n");
|
||||
printf(" -d, --outdir directory where the backup partition will be saved (default: /storage/emulated/0)\n");
|
||||
printf(" -c, --context it is meant to specify a custom /dev context. Only classic partitions (default: /dev/block/by-name)\n");
|
||||
printf(" -D, --list list partitions\n");
|
||||
printf(" -v, --version see version\n");
|
||||
printf(" -h, --help see help message\n");
|
||||
printf(" -L, --license see license\n\n");
|
||||
printf("Example 1:\n");
|
||||
printf(" -p boot_a -o boot_slot_a_image -d /sdcard/backup -c /dev/block/platform/bootdevice/by-name\n\n");
|
||||
printf("Example 2:\n");
|
||||
printf(" -c /dev/block/platform/bootdevice/by-name --list\n\n");
|
||||
printf("Report bugs to <xda-@YZBruh>\n");
|
||||
}
|
||||
|
||||
/* end of code */
|
||||
|
||||
#endif
|
||||
166
binary/include/pbt.h
Normal file
166
binary/include/pbt.h
Normal file
@@ -0,0 +1,166 @@
|
||||
#ifndef _PBT_H_
|
||||
#define _PBT_H_
|
||||
|
||||
/* By YZBruh */
|
||||
|
||||
/*
|
||||
* Copyright 2024 YZBruh - Partition Packupper
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* add pre-function important */
|
||||
char *out;
|
||||
char *outdir;
|
||||
char *my_out;
|
||||
char *cust_cxt;
|
||||
bool use_cust_cxt = false;
|
||||
bool pbt_ab = false;
|
||||
bool pbt_logical = false;
|
||||
|
||||
/* shorter error messages will be functional xd */
|
||||
void error(const char *err_msg) {
|
||||
fprintf(stderr, ANSI_RED "%s" ANSI_RESET, err_msg);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* check if the device is ab partitioned */
|
||||
void check_psf() {
|
||||
/* true = ab | false = a */
|
||||
if (use_cust_cxt) {
|
||||
char cust_cxt_ckpath[150];
|
||||
sprintf(cust_cxt_ckpath, "%s/boot_a", cust_cxt);
|
||||
if (access(cust_cxt_ckpath, F_OK) != 0) {
|
||||
pbt_ab = false;
|
||||
} else {
|
||||
pbt_ab = true;
|
||||
}
|
||||
} else {
|
||||
if (access("/dev/block/by-name/boot_a", F_OK) != 0) {
|
||||
pbt_ab = false;
|
||||
} else {
|
||||
pbt_ab = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* true = logical | false = classic */
|
||||
if (use_cust_cxt) {
|
||||
char cust_cxt_cklpath[150];
|
||||
sprintf(cust_cxt_cklpath, "%s/super", cust_cxt);
|
||||
if (access(cust_cxt_cklpath, F_OK) != 0) {
|
||||
pbt_logical = false;
|
||||
} else {
|
||||
pbt_logical = true;
|
||||
}
|
||||
} else {
|
||||
if (access("/dev/block/by-name/super", F_OK) != 0) {
|
||||
pbt_logical = false;
|
||||
} else {
|
||||
pbt_logical = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* list existing partitions */
|
||||
void listpart() {
|
||||
if (use_cust_cxt) {
|
||||
printf("List of classic partitions (%s): \n", cust_cxt);
|
||||
char cust_cxt_path[150];
|
||||
sprintf(cust_cxt_path, "ls %s", cust_cxt);
|
||||
if (system(cust_cxt_path) != 0) {
|
||||
error("An error occurred when the partition list appears!\n");
|
||||
}
|
||||
} else {
|
||||
printf("List of classic partitions (/dev/block/by-name): \n");
|
||||
if (system("ls /dev/block/by-name") != 0) {
|
||||
error("An error occurred when the classic partition list appears!\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (pbt_logical) {
|
||||
printf("List of logical partitions (/dev/block/mapper): \n");
|
||||
if (system("ls /dev/block/mapper") != 0) {
|
||||
error("An error occurred when the logical partition list appears!\n");
|
||||
}
|
||||
}
|
||||
if (pbt_ab) {
|
||||
printf("%sWarning: device using A/B partition style.%s\n", ANSI_YELLOW, ANSI_RESET);
|
||||
}
|
||||
if (pbt_logical) {
|
||||
printf("%sWarning: device using logical partition type.%s\n", ANSI_YELLOW, ANSI_RESET);
|
||||
}
|
||||
}
|
||||
|
||||
/* additional function to perform backup */
|
||||
void backup(char *target_pt, char *pst) {
|
||||
char path[200];
|
||||
if (strstr(pst, "classic") != NULL) {
|
||||
if (use_cust_cxt) {
|
||||
sprintf(path, "%s/%s", cust_cxt, target_pt);
|
||||
} else {
|
||||
sprintf(path, "/dev/block/by-name/%s", target_pt);
|
||||
}
|
||||
} else if (strstr(pst, "logical") != NULL) {
|
||||
sprintf(path, "/dev/block/mapper/%s", target_pt);
|
||||
} else {
|
||||
error("İnvalid partition type!\n");
|
||||
}
|
||||
if (access(path, F_OK) == -1) {
|
||||
error("Partition not found!\n");
|
||||
} else {
|
||||
printf("Target partition: %s\nBackupping...\n", target_pt);
|
||||
}
|
||||
char cmd[256];
|
||||
if (my_out != NULL) {
|
||||
if (out != NULL) {
|
||||
sprintf(cmd, "dd if=%s of=%s/%s.img status=none", path, my_out, out);
|
||||
} else {
|
||||
sprintf(cmd, "dd if=%s of=%s/%s.img status=none", path, my_out, target_pt);
|
||||
}
|
||||
} else {
|
||||
if (out != NULL) {
|
||||
sprintf(cmd, "dd if=%s of=/storage/emulated/0/%s.img status=none", path, out);
|
||||
} else {
|
||||
sprintf(cmd, "dd if=%s of=/storage/emulated/0/%s.img status=none", path, target_pt);
|
||||
}
|
||||
}
|
||||
if (system(cmd) != 0) {
|
||||
error("Failed!\n");
|
||||
} else {
|
||||
if (my_out != NULL) {
|
||||
if (out != NULL) {
|
||||
printf("%sSuccess. Output: %s/%s.img%s\n", ANSI_GREEN, my_out, out, ANSI_RESET);
|
||||
} else {
|
||||
printf("%sSuccess. Output: %s/%s.img%s\n", ANSI_GREEN, my_out, target_pt, ANSI_RESET);
|
||||
}
|
||||
} else {
|
||||
if (out != NULL) {
|
||||
printf("%sSuccess. Output: /storage/emulated/0/%s.img%s\n", ANSI_GREEN, out, ANSI_RESET);
|
||||
} else {
|
||||
printf("%sSuccess. Output: /storage/emulated/0/%s.img%s\n", ANSI_GREEN, target_pt, ANSI_RESET);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* root checker function */
|
||||
void verify_root() {
|
||||
// a quick, easy method to verify root :D
|
||||
if (chdir("/dev/block") != 0) {
|
||||
error("Root privileges could not be detected! Please run this binary with root.\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* end of code */
|
||||
|
||||
#endif
|
||||
173
binary/pbt.c
Normal file
173
binary/pbt.c
Normal file
@@ -0,0 +1,173 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <getopt.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define ANSI_RED "\033[31m"
|
||||
#define ANSI_YELLOW "\033[33m"
|
||||
#define ANSI_GREEN "\033[32m"
|
||||
#define ANSI_RESET "\033[0m"
|
||||
|
||||
#define PACK_VER "1.4.0"
|
||||
#define PACK_VER_CODE "140"
|
||||
#define PACK_NAME "Partition Backupper"
|
||||
#define PACK_LANG "en"
|
||||
|
||||
#include "include/pbt.h"
|
||||
#include "include/documentation.h"
|
||||
|
||||
/* By YZBruh */
|
||||
|
||||
/*
|
||||
* Copyright 2024 YZBruh - Partition Backupper
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* classic main function (C binary here xd) */
|
||||
int main(int argc, char *argv[]) {
|
||||
# ifdef __aarch64__
|
||||
/* empty */
|
||||
# elif __armv8l__
|
||||
/* empty */
|
||||
# elif __aarch32__
|
||||
/* empty */
|
||||
# elif __armv7l__
|
||||
/* empty */
|
||||
# else
|
||||
error("Incompatible architecture was detected. This binary works with only arm (32-bit or 64-bit).\n");
|
||||
# endif
|
||||
/* a structure for long arguments... */
|
||||
struct option long_options[] = {
|
||||
{"partition", required_argument, 0, 'p'},
|
||||
{"logical", no_argument, 0, 'l'},
|
||||
{"out", required_argument, 0, 'o'},
|
||||
{"outdir", required_argument, 0, 'd'},
|
||||
{"context", required_argument, 0, 'c'},
|
||||
{"list", no_argument, 0, 'D'},
|
||||
{"version", no_argument, 0, 'v'},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"license", no_argument, 0, 'L'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
char *argx_target_p;
|
||||
bool use_argx_p = false;
|
||||
bool use_logical = false;
|
||||
int opt;
|
||||
/* control for each argument */
|
||||
while ((opt = getopt_long(argc, argv, "p:lo:d:c:DvhL", long_options, NULL)) != -1) {
|
||||
/* process arguments */
|
||||
switch (opt) {
|
||||
case 'p':
|
||||
argx_target_p = strdup(optarg);
|
||||
use_argx_p = true;
|
||||
break;
|
||||
case 'l':
|
||||
verify_root();
|
||||
check_psf();
|
||||
if (pbt_logical) {
|
||||
use_logical = true;
|
||||
} else {
|
||||
error("This device does not have logical partitions!\n");
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
out = strdup(optarg);
|
||||
break;
|
||||
case 'd':
|
||||
verify_root();
|
||||
check_psf();
|
||||
outdir = strdup(optarg);
|
||||
struct stat out_info;
|
||||
if (stat(outdir, &out_info) != 0) {
|
||||
fprintf(stderr, "%s: %s: no such file or directory.\n", argv[0], outdir);
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
if (S_ISDIR(out_info.st_mode)) {
|
||||
my_out = outdir;
|
||||
} else {
|
||||
fprintf(stderr, "%s: %s: is a not directory.\n", argv[0], outdir);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
use_cust_cxt = true;
|
||||
cust_cxt = strdup(optarg);
|
||||
break;
|
||||
case 'D':
|
||||
listpart();
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
case 'v':
|
||||
printf("Version: %s (code %s)\n", PACK_VER, PACK_VER_CODE);
|
||||
# ifdef __clang__
|
||||
printf("Compiled by clang version %s\n", __clang_version__);
|
||||
# endif
|
||||
printf("See licenses with -L argument.\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
case 'h':
|
||||
help();
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
case 'L':
|
||||
licenses();
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
case '?':
|
||||
printf("Try `%s --help' for more information.\n", argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
break;
|
||||
default:
|
||||
printf("Usage: %s -p, --partition PARTITION [-l, --logical] [-o, --out] [-d, --outdir] [-D, --list] [-v, --version] [-h, --help] [-L, --license]\n", argv[0]);
|
||||
}
|
||||
}
|
||||
verify_root();
|
||||
check_psf();
|
||||
/* custom context checker */
|
||||
if (use_cust_cxt) {
|
||||
struct stat cxtinfo;
|
||||
printf("Checking custom context path...\n");
|
||||
if (stat(cust_cxt, &cxtinfo) == 0) {
|
||||
if (S_ISDIR(cxtinfo.st_mode)) {
|
||||
/* empty */
|
||||
} else {
|
||||
fprintf(stderr, "%s: %s: is a not directory.\n", argv[0], cust_cxt);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
error("The specified context was not found!\n");
|
||||
}
|
||||
if (strstr(cust_cxt, "/dev") != 0) {
|
||||
printf("%sThis custom context is strange...%s", ANSI_YELLOW, ANSI_RESET);
|
||||
}
|
||||
}
|
||||
if (use_argx_p) {
|
||||
if (use_logical) {
|
||||
backup(argx_target_p, "logical");
|
||||
} else {
|
||||
backup(argx_target_p, "classic");
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "%s: required partition name.\nTry `%s --help' for more information.\n", argv[0], argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/* end of code */
|
||||
Reference in New Issue
Block a user