diff options
-rw-r--r-- | Android.mk | 6 | ||||
-rw-r--r-- | adbbu/Android.mk | 45 | ||||
-rw-r--r-- | adbbu/libtwadbbu.cpp | 196 | ||||
-rw-r--r-- | adbbu/libtwadbbu.hpp | 44 | ||||
-rw-r--r-- | adbbu/twadbstream.h | 101 | ||||
-rw-r--r-- | adbbu/twrpback.cpp | 823 | ||||
-rw-r--r-- | adbbu/twrpback.hpp | 49 | ||||
-rw-r--r-- | gui/Android.mk | 1 | ||||
-rw-r--r-- | gui/action.cpp | 19 | ||||
-rw-r--r-- | gui/devices/common/res/languages/en.xml | 4 | ||||
-rw-r--r-- | gui/gui.cpp | 10 | ||||
-rw-r--r-- | gui/theme/common/landscape.xml | 3 | ||||
-rw-r--r-- | gui/theme/common/languages/en.xml | 4 | ||||
-rw-r--r-- | gui/theme/common/portrait.xml | 12 | ||||
-rw-r--r-- | gui/theme/common/watch.xml | 18 | ||||
-rw-r--r-- | openrecoveryscript.cpp | 289 | ||||
-rw-r--r-- | openrecoveryscript.hpp | 3 | ||||
-rw-r--r-- | orscmd/Android.mk | 2 | ||||
-rw-r--r-- | orscmd/orscmd.cpp | 1 | ||||
-rw-r--r-- | partition.cpp | 269 | ||||
-rw-r--r-- | partitionmanager.cpp | 282 | ||||
-rw-r--r-- | partitions.hpp | 82 | ||||
-rw-r--r-- | prebuilt/Android.mk | 4 | ||||
-rw-r--r-- | twrp-functions.cpp | 13 | ||||
-rw-r--r-- | twrp-functions.hpp | 9 | ||||
-rw-r--r-- | twrpDigest.cpp | 60 | ||||
-rw-r--r-- | twrpDigest.hpp | 6 | ||||
-rw-r--r-- | twrpTar.cpp | 296 | ||||
-rw-r--r-- | twrpTar.hpp | 16 |
29 files changed, 2276 insertions, 391 deletions
diff --git a/Android.mk b/Android.mk index 6ee788927..67e504f12 100644 --- a/Android.mk +++ b/Android.mk @@ -100,7 +100,8 @@ LOCAL_C_INCLUDES += \ system/vold \ system/extras/ext4_utils \ system/core/adb \ - system/core/libsparse + system/core/libsparse \ + external/zlib LOCAL_C_INCLUDES += bionic external/openssl/include $(LOCAL_PATH)/libmincrypt/includes ifeq ($(shell test $(PLATFORM_SDK_VERSION) -lt 23; echo $$?),0) @@ -111,7 +112,7 @@ LOCAL_STATIC_LIBRARIES := LOCAL_SHARED_LIBRARIES := LOCAL_STATIC_LIBRARIES += libguitwrp -LOCAL_SHARED_LIBRARIES += libz libc libcutils libstdc++ libtar libblkid libminuitwrp libminadbd libmtdutils libminzip libaosprecovery +LOCAL_SHARED_LIBRARIES += libz libc libcutils libstdc++ libtar libblkid libminuitwrp libminadbd libmtdutils libminzip libaosprecovery libtwadbbu LOCAL_SHARED_LIBRARIES += libcrecovery ifeq ($(shell test $(PLATFORM_SDK_VERSION) -lt 23; echo $$?),0) @@ -588,6 +589,7 @@ include $(commands_recovery_local_path)/injecttwrp/Android.mk \ $(commands_recovery_local_path)/etc/Android.mk \ $(commands_recovery_local_path)/toybox/Android.mk \ $(commands_recovery_local_path)/simg2img/Android.mk \ + $(commands_recovery_local_path)/adbbu/Android.mk \ $(commands_recovery_local_path)/libpixelflinger/Android.mk ifeq ($(TW_INCLUDE_CRYPTO), true) diff --git a/adbbu/Android.mk b/adbbu/Android.mk new file mode 100644 index 000000000..65568ef3f --- /dev/null +++ b/adbbu/Android.mk @@ -0,0 +1,45 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + twrpback.cpp \ + ../twrpDigest.cpp \ + ../digest/md5.c +LOCAL_SHARED_LIBRARIES += libstdc++ libz +ifeq ($(shell test $(PLATFORM_SDK_VERSION) -lt 23; echo $$?),0) + LOCAL_C_INCLUDES += external/stlport/stlport + LOCAL_SHARED_LIBRARIES += libstlport +else + LOCAL_SHARED_LIBRARIES += libc++ +endif + +LOCAL_C_INCLUDES += bionic external/zlib +LOCAL_CFLAGS:= -c -W +LOCAL_MODULE:= twrpbu +LOCAL_MODULE_STEM := bu +LOCAL_MODULE_TAGS:= eng +LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES +LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin +include $(BUILD_EXECUTABLE) + +include $(CLEAR_VARS) +LOCAL_MODULE := libtwadbbu +LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS = -D_FILE_OFFSET_BITS=64 -DMTP_DEVICE -DMTP_HOST -fno-strict-aliasing +LOCAL_C_INCLUDES += $(LOCAL_PATH) bionic frameworks/base/include system/core/include bionic/libc/private/ +ifeq ($(shell test $(PLATFORM_SDK_VERSION) -lt 23; echo $$?),0) + LOCAL_C_INCLUDES += external/stlport/stlport +endif + +LOCAL_SRC_FILES = \ + libtwadbbu.cpp + +LOCAL_SHARED_LIBRARIES += libz libc libstdc++ + +ifeq ($(shell test $(PLATFORM_SDK_VERSION) -lt 23; echo $$?),0) + LOCAL_SHARED_LIBRARIES += libstlport +else + LOCAL_SHARED_LIBRARIES += libc++ +endif + +include $(BUILD_SHARED_LIBRARY) diff --git a/adbbu/libtwadbbu.cpp b/adbbu/libtwadbbu.cpp new file mode 100644 index 000000000..cdc2170ba --- /dev/null +++ b/adbbu/libtwadbbu.cpp @@ -0,0 +1,196 @@ +/* + Copyright 2013 to 2016 TeamWin + TWRP is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + TWRP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with TWRP. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <errno.h> +#include <zlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/select.h> +#include <sys/time.h> +#include <string> +#include <fstream> +#include <sstream> + +#include "twadbstream.h" +#include "libtwadbbu.hpp" + +bool twadbbu::Write_ADB_Stream_Header(uint64_t partition_count) { + struct AdbBackupStreamHeader twhdr; + int adb_control_bu_fd; + + memset(&twhdr, 0, sizeof(twhdr)); + adb_control_bu_fd = open(TW_ADB_BU_CONTROL, O_WRONLY | O_NONBLOCK); + if (adb_control_bu_fd < 0) { + printf("Cannot write to TW_ADB_BU_CONTROL.\n"); + return false; + } + + strncpy(twhdr.start_of_header, TWRP, sizeof(twhdr.start_of_header)); + strncpy(twhdr.type, TWSTREAMHDR, sizeof(twhdr.type)); + twhdr.partition_count = partition_count; + twhdr.version = ADB_BACKUP_VERSION; + memset(twhdr.space, 0, sizeof(twhdr.space)); + twhdr.crc = crc32(0L, Z_NULL, 0); + twhdr.crc = crc32(twhdr.crc, (const unsigned char*) &twhdr, sizeof(twhdr)); + if (write(adb_control_bu_fd, &twhdr, sizeof(twhdr)) < 0) { + printf("Cannot write to adb control channel\n"); + close(adb_control_bu_fd); + return false; + } + return true; +} + +bool twadbbu::Write_ADB_Stream_Trailer() { + int adb_control_bu_fd; + struct AdbBackupControlType endadb; + + memset(&endadb, 0, sizeof(endadb)); + + adb_control_bu_fd = open(TW_ADB_BU_CONTROL, O_WRONLY); + if (adb_control_bu_fd < 0) { + printf("Error opening adb_control_bu_fd\n"); + return false; + } + strncpy(endadb.start_of_header, TWRP, sizeof(endadb.start_of_header)); + strncpy(endadb.type, TWENDADB, sizeof(endadb.type)); + endadb.crc = crc32(0L, Z_NULL, 0); + endadb.crc = crc32(endadb.crc, (const unsigned char*) &endadb, sizeof(endadb)); + if (write(adb_control_bu_fd, &endadb, sizeof(endadb)) < 0) { + printf("Cannot write to ADB control.\n"); + close(adb_control_bu_fd); + return false; + } + close(adb_control_bu_fd); + return true; +} + +bool twadbbu::Write_TWFN(std::string Backup_FileName, uint64_t file_size, bool use_compression) { + int adb_control_bu_fd; + adb_control_bu_fd = open(TW_ADB_BU_CONTROL, O_WRONLY | O_NONBLOCK); + struct twfilehdr twfilehdr; + strncpy(twfilehdr.start_of_header, TWRP, sizeof(twfilehdr.start_of_header)); + strncpy(twfilehdr.type, TWFN, sizeof(twfilehdr.type)); + strncpy(twfilehdr.name, Backup_FileName.c_str(), sizeof(twfilehdr.name)); + twfilehdr.size = (file_size == 0 ? 1024 : file_size); + twfilehdr.compressed = use_compression; + twfilehdr.crc = crc32(0L, Z_NULL, 0); + twfilehdr.crc = crc32(twfilehdr.crc, (const unsigned char*) &twfilehdr, sizeof(twfilehdr)); + + printf("Sending TWFN to adb\n"); + if (write(adb_control_bu_fd, &twfilehdr, sizeof(twfilehdr)) < 1) { + printf("Cannot that write to adb_control_bu_fd\n"); + close(adb_control_bu_fd); + return false; + } + close(adb_control_bu_fd); + return true; +} + +bool twadbbu::Write_TWIMG(std::string Backup_FileName, uint64_t file_size) { + int adb_control_bu_fd; + struct twfilehdr twimghdr; + + adb_control_bu_fd = open(TW_ADB_BU_CONTROL, O_WRONLY | O_NONBLOCK); + strncpy(twimghdr.start_of_header, TWRP, sizeof(twimghdr.start_of_header)); + strncpy(twimghdr.type, TWIMG, sizeof(twimghdr.type)); + twimghdr.size = file_size; + strncpy(twimghdr.name, Backup_FileName.c_str(), sizeof(twimghdr.name)); + twimghdr.crc = crc32(0L, Z_NULL, 0); + twimghdr.crc = crc32(twimghdr.crc, (const unsigned char*) &twimghdr, sizeof(twimghdr)); + printf("Sending TWIMG to adb\n"); + if (write(adb_control_bu_fd, &twimghdr, sizeof(twimghdr)) < 1) { + printf("Cannot write to adb control channel\n"); + return false; + } + + return true; +} + +bool twadbbu::Write_TWEOF() { + struct AdbBackupControlType tweof; + int adb_control_bu_fd; + int errctr = 0; + + printf("opening TW_ADB_BU_CONTROL\n"); + adb_control_bu_fd = open(TW_ADB_BU_CONTROL, O_WRONLY | O_NONBLOCK); + while (adb_control_bu_fd < 0) { + printf("failed to open TW_ADB_BU_CONTROL. Retrying: %s\n", strerror(errno)); + adb_control_bu_fd = open(TW_ADB_BU_CONTROL, O_WRONLY | O_NONBLOCK); + usleep(10000); + errctr++; + if (errctr > ADB_BU_MAX_ERROR) { + printf("Cannot write to adb_control_bu_fd: %s.\n", strerror(errno)); + close(adb_control_bu_fd); + return false; + } + } + memset(&tweof, 0, sizeof(tweof)); + strncpy(tweof.start_of_header, TWRP, sizeof(tweof.start_of_header)); + strncpy(tweof.type, TWEOF, sizeof(tweof.type)); + tweof.crc = crc32(0L, Z_NULL, 0); + tweof.crc = crc32(tweof.crc, (const unsigned char*) &tweof, sizeof(tweof)); + printf("Sending TWEOF to adb backup\n"); + if (write(adb_control_bu_fd, &tweof, sizeof(tweof)) < 0) { + printf("Cannot write to adb_control_bu_fd: %s.\n", strerror(errno)); + close(adb_control_bu_fd); + return false; + } + close(adb_control_bu_fd); + return true; +} + +bool twadbbu::Write_TWERROR() { + struct AdbBackupControlType twerror; + int adb_control_bu_fd = open(TW_ADB_BU_CONTROL, O_WRONLY | O_NONBLOCK); + + strncpy(twerror.start_of_header, TWRP, sizeof(twerror.start_of_header)); + strncpy(twerror.type, TWERROR, sizeof(twerror.type)); + memset(twerror.space, 0, sizeof(twerror.space)); + twerror.crc = crc32(0L, Z_NULL, 0); + twerror.crc = crc32(twerror.crc, (const unsigned char*) &twerror, sizeof(twerror)); + if (write(adb_control_bu_fd, &twerror, sizeof(twerror)) < 0) { + printf("Cannot write to adb control channel"); + return false; + } + close(adb_control_bu_fd); + return true; +} + +bool twadbbu::Write_TWENDADB() { + struct AdbBackupControlType endadb; + int adb_control_bu_fd = open(TW_ADB_BU_CONTROL, O_WRONLY | O_NONBLOCK); + + memset(&endadb, 0, sizeof(endadb)); + strncpy(endadb.start_of_header, TWRP, sizeof(endadb.start_of_header)); + strncpy(endadb.type, TWENDADB, sizeof(endadb.type)); + endadb.crc = crc32(0L, Z_NULL, 0); + endadb.crc = crc32(endadb.crc, (const unsigned char*) &endadb, sizeof(endadb)); + + printf("Sending TWENDADB to ADB Backup\n"); + if (write(adb_control_bu_fd, &endadb, sizeof(endadb)) < 1) { + printf("Cannot write to ADB_CONTROL_BU_FD: %s\n", strerror(errno)); + return false; + } + + close(adb_control_bu_fd); + return true; +} diff --git a/adbbu/libtwadbbu.hpp b/adbbu/libtwadbbu.hpp new file mode 100644 index 000000000..bcd8b6aa3 --- /dev/null +++ b/adbbu/libtwadbbu.hpp @@ -0,0 +1,44 @@ +/* + Copyright 2013 to 2016 TeamWin + TWRP is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + TWRP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with TWRP. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/select.h> +#include <sys/time.h> +#include <string> +#include <fstream> +#include <sstream> + +#include "twadbstream.h" +#include "twrpback.hpp" + +class twadbbu { +public: + static bool Write_ADB_Stream_Header(uint64_t partition_count); //Write ADB Stream Header to stream + static bool Write_ADB_Stream_Trailer(); //Write ADB Stream Trailer to stream + static bool Write_TWFN(std::string Backup_FileName, uint64_t file_size, bool use_compression); //Write a tar image to stream + static bool Write_TWIMG(std::string Backup_FileName, uint64_t file_size); //Write a partition image to stream + static bool Write_TWEOF(); //Write ADB End-Of-File marker to stream + static bool Write_TWERROR(); //Write error message occurred to stream + static bool Write_TWENDADB(); //Write ADB End-Of-Stream command to stream +}; diff --git a/adbbu/twadbstream.h b/adbbu/twadbstream.h new file mode 100644 index 000000000..4e76be165 --- /dev/null +++ b/adbbu/twadbstream.h @@ -0,0 +1,101 @@ +/* + TWRP is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + TWRP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with TWRP. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef __TWADBSTREAM_H +#define __TWADBSTREAM_H + +#define TW_ADB_BACKUP "/tmp/twadbbackup" //FIFO for adb backup +#define TW_ADB_RESTORE "/tmp/twadbrestore" //FIFO for adb restore +#define TW_ADB_BU_CONTROL "/tmp/twadbbucontrol" //FIFO for sending control from TWRP to ADB Backup +#define TW_ADB_TWRP_CONTROL "/tmp/twadbtwrpcontrol" //FIFO for sending control from ADB Backup to TWRP +#define TWRP "TWRP" //Magic Value +#define ADB_BU_MAX_ERROR 10 //Max amount of errors for while loops + +//ADB Backup Control Commands +#define TWSTREAMHDR "twstreamheader" //TWRP Parititon Count Control +#define TWFN "twfilename" //TWRP Filename Control +#define TWIMG "twimage" //TWRP Image name Control +#define TWEOF "tweof" //End of File for Image/File +#define MD5TRAILER "md5trailer" //Image/File MD5 Trailer +#define TWDATA "twdatablock" // twrp adb backup data block header +#define TWMD5 "twverifymd5" //This command is compared to the md5trailer by ORS to verify transfer +#define TWENDADB "twendadb" //End Protocol +#define TWERROR "twerror" //Send error +#define ADB_BACKUP_VERSION 1 //Backup Version +#define DATA_MAX_CHUNK_SIZE 1048576 //Maximum size between each data header +#define MAX_ADB_READ 512 //align with default tar size for amount to read fom adb stream + +/* +structs for adb backup need to align to 512 bytes for reading 512 +bytes at a time +Each struct contains a crc field so that when we are checking for commands +and the crc doesn't match we still assume it's data matching the command +struct but not really a command +*/ + +/* stream format: + | TW ADB Backup Header | + | TW File Stream Header | + | File Data | + | File/Image MD5 Trailer | + | TW File Stream Header | + | File Data | + | File/Image MD5 Trailer | + | etc... | +*/ + +//determine whether struct is 512 bytes, if not fail compilation +#define ADBSTRUCT_STATIC_ASSERT(structure) typedef char adb_assertion[( !!(structure) )*2-1 ] + +//generic cmd structure to align fields for sending commands to and from adb backup +struct AdbBackupControlType { + char start_of_header[8]; //stores the magic value #define TWRP + char type[16]; //stores the type of command, TWENDADB, TWCNT, TWEOF, TWMD5, TWDATA and TWERROR + uint32_t crc; //stores the zlib 32 bit crc of the AdbBackupControlType struct to allow for making sure we are processing metadata + char space[484]; //stores space to align the struct to 512 bytes +}; + +//general info for file metadata stored in adb backup header +struct twfilehdr { + char start_of_header[8]; //stores the magic value #define TWRP + char type[16]; //stores the type of file header, TWFN or TWIMG + uint64_t size; //stores the size of the file contained after this header in the backup file + uint64_t compressed; //stores whether the file is compressed or not. 1 == compressed and 0 == uncompressed + uint32_t crc; //stores the zlib 32 bit crc of the twfilehdr struct to allow for making sure we are processing metadata + char name[468]; //stores the filename of the file +}; + +//md5 for files stored as a trailer to files in the adb backup file to check +//that they are restored correctly +struct AdbBackupFileTrailer { + char start_of_trailer[8]; //stores the magic value #define TWRP + char type[16]; //stores the AdbBackupFileTrailer type MD5TRAILER + uint32_t crc; //stores the zlib 32 bit crc of the AdbBackupFileTrailer struct to allow for making sure we are processing metadata + uint32_t ident; //stores crc to determine if header is encapsulated in stream as data + char md5[40]; //stores the md5 computation of the file + char space[440]; //stores space to align the struct to 512 bytes +}; + +//info for version and number of partitions backed up +struct AdbBackupStreamHeader { + char start_of_header[8]; //stores the magic value #define TWRP + char type[16]; //stores the AdbBackupStreamHeader value TWCNT + uint64_t partition_count; //stores the number of partitions to restore in the stream + uint64_t version; //stores the version of adb backup. increment ADB_BACKUP_VERSION each time the metadata is updated + uint32_t crc; //stores the zlib 32 bit crc of the AdbBackupStreamHeader struct to allow for making sure we are processing metadata + char space[468]; //stores space to align the struct to 512 bytes +}; + +#endif //__TWADBSTREAM_H diff --git a/adbbu/twrpback.cpp b/adbbu/twrpback.cpp new file mode 100644 index 000000000..e22574b27 --- /dev/null +++ b/adbbu/twrpback.cpp @@ -0,0 +1,823 @@ +/* + Copyright 2013 to 2016 TeamWin + TWRP is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + TWRP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with TWRP. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/select.h> +#include <sys/time.h> +#include <zlib.h> +#include <ctype.h> +#include <semaphore.h> +#include <string> +#include <fstream> +#include <sstream> +#include <algorithm> + +#include "twadbstream.h" +#include "twrpback.hpp" +#include "../variables.h" +#include "../twcommon.h" +#include "../twrpDigest.hpp" + +twrpback::twrpback(void) { + read_fd = 0; + write_fd = 0; + adb_control_twrp_fd = 0; + adb_control_bu_fd = 0; + adb_read_fd = 0; + adb_write_fd = 0; + adb_write_fd = 0; + ors_fd = 0; + firstPart = true; + adbloginit(); +} + +twrpback::~twrpback(void) { + adblogfile.close(); +} + +void twrpback::adbloginit(void) { + adblogfile.open("/tmp/adb.log", std::fstream::app); +} + +void twrpback::adblogwrite(std::string writemsg) { + adblogfile << writemsg << std::flush; +} + +void twrpback::close_backup_fds() { + if (ors_fd > 0) + close(ors_fd); + if (write_fd > 0) + close(write_fd); + if (adb_read_fd > 0) + close(adb_read_fd); + if (adb_control_bu_fd > 0) + close(adb_control_bu_fd); + if (adbd_fp != NULL) + fclose(adbd_fp); + if (access(TW_ADB_BACKUP, F_OK) == 0) + unlink(TW_ADB_BACKUP); +} + +void twrpback::close_restore_fds() { + if (ors_fd > 0) + close(ors_fd); + if (write_fd > 0) + close(write_fd); + if (adb_control_bu_fd > 0) + close(adb_control_bu_fd); + if (adb_control_twrp_fd > 0) + close(adb_control_twrp_fd); + if (adbd_fp != NULL) + fclose(adbd_fp); + if (access(TW_ADB_RESTORE, F_OK) == 0) + unlink(TW_ADB_RESTORE); +} + +int twrpback::backup(std::string command) { + twrpDigest adb_md5; + bool breakloop = false; + int bytes = 0, errctr = 0; + char result[MAX_ADB_READ]; + uint64_t totalbytes = 0, dataChunkBytes = 0; + int64_t count = -1; // Count of how many blocks set + uint64_t md5fnsize = 0; + struct AdbBackupControlType endadb; + + ADBSTRUCT_STATIC_ASSERT(sizeof(endadb) == MAX_ADB_READ); + + bool writedata = true; + bool compressed = false; + bool firstDataPacket = true; + + adbd_fp = fdopen(adbd_fd, "w"); + if (adbd_fp == NULL) { + adblogwrite("Unable to open adb_fp\n"); + return -1; + } + + if (mkfifo(TW_ADB_BACKUP, 0666) < 0) { + adblogwrite("Unable to create TW_ADB_BACKUP fifo\n"); + return -1; + } + + adblogwrite("opening ORS_INPUT_FILE\n"); + write_fd = open(ORS_INPUT_FILE, O_WRONLY); + while (write_fd < 0) { + write_fd = open(ORS_INPUT_FILE, O_WRONLY); + usleep(10000); + errctr++; + if (errctr > ADB_BU_MAX_ERROR) { + adblogwrite("Unable to open ORS_INPUT_FILE\n"); + close_backup_fds(); + return -1; + } + } + + sprintf(operation, "adbbackup %s", command.c_str()); + if (write(write_fd, operation, sizeof(operation)) != sizeof(operation)) { + adblogwrite("Unable to write to ORS_INPUT_FILE\n"); + close_backup_fds(); + return -1; + } + + adblogwrite("opening ORS_OUTPUT_FILE\n"); + ors_fd = open(ORS_OUTPUT_FILE, O_RDONLY); + if (ors_fd < 0) { + adblogwrite("Unable to open ORS_OUTPUT_FILE\n"); + close_backup_fds(); + return -1; + } + + memset(&result, 0, sizeof(result)); + memset(&cmd, 0, sizeof(cmd)); + + adblogwrite("opening TW_ADB_BU_CONTROL\n"); + adb_control_bu_fd = open(TW_ADB_BU_CONTROL, O_RDONLY | O_NONBLOCK); + if (adb_control_bu_fd < 0) { + adblogwrite("Unable to open TW_ADB_BU_CONTROL for reading.\n"); + close_backup_fds(); + return -1; + } + + adblogwrite("opening TW_ADB_BACKUP\n"); + adb_read_fd = open(TW_ADB_BACKUP, O_RDONLY | O_NONBLOCK); + if (adb_read_fd < 0) { + adblogwrite("Unable to open TW_ADB_BACKUP for reading.\n"); + close_backup_fds(); + return -1; + } + + //loop until TWENDADB sent + while (!breakloop) { + if (read(adb_control_bu_fd, &cmd, sizeof(cmd)) > 0) { + struct AdbBackupControlType structcmd; + + memcpy(&structcmd, cmd, sizeof(cmd)); + std::string cmdstr(structcmd.type); + std::string cmdtype = cmdstr.substr(0, sizeof(structcmd.type) - 1); + + //we received an error, exit and unlink + if (cmdtype == TWERROR) { + writedata = false; + adblogwrite("Error received. Quitting...\n"); + close_backup_fds(); + return -1; + } + //we received the end of adb backup stream so we should break the loop + else if (cmdtype == TWENDADB) { + writedata = false; + adblogwrite("Recieved TWENDADB\n"); + memcpy(&endadb, cmd, sizeof(cmd)); + stringstream str; + str << totalbytes; + adblogwrite(str.str() + " total bytes written\n"); + breakloop = true; + } + //we recieved the TWSTREAMHDR structure metadata to write to adb + else if (cmdtype == TWSTREAMHDR) { + writedata = false; + adblogwrite("Writing TWSTREAMHDR\n"); + if (fwrite(cmd, 1, sizeof(cmd), adbd_fp) != sizeof(cmd)) { + stringstream str; + str << strerror(errno); + adblogwrite("Error writing TWSTREAMHDR to adbd" + str.str() + "\n"); + close_backup_fds(); + return -1; + } + fflush(adbd_fp); + } + //we will be writing an image from TWRP + else if (cmdtype == TWIMG) { + struct twfilehdr twimghdr; + + adblogwrite("Writing TWIMG\n"); + adb_md5.initMD5(); + + memset(&twimghdr, 0, sizeof(twimghdr)); + memcpy(&twimghdr, cmd, sizeof(cmd)); + md5fnsize = twimghdr.size; + + if (fwrite(cmd, 1, sizeof(cmd), adbd_fp) != sizeof(cmd)) { + adblogwrite("Error writing TWIMG to adbd\n"); + close_backup_fds(); + return -1; + } + fflush(adbd_fp); + writedata = true; + } + //we will be writing a tar from TWRP + else if (cmdtype == TWFN) { + struct twfilehdr twfilehdr; + + adblogwrite("Writing TWFN\n"); + adb_md5.initMD5(); + + ADBSTRUCT_STATIC_ASSERT(sizeof(twfilehdr) == MAX_ADB_READ); + + memset(&twfilehdr, 0, sizeof(twfilehdr)); + memcpy(&twfilehdr, cmd, sizeof(cmd)); + md5fnsize = twfilehdr.size; + + compressed = twfilehdr.compressed == 1 ? true: false; + + if (fwrite(cmd, 1, sizeof(cmd), adbd_fp) != sizeof(cmd)) { + adblogwrite("Error writing TWFN to adbd\n"); + close_backup_fds(); + return -1; + } + fflush(adbd_fp); + writedata = true; + } + /* + We received the command that we are done with the file stream. + We will flush the remaining data stream. + Update md5 and write final results to adb stream. + If we need padding because the total bytes are not a multiple + of 512, we pad the end with 0s to we reach 512. + We also write the final md5 to the adb stream. + */ + else if (cmdtype == TWEOF) { + adblogwrite("received TWEOF\n"); + count = totalbytes / MAX_ADB_READ + 1; + count = count * MAX_ADB_READ; + + while ((bytes = read(adb_read_fd, &result, sizeof(result))) == MAX_ADB_READ) { + totalbytes += bytes; + char *writeresult = new char [bytes]; + memcpy(writeresult, result, bytes); + if (adb_md5.updateMD5stream((unsigned char *) writeresult, bytes) == -1) + adblogwrite("failed to update md5 stream\n"); + if (fwrite(writeresult, 1, bytes, adbd_fp) != bytes) { + adblogwrite("Error writing backup data to adbd\n"); + close_backup_fds(); + return -1; + } + fflush(adbd_fp); + delete [] writeresult; + memset(&result, 0, sizeof(result)); + } + + if ((totalbytes % MAX_ADB_READ) != 0) { + adblogwrite("writing padding to stream\n"); + char padding[count - totalbytes]; + memset(padding, 0, sizeof(padding)); + if (fwrite(padding, 1, sizeof(padding), adbd_fp) != sizeof(padding)) { + adblogwrite("Error writing padding to adbd\n"); + close_backup_fds(); + return -1; + } + if (adb_md5.updateMD5stream((unsigned char *) padding, sizeof(padding)) == -1) + adblogwrite("failed to update md5 stream\n"); + fflush(adbd_fp); + totalbytes = 0; + } + + AdbBackupFileTrailer md5trailer; + + memset(&md5trailer, 0, sizeof(md5trailer)); + adb_md5.finalizeMD5stream(); + + std::string md5string = adb_md5.createMD5string(); + + strncpy(md5trailer.start_of_trailer, TWRP, sizeof(md5trailer.start_of_trailer)); + strncpy(md5trailer.type, MD5TRAILER, sizeof(md5trailer.type)); + strncpy(md5trailer.md5, md5string.c_str(), sizeof(md5trailer.md5)); + + md5trailer.crc = crc32(0L, Z_NULL, 0); + md5trailer.crc = crc32(md5trailer.crc, (const unsigned char*) &md5trailer, sizeof(md5trailer)); + + md5trailer.ident = crc32(0L, Z_NULL, 0); + md5trailer.ident = crc32(md5trailer.ident, (const unsigned char*) &md5trailer, sizeof(md5trailer)); + md5trailer.ident = crc32(md5trailer.ident, (const unsigned char*) &md5fnsize, sizeof(md5fnsize)); + + if (fwrite(&md5trailer, 1, sizeof(md5trailer), adbd_fp) != sizeof(md5trailer)) { + adblogwrite("Error writing md5trailer to adbd\n"); + close_backup_fds(); + return -1; + } + fflush(adbd_fp); + writedata = false; + firstDataPacket = true; + } + memset(&cmd, 0, sizeof(cmd)); + } + //If we are to write data because of a new file stream, lets write all the data. + //This will allow us to not write data after a command structure has been written + //to the adb stream. + //If the stream is compressed, we need to always write the data. + if (writedata || compressed) { + while ((bytes = read(adb_read_fd, &result, sizeof(result))) == MAX_ADB_READ) { + if (firstDataPacket) { + struct AdbBackupControlType data_block; + + memset(&data_block, 0, sizeof(data_block)); + strncpy(data_block.start_of_header, TWRP, sizeof(data_block.start_of_header)); + strncpy(data_block.type, TWDATA, sizeof(data_block.type)); + data_block.crc = crc32(0L, Z_NULL, 0); + data_block.crc = crc32(data_block.crc, (const unsigned char*) &data_block, sizeof(data_block)); + if (fwrite(&data_block, 1, sizeof(data_block), adbd_fp) != sizeof(data_block)) { + adblogwrite("Error writing data_block to adbd\n"); + close_backup_fds(); + return -1; + } + fflush(adbd_fp); + firstDataPacket = false; + } + char *writeresult = new char [bytes]; + memcpy(writeresult, result, bytes); + + if (adb_md5.updateMD5stream((unsigned char *) writeresult, bytes) == -1) + adblogwrite("failed to update md5 stream\n"); + + totalbytes += bytes; + dataChunkBytes += bytes; + + if (fwrite(writeresult, 1, bytes, adbd_fp) != bytes) { + adblogwrite("Error writing backup data to adbd\n"); + close_backup_fds(); + return -1; + } + fflush(adbd_fp); + + delete [] writeresult; + memset(&result, 0, sizeof(result)); + if (dataChunkBytes == DATA_MAX_CHUNK_SIZE - sizeof(result)) { + struct AdbBackupControlType data_block; + + memset(&data_block, 0, sizeof(data_block)); + strncpy(data_block.start_of_header, TWRP, sizeof(data_block.start_of_header)); + strncpy(data_block.type, TWDATA, sizeof(data_block.type)); + data_block.crc = crc32(0L, Z_NULL, 0); + data_block.crc = crc32(data_block.crc, (const unsigned char*) &data_block, sizeof(data_block)); + if (fwrite(&data_block, 1, sizeof(data_block), adbd_fp) != sizeof(data_block)) { + adblogwrite("Error writing data_block to adbd\n"); + close_backup_fds(); + return -1; + } + fflush(adbd_fp); + dataChunkBytes = 0; + } + + } + compressed = false; + } + } + + //Write the final end adb structure to the adb stream + if (fwrite(&endadb, 1, sizeof(endadb), adbd_fp) != sizeof(endadb)) { + adblogwrite("Error writing endadb to adbd\n"); + close_backup_fds(); + return -1; + } + fflush(adbd_fp); + close_backup_fds(); + return 0; +} + +int twrpback::restore(void) { + twrpDigest adb_md5; + char cmd[MAX_ADB_READ]; + char result[MAX_ADB_READ]; + struct AdbBackupControlType structcmd; + int adb_control_twrp_fd, errctr = 0; + uint64_t totalbytes = 0, dataChunkBytes = 0; + uint64_t md5fnsize = 0; + bool writedata, read_from_adb; + bool breakloop, eofsent, md5trsent; + + breakloop = false; + read_from_adb = true; + + signal(SIGPIPE, SIG_IGN); + + adbd_fp = fdopen(adbd_fd, "r"); + if (adbd_fp == NULL) { + adblogwrite("Unable to open adb_fp\n"); + close_restore_fds(); + return -1; + } + + if(mkfifo(TW_ADB_RESTORE, 0666)) { + adblogwrite("Unable to create TW_ADB_RESTORE fifo\n"); + close_restore_fds(); + return -1; + } + + adblogwrite("opening ORS_INPUT_FILE\n"); + write_fd = open(ORS_INPUT_FILE, O_WRONLY); + + while (write_fd < 0) { + write_fd = open(ORS_INPUT_FILE, O_WRONLY); + errctr++; + if (errctr > ADB_BU_MAX_ERROR) { + adblogwrite("Unable to open ORS_INPUT_FILE\n"); + close_restore_fds(); + return -1; + } + } + + sprintf(operation, "adbrestore"); + if (write(write_fd, operation, sizeof(operation)) != sizeof(operation)) { + adblogwrite("Unable to write to ORS_INPUT_FILE\n"); + close_restore_fds(); + return -1; + } + + ors_fd = open(ORS_OUTPUT_FILE, O_RDONLY); + if (ors_fd < 0) { + stringstream str; + str << strerror(errno); + adblogwrite("Unable to write to ORS_OUTPUT_FILE: " + str.str() + "\n"); + close_restore_fds(); + return -1; + } + + memset(&result, 0, sizeof(result)); + memset(&cmd, 0, sizeof(cmd)); + + adblogwrite("opening TW_ADB_BU_CONTROL\n"); + adb_control_bu_fd = open(TW_ADB_BU_CONTROL, O_RDONLY | O_NONBLOCK); + if (adb_control_bu_fd < 0) { + stringstream str; + str << strerror(errno); + adblogwrite("Unable to open TW_ADB_BU_CONTROL for writing. " + str.str() + "\n"); + close_restore_fds(); + return -1; + } + + adblogwrite("opening TW_ADB_TWRP_CONTROL\n"); + adb_control_twrp_fd = open(TW_ADB_TWRP_CONTROL, O_WRONLY | O_NONBLOCK); + if (adb_control_twrp_fd < 0) { + stringstream str; + str << strerror(errno); + adblogwrite("Unable to open TW_ADB_TWRP_CONTROL for writing. " + str.str() + ". Retrying...\n"); + while (adb_control_twrp_fd < 0) { + adb_control_twrp_fd = open(TW_ADB_TWRP_CONTROL, O_WRONLY | O_NONBLOCK); + usleep(10000); + errctr++; + if (errctr > ADB_BU_MAX_ERROR) { + adblogwrite("Unable to open TW_ADB_TWRP_CONTROL\n"); + close_backup_fds(); + return -1; + } + } + } + + //Loop until we receive TWENDADB from TWRP + while (!breakloop) { + memset(&cmd, 0, sizeof(cmd)); + if (read(adb_control_bu_fd, &cmd, sizeof(cmd)) > 0) { + struct AdbBackupControlType structcmd; + memcpy(&structcmd, cmd, sizeof(cmd)); + std::string cmdstr(structcmd.type); + std::string cmdtype = cmdstr.substr(0, sizeof(structcmd.type) - 1); + + //If we receive TWEOF from TWRP close adb data fifo + if (cmdtype == TWEOF) { + adblogwrite("Received TWEOF\n"); + struct AdbBackupControlType tweof; + + memset(&tweof, 0, sizeof(tweof)); + memcpy(&tweof, result, sizeof(result)); + read_from_adb = true; + } + //Break when TWRP sends TWENDADB + else if (cmdtype == TWENDADB) { + adblogwrite("Received TWENDADB\n"); + breakloop = true; + close_restore_fds(); + } + //we received an error, exit and unlink + else if (cmdtype == TWERROR) { + adblogwrite("Error received. Quitting...\n"); + close_restore_fds(); + return -1; + } + } + + //If we should read from the adb stream, write commands and data to TWRP + if (read_from_adb) { + std::string cmdstr; + int readbytes; + if ((readbytes = fread(result, 1, sizeof(result), adbd_fp)) == sizeof(result)) { + totalbytes += readbytes; + memcpy(&structcmd, result, sizeof(result)); + cmdstr = structcmd.type; + std::string cmdtype = cmdstr.substr(0, sizeof(structcmd.type) - 1); + + //Tell TWRP we have read the entire adb stream + if (cmdtype == TWENDADB) { + struct AdbBackupControlType endadb; + uint32_t crc, endadbcrc; + + totalbytes -= sizeof(result); + memset(&endadb, 0, sizeof(endadb)); + memcpy(&endadb, result, sizeof(result)); + endadbcrc = endadb.crc; + memset(&endadb.crc, 0, sizeof(endadb.crc)); + crc = crc32(0L, Z_NULL, 0); + crc = crc32(crc, (const unsigned char*) &endadb, sizeof(endadb)); + + if (crc == endadbcrc) { + adblogwrite("Sending TWENDADB\n"); + if (write(adb_control_twrp_fd, &endadb, sizeof(endadb)) < 1) { + stringstream str; + str << strerror(errno); + adblogwrite("Cannot write to ADB_CONTROL_READ_FD: " + str.str() + "\n"); + close_restore_fds(); + return -1; + } + } + else { + adblogwrite("ADB TWENDADB crc header doesn't match\n"); + close_restore_fds(); + return -1; + } + } + //Send TWRP partition metadata + else if (cmdtype == TWSTREAMHDR) { + struct AdbBackupStreamHeader cnthdr; + uint32_t crc, cnthdrcrc; + + ADBSTRUCT_STATIC_ASSERT(sizeof(cnthdr) == MAX_ADB_READ); + totalbytes -= sizeof(result); + + memset(&cnthdr, 0, sizeof(cnthdr)); + memcpy(&cnthdr, result, sizeof(result)); + cnthdrcrc = cnthdr.crc; + memset(&cnthdr.crc, 0, sizeof(cnthdr.crc)); + crc = crc32(0L, Z_NULL, 0); + crc = crc32(crc, (const unsigned char*) &cnthdr, sizeof(cnthdr)); + + if (crc == cnthdrcrc) { + adblogwrite("Restoring TWSTREAMHDR\n"); + if (write(adb_control_twrp_fd, result, sizeof(result)) < 0) { + stringstream str; + str << strerror(errno); + adblogwrite("Cannot write to adb_control_twrp_fd: " + str.str() + "\n"); + close_restore_fds(); + return -1; + } + } + else { + adblogwrite("ADB TWSTREAMHDR crc header doesn't match\n"); + close_restore_fds(); + return -1; + } + } + //Tell TWRP we are sending a partition image + else if (cmdtype == TWIMG) { + struct twfilehdr twimghdr; + uint32_t crc, twimghdrcrc; + + totalbytes -= sizeof(result); + adb_md5.initMD5(); + adblogwrite("Restoring TWIMG\n"); + memset(&twimghdr, 0, sizeof(twimghdr)); + memcpy(&twimghdr, result, sizeof(result)); + md5fnsize = twimghdr.size; + twimghdrcrc = twimghdr.crc; + memset(&twimghdr.crc, 0, sizeof(twimghdr.crc)); + + crc = crc32(0L, Z_NULL, 0); + crc = crc32(crc, (const unsigned char*) &twimghdr, sizeof(twimghdr)); + if (crc == twimghdrcrc) { + if (write(adb_control_twrp_fd, result, sizeof(result)) < 1) { + stringstream str; + str << strerror(errno); + adblogwrite("Cannot write to adb_control_twrp_fd: " + str.str() + "\n"); + close_restore_fds(); + return -1; + } + } + else { + adblogwrite("ADB TWIMG crc header doesn't match\n"); + close_restore_fds(); + return -1; + } + adblogwrite("opening TW_ADB_RESTORE\n"); + adb_write_fd = open(TW_ADB_RESTORE, O_WRONLY); + } + //Tell TWRP we are sending a tar stream + else if (cmdtype == TWFN) { + struct twfilehdr twfilehdr; + uint32_t crc, twfilehdrcrc; + + totalbytes -= sizeof(result); + adb_md5.initMD5(); + adblogwrite("Restoring TWFN\n"); + memset(&twfilehdr, 0, sizeof(twfilehdr)); + memcpy(&twfilehdr, result, sizeof(result)); + md5fnsize = twfilehdr.size; + twfilehdrcrc = twfilehdr.crc; + memset(&twfilehdr.crc, 0, sizeof(twfilehdr.crc)); + + crc = crc32(0L, Z_NULL, 0); + crc = crc32(crc, (const unsigned char*) &twfilehdr, sizeof(twfilehdr)); + + if (crc == twfilehdrcrc) { + if (write(adb_control_twrp_fd, result, sizeof(result)) < 1) { + stringstream str; + str << strerror(errno); + adblogwrite("Cannot write to adb_control_twrp_fd: " + str.str() + "\n"); + close_restore_fds(); + return -1; + } + } + else { + adblogwrite("ADB TWFN crc header doesn't match\n"); + close_restore_fds(); + return -1; + } + + adblogwrite("opening TW_ADB_RESTORE\n"); + adb_write_fd = open(TW_ADB_RESTORE, O_WRONLY); + } + //Send the tar or partition image md5 to TWRP + else if (cmdtype == TWDATA) { + totalbytes -= sizeof(result); + while (1) { + if ((readbytes = fread(result, 1, sizeof(result), adbd_fp)) != sizeof(result)) { + close_restore_fds(); + return -1; + } + totalbytes += readbytes; + memcpy(&structcmd, result, sizeof(result)); + cmdstr = structcmd.type; + + if (cmdstr.substr(0, sizeof(MD5TRAILER) - 1) == MD5TRAILER) { + struct AdbBackupFileTrailer md5tr; + uint32_t crc, md5trcrc, md5ident, md5identmatch; + + ADBSTRUCT_STATIC_ASSERT(sizeof(md5tr) == MAX_ADB_READ); + memset(&md5tr, 0, sizeof(md5tr)); + memcpy(&md5tr, result, sizeof(result)); + md5ident = md5tr.ident; + + memset(&md5tr.ident, 0, sizeof(md5tr.ident)); + + md5identmatch = crc32(0L, Z_NULL, 0); + md5identmatch = crc32(md5identmatch, (const unsigned char*) &md5tr, sizeof(md5tr)); + md5identmatch = crc32(md5identmatch, (const unsigned char*) &md5fnsize, sizeof(md5fnsize)); + + if (md5identmatch == md5ident) { + totalbytes -= sizeof(result); + close(adb_write_fd); + adblogwrite("Restoring MD5TRAILER\n"); + md5trcrc = md5tr.crc; + memset(&md5tr.crc, 0, sizeof(md5tr.crc)); + crc = crc32(0L, Z_NULL, 0); + crc = crc32(crc, (const unsigned char*) &md5tr, sizeof(md5tr)); + if (crc == md5trcrc) { + if (write(adb_control_twrp_fd, result, sizeof(result)) < 1) { + stringstream str; + str << strerror(errno); + adblogwrite("Cannot write to adb_control_twrp_fd: " + str.str() + "\n"); + close_restore_fds(); + return -1; + } + } + else { + adblogwrite("ADB MD5TRAILER crc header doesn't match\n"); + close_restore_fds(); + return -1; + } + adblogwrite("md5 finalize stream\n"); + adb_md5.finalizeMD5stream(); + + AdbBackupFileTrailer md5; + + memset(&md5, 0, sizeof(md5)); + strncpy(md5.start_of_trailer, TWRP, sizeof(md5.start_of_trailer)); + strncpy(md5.type, TWMD5, sizeof(md5.type)); + std::string md5string = adb_md5.createMD5string(); + strncpy(md5.md5, md5string.c_str(), sizeof(md5.md5)); + + adblogwrite("Sending MD5Check\n"); + if (write(adb_control_twrp_fd, &md5, sizeof(md5)) < 1) { + stringstream str; + str << strerror(errno); + adblogwrite("Cannot write to adb_control_twrp_fd: " + str.str() + "\n"); + close_restore_fds(); + return -1; + } + read_from_adb = false; //don't read from adb until TWRP sends TWEOF + break; + } + } + if (adb_md5.updateMD5stream((unsigned char*)result, sizeof(result)) == -1) + adblogwrite("failed to update md5 stream\n"); + dataChunkBytes += readbytes; + + if (write(adb_write_fd, result, sizeof(result)) < 0) { + stringstream str; + str << strerror(errno); + adblogwrite("Cannot write to adb_write_fd\n" + str.str() + ". Retrying.\n"); + while(write(adb_write_fd, result, sizeof(result)) < 0) { + adblogwrite("Cannot write to adb_write_fd\n" + str.str() + ". Retrying.\n"); + continue; + } + } + if (dataChunkBytes == ((DATA_MAX_CHUNK_SIZE) - sizeof(result))) { + dataChunkBytes = 0; + break; + } + memset(&result, 0, sizeof(result)); + } + } + } + } + } + + stringstream str; + str << totalbytes; + adblogwrite(str.str() + " bytes restored from adbbackup\n"); + return 0; +} + +int main(int argc, char **argv) { + int index; + int ret = 0, pos = 0; + std::string command; + twrpback tw; + + tw.adblogwrite("Starting adb backup and restore\n"); + if (mkfifo(TW_ADB_BU_CONTROL, 0666) < 0) { + stringstream str; + str << strerror(errno); + tw.adblogwrite("Unable to create TW_ADB_BU_CONTROL fifo: " + str.str() + "\n"); + unlink(TW_ADB_BU_CONTROL); + return -1; + } + if (mkfifo(TW_ADB_TWRP_CONTROL, 0666) < 0) { + stringstream str; + str << strerror(errno); + tw.adblogwrite("Unable to create TW_ADB_TWRP_CONTROL fifo: " + str.str() + "\n"); + unlink(TW_ADB_TWRP_CONTROL); + unlink(TW_ADB_BU_CONTROL); + return -1; + } + + command = argv[1]; + for (index = 2; index < argc; index++) { + command = command + " " + argv[index]; + } + + pos = command.find("backup"); + if (pos < 0) { + pos = command.find("restore"); + } + command.erase(0, pos); + command.erase(std::remove(command.begin(), command.end(), '\''), command.end()); + tw.adblogwrite("command: " + command + "\n"); + + if (command.substr(0, sizeof("backup") - 1) == "backup") { + tw.adblogwrite("Starting adb backup\n"); + if (isdigit(*argv[1])) + tw.adbd_fd = atoi(argv[1]); + else + tw.adbd_fd = 1; + ret = tw.backup(command); + } + else if (command.substr(0, sizeof("restore") - 1) == "restore") { + tw.adblogwrite("Starting adb restore\n"); + if (isdigit(*argv[1])) + tw.adbd_fd = atoi(argv[1]); + else + tw.adbd_fd = 0; + ret = tw.restore(); + } + if (ret == 0) + tw.adblogwrite("Adb backup/restore completed\n"); + else + tw.adblogwrite("Adb backup/restore failed\n"); + + if (unlink(TW_ADB_BU_CONTROL) < 0) { + stringstream str; + str << strerror(errno); + tw.adblogwrite("Unable to remove TW_ADB_BU_CONTROL: " + str.str()); + } + unlink(TW_ADB_TWRP_CONTROL); + return ret; +} diff --git a/adbbu/twrpback.hpp b/adbbu/twrpback.hpp new file mode 100644 index 000000000..752d35ea1 --- /dev/null +++ b/adbbu/twrpback.hpp @@ -0,0 +1,49 @@ +/* + Copyright 2013 to 2016 TeamWin + TWRP is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + TWRP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with TWRP. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <fstream> + +#include "../orscmd/orscmd.h" +#include "../variables.h" +#include "../twcommon.h" + +class twrpback { +public: + int adbd_fd; // adbd data stream + + twrpback(void); + virtual ~twrpback(void); + int backup(std::string command); // adb backup stream + int restore(void); // adb restore stream + void adblogwrite(std::string writemsg); // adb debugging log function + void close_backup_fds(); // close backup resources + void close_restore_fds(); // close restore resources + +private: + int read_fd; // ors input fd + int write_fd; // ors operation fd + int ors_fd; // ors output fd + int adb_control_twrp_fd; // fd for bu to twrp communication + int adb_control_bu_fd; // fd for twrp to bu communication + int adb_read_fd; // adb read data stream + int adb_write_fd; // adb write data stream + bool firstPart; // first partition in the stream + FILE *adbd_fp; // file pointer for adb stream + char cmd[512]; // store result of commands + char operation[512]; // operation to send to ors + std::ofstream adblogfile; // adb stream log file + void adbloginit(void); // setup adb log stream file +}; diff --git a/gui/Android.mk b/gui/Android.mk index 045824df6..98d562944 100644 --- a/gui/Android.mk +++ b/gui/Android.mk @@ -110,6 +110,7 @@ ifeq ($(TW_CUSTOM_THEME),) TW_THEME := landscape_hdpi endif endif + ifeq ($(TWRP_NEW_THEME),true) TWRP_THEME_LOC := $(commands_recovery_local_path)/gui/theme/$(TW_THEME) TWRP_RES := $(commands_recovery_local_path)/gui/theme/common/fonts diff --git a/gui/action.cpp b/gui/action.cpp index aac2c313f..d98a81420 100644 --- a/gui/action.cpp +++ b/gui/action.cpp @@ -1180,9 +1180,8 @@ int GUIAction::nandroid(std::string arg) DataManager::GetValue(TW_BACKUP_NAME, Backup_Name); string auto_gen = gui_lookup("auto_generate", "(Auto Generate)"); if (Backup_Name == auto_gen || Backup_Name == gui_lookup("curr_date", "(Current Date)") || Backup_Name == "0" || Backup_Name == "(" || PartitionManager.Check_Backup_Name(true) == 0) { - ret = PartitionManager.Run_Backup(); - } - else { + ret = PartitionManager.Run_Backup(false); + } else { operation_end(1); return -1; } @@ -1728,12 +1727,16 @@ int GUIAction::flashimage(std::string arg __unused) { int op_status = 0; + PartitionSettings part_settings; operation_start("Flash Image"); - string path, filename, full_filename; - DataManager::GetValue("tw_zip_location", path); - DataManager::GetValue("tw_file", filename); - full_filename = path + "/" + filename; - if (PartitionManager.Flash_Image(full_filename)) + DataManager::GetValue("tw_zip_location", part_settings.Restore_Name); + DataManager::GetValue("tw_file", part_settings.Backup_FileName); + unsigned long long total_bytes = TWFunc::Get_File_Size(part_settings.Restore_Name + "/" + part_settings.Backup_FileName); + ProgressTracking progress(total_bytes); + part_settings.progress = &progress; + part_settings.adbbackup = false; + part_settings.PM_Method = PM_RESTORE; + if (PartitionManager.Flash_Image(&part_settings)) op_status = 0; // success else op_status = 1; // fail diff --git a/gui/devices/common/res/languages/en.xml b/gui/devices/common/res/languages/en.xml index 8ce476254..e47ee7050 100644 --- a/gui/devices/common/res/languages/en.xml +++ b/gui/devices/common/res/languages/en.xml @@ -227,5 +227,9 @@ <string name="change_fs_err">Error changing file system.</string> <string name="theme_ver_err">Custom theme version does not match TWRP version. Using stock theme.</string> <string name="install_reboot">Rebooting in 5 seconds</string> + <string name="adbbackup_error">Error with ADB Backup. Quitting..."</string> + <string name="adbbackup_control_error">Cannot write to adb control channel</string> + <string name="twrp_adbbu_option">--twrp option is required to enable twrp adb backup</string> + <string name="partition_not_found">path: {1} not found in partititon list</string> </resources> </language> diff --git a/gui/gui.cpp b/gui/gui.cpp index 4cf80a482..df41939fb 100644 --- a/gui/gui.cpp +++ b/gui/gui.cpp @@ -460,6 +460,14 @@ static void ors_command_read() gui_set_FILE(orsout); PageManager::GetResources()->DumpStrings(); ors_command_done(); + //check to see if we should show backup page for parsing adbbackup partitions + } else if (strlen(command) == 23 && strncmp(command, "adbbackup", 9) == 0) { + gui_set_FILE(orsout); + DataManager::SetValue("tw_action", "twcmd"); + DataManager::SetValue("tw_action_param", command); + DataManager::SetValue("tw_enable_adb_backup", 1); + gui_changePage("backup"); + ors_command_done(); } else { // mirror output messages gui_set_FILE(orsout); @@ -480,8 +488,6 @@ static void ors_command_read() // put all things that need to be done after the command is finished into ors_command_done, not here } } - } else { - LOGINFO("ORS command line read returned an error: %i, %i, %s\n", read_ret, errno, strerror(errno)); } } diff --git a/gui/theme/common/landscape.xml b/gui/theme/common/landscape.xml index 525a2c1da..a7a59d897 100644 --- a/gui/theme/common/landscape.xml +++ b/gui/theme/common/landscape.xml @@ -1557,6 +1557,7 @@ <conditions> <condition var1="tw_include_encrypted_backup" var2="1"/> <condition var1="tw_encrypt_backup" var2="0"/> + <condition var1="tw_enable_adb_backup" op="!=" var2="1"/> </conditions> <placement x="%col1_x_right%" y="%row3_y%"/> <text>{@enc_disabled=disabled - set a password to enable}</text> @@ -1566,6 +1567,7 @@ <conditions> <condition var1="tw_include_encrypted_backup" var2="1"/> <condition var1="tw_encrypt_backup" var2="1"/> + <condition var1="tw_enable_adb_backup" op="!=" var2="1"/> </conditions> <placement x="%col1_x_right%" y="%row3_y%"/> <text>{@enc_enabled=enabled}</text> @@ -1608,6 +1610,7 @@ </checkbox> <button style="main_button_half_width"> + <condition var1="tw_enable_adb_backup" op="!=" var2="1"/> <placement x="%col1_x_left%" y="%row15a_y%"/> <text>{@select_storage_btn=Select Storage}</text> <actions> diff --git a/gui/theme/common/languages/en.xml b/gui/theme/common/languages/en.xml index 4c26d304f..2b80b25cf 100644 --- a/gui/theme/common/languages/en.xml +++ b/gui/theme/common/languages/en.xml @@ -668,5 +668,9 @@ <string name="theme_ver_err">Custom theme version does not match TWRP version. Using stock theme.</string> <string name="up_a_level">(Up A Level)</string> <string name="install_reboot">Rebooting in 5 seconds</string> + <string name="adbbackup_error">Error with ADB Backup. Quitting..."</string> + <string name="adbbackup_control_error">Cannot write to adb control channel</string> + <string name="twrp_adbbu_option">--twrp option is required to enable twrp adb backup</string> + <string name="partition_not_found">path: {1} not found in partititon list</string> </resources> </language> diff --git a/gui/theme/common/portrait.xml b/gui/theme/common/portrait.xml index 03e3982a2..6b7453845 100644 --- a/gui/theme/common/portrait.xml +++ b/gui/theme/common/portrait.xml @@ -1485,6 +1485,7 @@ <conditions> <condition var1="tw_include_encrypted_backup" var2="1"/> <condition var1="tw_encrypt_backup" var2="0"/> + <condition var1="tw_enable_adb_backup" op="!=" var2="1"/> </conditions> <placement x="%tab3_col3_x%" y="%row1_y%" w="%tab3_width%" h="%tab_height%"/> <text>{@encryption_tab=ENCRYPTION}</text> @@ -1499,6 +1500,7 @@ <conditions> <condition var1="tw_include_encrypted_backup" var2="1"/> <condition var1="tw_encrypt_backup" var2="1"/> + <condition var1="tw_enable_adb_backup" op="!=" var2="1"/> </conditions> <placement x="%tab3_col3_x%" y="%row1_y%" w="%tab3_width%" h="%tab_height%"/> <text>{@encryption_tab=ENCRYPTION}</text> @@ -1524,6 +1526,7 @@ </fill> <button> + <condition var1="tw_enable_adb_backup" op="!=" var2="1"/> <placement x="indent" y="%row3a_y%" w="%content_width%" h="%navbar_height%"/> <fill color="%transparent%"/> <actions> @@ -1540,6 +1543,7 @@ </partitionlist> <button style="main_button_half_height"> + <condition var1="tw_enable_adb_backup" op="!=" var2="1"/> <placement x="%indent%" y="%row18a_y%"/> <text>{@select_storage_btn=Select Storage}</text> <actions> @@ -1596,6 +1600,7 @@ <conditions> <condition var1="tw_include_encrypted_backup" var2="1"/> <condition var1="tw_encrypt_backup" var2="0"/> + <condition var1="tw_enable_adb_backup" op="!=" var2="1"/> </conditions> <placement x="%tab3_col3_x%" y="%row1_y%" w="%tab3_width%" h="%tab_height%"/> <text>{@encryption_tab=ENCRYPTION}</text> @@ -1610,6 +1615,7 @@ <conditions> <condition var1="tw_include_encrypted_backup" var2="1"/> <condition var1="tw_encrypt_backup" var2="1"/> + <condition var1="tw_enable_adb_backup" op="!=" var2="1"/> </conditions> <placement x="%tab3_col3_x%" y="%row1_y%" w="%tab3_width%" h="%tab_height%"/> <text>{@encryption_tab=ENCRYPTION}</text> @@ -1683,6 +1689,7 @@ <conditions> <condition var1="tw_include_encrypted_backup" var2="1"/> <condition var1="tw_encrypt_backup" var2="0"/> + <condition var1="tw_enable_adb_backup" op="!=" var2="1"/> </conditions> <placement x="%tab3_col3_x%" y="%row1_y%" w="%tab3_width%" h="%tab_height%"/> <text>{@encryption_tab=ENCRYPTION}</text> @@ -1697,6 +1704,7 @@ <conditions> <condition var1="tw_include_encrypted_backup" var2="1"/> <condition var1="tw_encrypt_backup" var2="1"/> + <condition var1="tw_enable_adb_backup" op="!=" var2="1"/> </conditions> <placement x="%tab3_col3_x%" y="%row1_y%" w="%tab3_width%" h="%tab_height%"/> <text>{@encryption_tab=ENCRYPTION}</text> @@ -1793,6 +1801,7 @@ <conditions> <condition var1="tw_include_encrypted_backup" var2="1"/> <condition var1="tw_encrypt_backup" var2="0"/> + <condition var1="tw_enable_adb_backup" op="!=" var2="1"/> </conditions> <placement x="%tab3_col3_x%" y="%row1_y%" w="%tab3_width%" h="%tab_height%"/> <text>{@encryption_tab=ENCRYPTION}</text> @@ -1807,6 +1816,7 @@ <conditions> <condition var1="tw_include_encrypted_backup" var2="1"/> <condition var1="tw_encrypt_backup" var2="1"/> + <condition var1="tw_enable_adb_backup" op="!=" var2="1"/> </conditions> <placement x="%tab3_col3_x%" y="%row1_y%" w="%tab3_width%" h="%tab_height%"/> <text>{@encryption_tab=ENCRYPTION}</text> @@ -1899,6 +1909,7 @@ <conditions> <condition var1="tw_include_encrypted_backup" var2="1"/> <condition var1="tw_encrypt_backup" var2="0"/> + <condition var1="tw_enable_adb_backup" op="!=" var2="1"/> </conditions> <placement x="%tab3_col3_x%" y="%row1_y%" w="%tab3_width%" h="%tab_height%"/> <text>{@encryption_tab=ENCRYPTION}</text> @@ -1913,6 +1924,7 @@ <conditions> <condition var1="tw_include_encrypted_backup" var2="1"/> <condition var1="tw_encrypt_backup" var2="1"/> + <condition var1="tw_enable_adb_backup" op="!=" var2="1"/> </conditions> <placement x="%tab3_col3_x%" y="%row1_y%" w="%tab3_width%" h="%tab_height%"/> <text>{@encryption_tab=ENCRYPTION}</text> diff --git a/gui/theme/common/watch.xml b/gui/theme/common/watch.xml index 4516ce262..38a2a238f 100644 --- a/gui/theme/common/watch.xml +++ b/gui/theme/common/watch.xml @@ -213,7 +213,7 @@ <text>{@backup_btn=Backup}</text> <actions> <action function="set">tw_back=main</action> - <action function="page">backup_selectstorage</action> + <action function="page">backup</action> </actions> </button> @@ -1786,7 +1786,7 @@ </action> </page> - <page name="backup_selectstorage"> + <page name="backup"> <template name="page"/> <template name="statusbar"/> @@ -1807,7 +1807,7 @@ <image resource="q_btn_refresh"/> <actions> <action function="refreshsizes"/> - <action function="page">backup_selectstorage</action> + <action function="page">backup</action> </actions> </button> @@ -1824,7 +1824,7 @@ <highlight color="%highlight_color%"/> <image resource="q_btn_arrow_right"/> <actions> - <action function="set">tw_back=backup_selectstorage</action> + <action function="set">tw_back=backup</action> <action function="page">backup_selectpartitions</action> </actions> </button> @@ -1869,7 +1869,7 @@ <placement x="%col1_x_left%" y="%row11_y%"/> <highlight color="%highlight_color%"/> <image resource="q_btn_arrow_left"/> - <action function="page">backup_selectstorage</action> + <action function="page">backup</action> </button> <button> @@ -1946,6 +1946,7 @@ <conditions> <condition var1="tw_include_encrypted_backup" var2="1"/> <condition var1="tw_encrypt_backup" var2="0"/> + <condition var1="tw_enable_adb_backup" op="!=" var2="1"/> </conditions> <placement x="%btn4_col2_x%" y="%row11_y%"/> <highlight color="%highlight_color%"/> @@ -1961,6 +1962,7 @@ <conditions> <condition var1="tw_include_encrypted_backup" var2="1"/> <condition var1="tw_encrypt_backup" var2="1"/> + <condition var1="tw_enable_adb_backup" op="!=" var2="1"/> </conditions> <placement x="%btn4_col2_x%" y="%row11_y%"/> <highlight color="%highlight_color%"/> @@ -2071,7 +2073,7 @@ <placement x="%center_x%" y="%row2_header_y%" w="%screen_half_width%" h="48"/> <actions> <action function="set">tw_back=backup_confirm</action> - <action function="page">backup_selectstorage</action> + <action function="page">backup</action> </actions> </button> @@ -2084,6 +2086,7 @@ <conditions> <condition var1="tw_include_encrypted_backup" var2="1"/> <condition var1="tw_encrypt_backup" var2="0"/> + <condition var1="tw_enable_adb_backup" op="!=" var2="1"/> </conditions> <placement x="%col1_x_right%" y="%row4a_y%"/> <text>{@disabled=Disabled}</text> @@ -2093,6 +2096,7 @@ <conditions> <condition var1="tw_include_encrypted_backup" var2="1"/> <condition var1="tw_encrypt_backup" var2="1"/> + <condition var1="tw_enable_adb_backup" op="!=" var2="1"/> </conditions> <placement x="%col1_x_right%" y="%row4a_y%"/> <text>{@enabled=Enabled}</text> @@ -2146,7 +2150,7 @@ <action> <touch key="back"/> - <action function="page">backup_selectstorage</action> + <action function="page">backup</action> </action> </page> diff --git a/openrecoveryscript.cpp b/openrecoveryscript.cpp index 75db902e2..0d2268cd1 100644 --- a/openrecoveryscript.cpp +++ b/openrecoveryscript.cpp @@ -1,5 +1,5 @@ /* - Copyright 2012 bigbiff/Dees_Troy TeamWin + Copyright 2016 TeamWin This file is part of TWRP/TeamWin Recovery Project. TWRP is free software: you can redistribute it and/or modify @@ -16,6 +16,7 @@ along with TWRP. If not, see <http://www.gnu.org/licenses/>. */ +#define __STDC_FORMAT_MACROS 1 #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -26,21 +27,31 @@ #include <dirent.h> #include <time.h> #include <errno.h> +#include <inttypes.h> #include <iostream> #include <fstream> +#include <sstream> +#include <string> +#include <iterator> +#include <algorithm> #include <sys/types.h> #include <sys/wait.h> +#include <zlib.h> #include "twrp-functions.hpp" #include "partitions.hpp" #include "twcommon.h" #include "openrecoveryscript.hpp" +#include "progresstracking.hpp" #include "variables.h" #include "adb_install.h" #include "data.hpp" #include "adb_install.h" #include "fuse_sideload.h" #include "gui/gui.hpp" +#include "gui/pages.hpp" +#include "orscmd/orscmd.h" +#include "adbbu/libtwadbbu.hpp" extern "C" { #include "twinstall.h" #include "gui/gui.h" @@ -139,6 +150,8 @@ int OpenRecoveryScript::run_script_file(void) { // Wipe if (strcmp(value, "cache") == 0 || strcmp(value, "/cache") == 0) { PartitionManager.Wipe_By_Path("/cache"); + } else if (strcmp(value, "system") == 0 || strcmp(value, "/system") == 0) { + PartitionManager.Wipe_By_Path("/system"); } else if (strcmp(value, "dalvik") == 0 || strcmp(value, "dalvick") == 0 || strcmp(value, "dalvikcache") == 0 || strcmp(value, "dalvickcache") == 0) { PartitionManager.Wipe_Dalvik_Cache(); } else if (strcmp(value, "data") == 0 || strcmp(value, "/data") == 0 || strcmp(value, "factory") == 0 || strcmp(value, "factoryreset") == 0) { @@ -280,6 +293,17 @@ int OpenRecoveryScript::run_script_file(void) { ret_val = 1; else gui_msg("done=Done."); + } else if (strncmp(command, "adbbackup", 9) == 0) { + ret_val = Backup_ADB_Command(value); + if (ret_val == 1) { + twadbbu::Write_TWERROR(); + gui_err("adbbackup_error=Error with ADB Backup. Quitting..."); + } + } else if (strcmp(command, "adbrestore") == 0) { + LOGINFO("running adb restore\n"); + ret_val = Restore_ADB_Backup(); + } else if (strcmp(command, "remountrw") == 0) { + ret_val = remountrw(); } else if (strcmp(command, "mount") == 0) { // Mount DataManager::SetValue("tw_action_text2", gui_parse_text("{@mounting}")); @@ -400,6 +424,7 @@ int OpenRecoveryScript::run_script_file(void) { gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(SCRIPT_FILE_TMP)(strerror(errno))); return 1; } + if (install_cmd && DataManager::GetIntValue(TW_HAS_INJECTTWRP) == 1 && DataManager::GetIntValue(TW_INJECT_AFTER_ZIP) == 1) { gui_msg("injecttwrp=Injecting TWRP into boot image..."); TWPartition* Boot = PartitionManager.Find_Partition_By_Path("/boot"); @@ -485,6 +510,72 @@ int OpenRecoveryScript::Install_Command(string Zip) { return ret_val; } +int OpenRecoveryScript::Backup_ADB_Command(std::string Options) { + std::vector<std::string> args; + std::string Backup_List; + bool adbbackup = true, ret = false; + std::string rmopt = "--"; + + std::replace(Options.begin(), Options.end(), ':', ' '); + args = TWFunc::Split_String(Options, " "); + + DataManager::SetValue(TW_USE_COMPRESSION_VAR, 0); + DataManager::SetValue(TW_SKIP_MD5_GENERATE_VAR, 0); + + if (args[1].compare("--twrp") != 0) { + gui_err("twrp_adbbu_option=--twrp option is required to enable twrp adb backup"); + sleep(2); + return 1; + } + + for (unsigned i = 2; i < args.size(); i++) { + int compress; + + std::string::size_type size = args[i].find(rmopt); + if (size != std::string::npos) + args[i].erase(size, rmopt.length()); + + if (args[i].compare("compress") == 0) { + gui_msg("compression_on=Compression is on"); + DataManager::SetValue(TW_USE_COMPRESSION_VAR, 1); + continue; + } + DataManager::GetValue(TW_USE_COMPRESSION_VAR, compress); + gui_print("%s\n", args[i].c_str()); + std::string path; + path = "/" + args[i]; + TWPartition* part = PartitionManager.Find_Partition_By_Path(path); + if (part) { + Backup_List += path; + Backup_List += ";"; + } + else { + gui_msg(Msg(msg::kError, "partition_not_found=path: {1} not found in partition list")(path)); + return 1; + } + } + + if (Backup_List.empty()) { + DataManager::GetValue("tw_backup_list", Backup_List); + if (Backup_List.empty()) { + gui_err("no_partition_selected=No partitions selected for backup."); + return 1; + } + } + else + DataManager::SetValue("tw_backup_list", Backup_List); + + ret = PartitionManager.Run_Backup(adbbackup); + DataManager::SetValue(TW_BACKUP_NAME, gui_lookup("auto_generate", "(Auto Generate)")); + if (!ret) { + gui_err("backup_fail=Backup failed"); + return 1; + } + gui_msg("backup_complete=Backup Complete"); + sleep(2); //give time for user to see messages on console + return 0; +} + string OpenRecoveryScript::Locate_Zip_File(string Zip, string Storage_Root) { string Path = TWFunc::Get_Path(Zip); string File = TWFunc::Get_Filename(Zip); @@ -513,6 +604,7 @@ int OpenRecoveryScript::Backup_Command(string Options) { char value1[SCRIPT_COMMAND_SIZE]; int line_len, i; string Backup_List; + bool adbbackup = false; strcpy(value1, Options.c_str()); @@ -558,7 +650,7 @@ int OpenRecoveryScript::Backup_Command(string Options) { } } DataManager::SetValue("tw_backup_list", Backup_List); - if (!PartitionManager.Run_Backup()) { + if (!PartitionManager.Run_Backup(false)) { gui_err("backup_fail=Backup Failed"); return 1; } @@ -651,3 +743,196 @@ void OpenRecoveryScript::Run_CLI_Command(const char* command) { call_after_cli_command(); LOGINFO("Done reading ORS command from command line\n"); } + +int OpenRecoveryScript::Restore_ADB_Backup(void) { + bool breakloop = false; + int partition_count = 0; + std::string Restore_Name; + std::size_t pos = 0; + struct AdbBackupFileTrailer adbmd5; + struct PartitionSettings part_settings; + int adb_control_twrp_fd, adb_write_fd, systemro; + int adb_control_bu_fd, ret = 0; + char cmd[512]; + int orsfd = open(ORS_OUTPUT_FILE, O_WRONLY); + + part_settings.total_restore_size = 0; + + PartitionManager.Mount_All_Storage(); + DataManager::SetValue(TW_SKIP_MD5_CHECK_VAR, 0); + LOGINFO("opening TW_ADB_BU_CONTROL\n"); + adb_control_bu_fd = open(TW_ADB_BU_CONTROL, O_WRONLY | O_NONBLOCK); + LOGINFO("opening TW_ADB_TWRP_CONTROL\n"); + adb_control_twrp_fd = open(TW_ADB_TWRP_CONTROL, O_RDONLY | O_NONBLOCK); + memset(&adbmd5, 0, sizeof(adbmd5)); + + while (!breakloop) { + memset(&cmd, 0, sizeof(cmd)); + if (read(adb_control_twrp_fd, cmd, sizeof(cmd)) > 0) { + struct AdbBackupControlType cmdstruct; + + memset(&cmdstruct, 0, sizeof(cmdstruct)); + memcpy(&cmdstruct, cmd, sizeof(cmdstruct)); + std::string cmdstr(cmdstruct.type); + std::string cmdtype = cmdstr.substr(0, sizeof(cmdstruct.type) - 1); + if (cmdstr.substr(0, sizeof(cmdstruct.type) - 1) == TWSTREAMHDR) { + struct AdbBackupStreamHeader twhdr; + memcpy(&twhdr, cmd, sizeof(cmd)); + LOGINFO("ADB Partition count: %" PRIu64 "\n", twhdr.partition_count); + LOGINFO("ADB version: %" PRIu64 "\n", twhdr.version); + if (twhdr.version != ADB_BACKUP_VERSION) { + LOGERR("Incompatible adb backup version!\n"); + breakloop = false; + break; + } + partition_count = twhdr.partition_count; + } + else if (cmdtype == MD5TRAILER) { + LOGINFO("Restoring MD5TRAILER\n"); + memcpy(&adbmd5, cmd, sizeof(cmd)); + } + else if (cmdtype == TWMD5) { + struct AdbBackupFileTrailer md5check; + LOGINFO("Restoring TWMD5\n"); + + memset(&md5check, 0, sizeof(md5check)); + memcpy(&md5check, cmd, sizeof(cmd)); + if (strcmp(md5check.md5, adbmd5.md5) != 0) { + LOGERR("md5 doesn't match!\n"); + LOGERR("file md5: %s\n", adbmd5.md5); + LOGERR("check md5: %s\n", md5check.md5); + breakloop = true; + ret = 1; + break; + } + else { + LOGINFO("adbrestore md5 matches\n"); + LOGINFO("adbmd5.md5: %s\n", adbmd5.md5); + LOGINFO("md5check.md5: %s\n", md5check.md5); + } + } + else if (cmdtype == TWENDADB) { + LOGINFO("received TWENDADB\n"); + breakloop = true; + break; + } + else { + struct twfilehdr twimghdr; + memcpy(&twimghdr, cmd, sizeof(cmd)); + std::string cmdstr(twimghdr.type); + Restore_Name = twimghdr.name; + part_settings.total_restore_size = twimghdr.size; + if (cmdtype == TWIMG) { + LOGINFO("ADB Type: %s\n", twimghdr.type); + LOGINFO("ADB Restore_Name: %s\n", Restore_Name.c_str()); + LOGINFO("ADB Restore_size: %" PRIu64 "\n", part_settings.total_restore_size); + string compression = (twimghdr.compressed == 1) ? "compressed" : "uncompressed"; + LOGINFO("ADB compression: %s\n", compression.c_str()); + std::string Backup_FileName; + std::size_t pos = Restore_Name.find_last_of("/"); + std::string path = "/" + Restore_Name.substr(pos, Restore_Name.size()); + pos = path.find_first_of("."); + path = path.substr(0, pos); + if (path.substr(0,1).compare("//")) { + path = path.substr(1, path.size()); + } + + pos = Restore_Name.find_last_of("/"); + Backup_FileName = Restore_Name.substr(pos + 1, Restore_Name.size()); + part_settings.Part = PartitionManager.Find_Partition_By_Path(path); + part_settings.Restore_Name = path; + part_settings.partition_count = partition_count; + part_settings.adbbackup = true; + part_settings.adb_compression = twimghdr.compressed; + part_settings.Backup_FileName = Backup_FileName; + part_settings.PM_Method = PM_RESTORE; + ProgressTracking progress(part_settings.total_restore_size); + part_settings.progress = &progress; + if (!PartitionManager.Restore_Partition(&part_settings)) { + LOGERR("ADB Restore failed.\n"); + return 1; + } + } + else if (cmdtype == TWFN) { + LOGINFO("ADB Type: %s\n", twimghdr.type); + LOGINFO("ADB Restore_Name: %s\n", Restore_Name.c_str()); + LOGINFO("ADB Restore_size: %" PRIi64 "\n", part_settings.total_restore_size); + string compression = (twimghdr.compressed == 1) ? "compressed" : "uncompressed"; + LOGINFO("ADB compression: %s\n", compression.c_str()); + std::string Backup_FileName; + std::size_t pos = Restore_Name.find_last_of("/"); + std::string path = "/" + Restore_Name.substr(pos, Restore_Name.size()); + pos = path.find_first_of("."); + path = path.substr(0, pos); + if (path.substr(0,1).compare("//")) { + path = path.substr(1, path.size()); + } + + pos = Restore_Name.find_last_of("/"); + Backup_FileName = Restore_Name.substr(pos + 1, Restore_Name.size()); + pos = Restore_Name.find_last_of("/"); + part_settings.Restore_Name = Restore_Name.substr(0, pos); + part_settings.Part = PartitionManager.Find_Partition_By_Path(path); + + if (path.compare("/system") == 0) { + if (part_settings.Part->Is_Read_Only()) { + struct AdbBackupControlType twerror; + strncpy(twerror.start_of_header, TWRP, sizeof(twerror.start_of_header)); + strncpy(twerror.type, TWERROR, sizeof(twerror.type)); + memset(twerror.space, 0, sizeof(twerror.space)); + twerror.crc = crc32(0L, Z_NULL, 0); + twerror.crc = crc32(twerror.crc, (const unsigned char*) &twerror, sizeof(twerror)); + if (write(adb_control_bu_fd, &twerror, sizeof(twerror)) < 0) { + LOGERR("Cannot write to ADB_CONTROL_BU_FD: %s\n", strerror(errno)); + } + gui_msg(Msg(msg::kError, "restore_read_only=Cannot restore {1} -- mounted read only.")(part_settings.Part->Backup_Display_Name)); + return 1; + + } + } + part_settings.partition_count = partition_count; + part_settings.adbbackup = true; + part_settings.adb_compression = twimghdr.compressed; + part_settings.Backup_FileName = Backup_FileName; + part_settings.total_restore_size += part_settings.Part->Get_Restore_Size(&part_settings); + part_settings.PM_Method = PM_RESTORE; + ProgressTracking progress(part_settings.total_restore_size); + part_settings.progress = &progress; + if (!PartitionManager.Restore_Partition(&part_settings)) { + LOGERR("ADB Restore failed.\n"); + return 1; + } + } + } + } + } + gui_msg("restore_complete=Restore Complete"); + + if (!twadbbu::Write_TWENDADB()) + ret = 1; + sleep(2); //give time for user to see messages on console + return ret; +} + +int OpenRecoveryScript::remountrw(void) +{ + bool remount_system = PartitionManager.Is_Mounted_By_Path("/system"); + int op_status; + TWPartition* Part; + + if (!PartitionManager.UnMount_By_Path("/system", true)) { + op_status = 1; // fail + } else { + Part = PartitionManager.Find_Partition_By_Path("/system"); + if (Part) { + DataManager::SetValue("tw_mount_system_ro", 0); + Part->Change_Mount_Read_Only(false); + } + if (remount_system) { + Part->Mount(true); + } + op_status = 0; // success + } + + return op_status; +} diff --git a/openrecoveryscript.hpp b/openrecoveryscript.hpp index 38311959b..f442746c7 100644 --- a/openrecoveryscript.hpp +++ b/openrecoveryscript.hpp @@ -40,6 +40,9 @@ public: static int Run_OpenRecoveryScript_Action(); // Actually runs the ORS scripts for the GUI action static void Call_After_CLI_Command(VoidFunction fn) { call_after_cli_command = fn; } static void Run_CLI_Command(const char* command); // Runs a command for orscmd (twrp binary) + static int Backup_ADB_Command(string Options); // Runs adbbackup + static int Restore_ADB_Backup(); // Restore adb backup through ors + static int remountrw(); // Remount system and vendor rw }; #endif // _OPENRECOVERYSCRIPT_HPP diff --git a/orscmd/Android.mk b/orscmd/Android.mk index 8ddf93f84..9f18c16a7 100644 --- a/orscmd/Android.mk +++ b/orscmd/Android.mk @@ -3,7 +3,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ orscmd.cpp -LOCAL_CFLAGS:= -g -c -W +LOCAL_CFLAGS:= -c -W LOCAL_MODULE:=orscmd LOCAL_MODULE_STEM := twrp LOCAL_MODULE_TAGS:= eng diff --git a/orscmd/orscmd.cpp b/orscmd/orscmd.cpp index 0240ff9fd..53c5bc030 100644 --- a/orscmd/orscmd.cpp +++ b/orscmd/orscmd.cpp @@ -40,6 +40,7 @@ void print_usage(void) { printf(" set variable value\n"); printf(" get variable\n"); printf(" decrypt password\n"); + printf(" remountrw\n"); printf("\nSee more documentation at http://teamw.in/openrecoveryscript\n"); } diff --git a/partition.cpp b/partition.cpp index 1261a2a26..bf87de38a 100644 --- a/partition.cpp +++ b/partition.cpp @@ -25,6 +25,7 @@ #include <unistd.h> #include <dirent.h> #include <libgen.h> +#include <zlib.h> #include <iostream> #include <sstream> #include <sys/param.h> @@ -46,6 +47,7 @@ #include "infomanager.hpp" #include "set_metadata.h" #include "gui/gui.hpp" +#include "adbbu/libtwadbbu.hpp" extern "C" { #include "mtdutils/mtdutils.h" #include "mtdutils/mounts.h" @@ -208,7 +210,7 @@ TWPartition::TWPartition() { Backup_Name = ""; Backup_FileName = ""; MTD_Name = ""; - Backup_Method = NONE; + Backup_Method = BM_NONE; Can_Encrypt_Backup = false; Use_Userdata_Encryption = false; Has_Data_Media = false; @@ -801,16 +803,16 @@ void TWPartition::Setup_File_System(bool Display_Error) { Make_Dir(Mount_Point, Display_Error); Display_Name = Mount_Point.substr(1, Mount_Point.size() - 1); Backup_Name = Display_Name; - Backup_Method = FILES; + Backup_Method = BM_FILES; } void TWPartition::Setup_Image(bool Display_Error) { Display_Name = Mount_Point.substr(1, Mount_Point.size() - 1); Backup_Name = Display_Name; if (Current_File_System == "emmc") - Backup_Method = DD; + Backup_Method = BM_DD; else if (Current_File_System == "mtd" || Current_File_System == "bml") - Backup_Method = FLASH_UTILS; + Backup_Method = BM_FLASH_UTILS; else LOGINFO("Unhandled file system '%s' on image '%s'\n", Current_File_System.c_str(), Display_Name.c_str()); if (Find_Partition_Size()) { @@ -1598,14 +1600,13 @@ bool TWPartition::Resize() { return false; } -bool TWPartition::Backup(const string& backup_folder, pid_t &tar_fork_pid, ProgressTracking *progress) { - if (Backup_Method == FILES) { - return Backup_Tar(backup_folder, progress, tar_fork_pid); - } - else if (Backup_Method == DD) - return Backup_Image(backup_folder, progress); - else if (Backup_Method == FLASH_UTILS) - return Backup_Dump_Image(backup_folder, progress); +bool TWPartition::Backup(PartitionSettings *part_settings, pid_t *tar_fork_pid) { + if (Backup_Method == BM_FILES) + return Backup_Tar(part_settings, tar_fork_pid); + else if (Backup_Method == BM_DD) + return Backup_Image(part_settings); + else if (Backup_Method == BM_FLASH_UTILS) + return Backup_Dump_Image(part_settings); LOGERR("Unknown backup method for '%s'\n", Mount_Point.c_str()); return false; } @@ -1658,53 +1659,49 @@ bool TWPartition::Check_MD5(string restore_folder) { return false; } -bool TWPartition::Restore(const string& restore_folder, ProgressTracking *progress) { - string Restore_File_System; - +bool TWPartition::Restore(PartitionSettings *part_settings) { TWFunc::GUI_Operation_Text(TW_RESTORE_TEXT, Display_Name, gui_parse_text("{@restoring_hdr}")); - LOGINFO("Restore filename is: %s\n", Backup_FileName.c_str()); + LOGINFO("Restore filename is: %s/%s\n", part_settings->Restore_Name.c_str(), part_settings->Backup_FileName.c_str()); - Restore_File_System = Get_Restore_File_System(restore_folder); + string Restore_File_System = Get_Restore_File_System(part_settings); if (Is_File_System(Restore_File_System)) - return Restore_Tar(restore_folder, Restore_File_System, progress); - else if (Is_Image(Restore_File_System)) { - return Restore_Image(restore_folder, Restore_File_System, progress); - } + return Restore_Tar(part_settings); + else if (Is_Image(Restore_File_System)) + return Restore_Image(part_settings); LOGERR("Unknown restore method for '%s'\n", Mount_Point.c_str()); return false; } -string TWPartition::Get_Restore_File_System(const string& restore_folder) { +string TWPartition::Get_Restore_File_System(PartitionSettings *part_settings) { size_t first_period, second_period; string Restore_File_System; // Parse backup filename to extract the file system before wiping - first_period = Backup_FileName.find("."); + first_period = part_settings->Backup_FileName.find("."); if (first_period == string::npos) { LOGERR("Unable to find file system (first period).\n"); return string(); } - Restore_File_System = Backup_FileName.substr(first_period + 1, Backup_FileName.size() - first_period - 1); + Restore_File_System = part_settings->Backup_FileName.substr(first_period + 1, part_settings->Backup_FileName.size() - first_period - 1); second_period = Restore_File_System.find("."); if (second_period == string::npos) { LOGERR("Unable to find file system (second period).\n"); return string(); } Restore_File_System.resize(second_period); - LOGINFO("Restore file system is: '%s'.\n", Restore_File_System.c_str()); return Restore_File_System; } string TWPartition::Backup_Method_By_Name() { - if (Backup_Method == NONE) + if (Backup_Method == BM_NONE) return "none"; - else if (Backup_Method == FILES) + else if (Backup_Method == BM_FILES) return "files"; - else if (Backup_Method == DD) + else if (Backup_Method == BM_DD) return "dd"; - else if (Backup_Method == FLASH_UTILS) + else if (Backup_Method == BM_FLASH_UTILS) return "flash_utils"; else return "undefined"; @@ -2141,7 +2138,7 @@ bool TWPartition::Wipe_Data_Without_Wiping_Media_Func(const string& parent __unu return false; } -bool TWPartition::Backup_Tar(const string& backup_folder, ProgressTracking *progress, pid_t &tar_fork_pid) { +bool TWPartition::Backup_Tar(PartitionSettings *part_settings, pid_t *tar_fork_pid) { string Full_FileName; twrpTar tar; @@ -2169,72 +2166,114 @@ bool TWPartition::Backup_Tar(const string& backup_folder, ProgressTracking *prog #endif Backup_FileName = Backup_Name + "." + Current_File_System + ".win"; - Full_FileName = backup_folder + "/" + Backup_FileName; + Full_FileName = part_settings->Full_Backup_Path + Backup_FileName; tar.has_data_media = Has_Data_Media; - Full_FileName = backup_folder + "/" + Backup_FileName; + tar.part_settings = part_settings; tar.setdir(Backup_Path); tar.setfn(Full_FileName); tar.setsize(Backup_Size); tar.partition_name = Backup_Name; - tar.backup_folder = backup_folder; - if (tar.createTarFork(progress, tar_fork_pid) != 0) + tar.backup_folder = part_settings->Full_Backup_Path; + if (tar.createTarFork(tar_fork_pid) != 0) return false; return true; } -bool TWPartition::Backup_Image(const string& backup_folder, ProgressTracking *progress) { - string Full_FileName; +bool TWPartition::Backup_Image(PartitionSettings *part_settings) { + string Full_FileName, adb_file_name; + int adb_control_bu_fd, compressed; TWFunc::GUI_Operation_Text(TW_BACKUP_TEXT, Display_Name, gui_parse_text("{@backing}")); gui_msg(Msg("backing_up=Backing up {1}...")(Backup_Display_Name)); Backup_FileName = Backup_Name + "." + Current_File_System + ".win"; - Full_FileName = backup_folder + "/" + Backup_FileName; - if (!Raw_Read_Write(Actual_Block_Device, Full_FileName, Backup_Size, progress)) - return false; + if (part_settings->adbbackup) { + Full_FileName = TW_ADB_BACKUP; + adb_file_name = part_settings->Full_Backup_Path + "/" + Backup_FileName; + } + else + Full_FileName = part_settings->Full_Backup_Path + "/" + Backup_FileName; - tw_set_default_metadata(Full_FileName.c_str()); - if (TWFunc::Get_File_Size(Full_FileName) == 0) { - gui_msg(Msg(msg::kError, "backup_size=Backup file size for '{1}' is 0 bytes.")(Full_FileName)); + part_settings->total_restore_size = Backup_Size; + + if (part_settings->adbbackup) { + if (!twadbbu::Write_TWIMG(adb_file_name, Backup_Size)) + return false; + } + + if (!Raw_Read_Write(part_settings)) return false; + + if (part_settings->adbbackup) { + if (!twadbbu::Write_TWEOF()) + return false; } return true; } -bool TWPartition::Raw_Read_Write(const string& input_file, const string& output_file, const unsigned long long input_size, ProgressTracking *progress) { - unsigned long long RW_Block_Size, Remain; - int src_fd = -1, dest_fd = -1, bs; +bool TWPartition::Raw_Read_Write(PartitionSettings *part_settings) { + unsigned long long RW_Block_Size, Remain = Backup_Size; + int src_fd = -1, dest_fd = -1; + ssize_t bs; bool ret = false; void* buffer = NULL; unsigned long long backedup_size = 0; + string srcfn, destfn; - RW_Block_Size = 1048576LLU; // 1MB - Remain = input_size; + if (part_settings->PM_Method == PM_BACKUP) { + srcfn = Actual_Block_Device; + if (part_settings->adbbackup) + destfn = TW_ADB_BACKUP; + else + destfn = part_settings->Full_Backup_Path + part_settings->Backup_FileName; + } + else { + destfn = Actual_Block_Device; + if (part_settings->adbbackup) { + srcfn = TW_ADB_RESTORE; + } else { + srcfn = part_settings->Restore_Name + "/" + part_settings->Backup_FileName; + Remain = TWFunc::Get_File_Size(srcfn); + } + } - src_fd = open(input_file.c_str(), O_RDONLY | O_LARGEFILE); + src_fd = open(srcfn.c_str(), O_RDONLY | O_LARGEFILE); if (src_fd < 0) { - gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(input_file)(strerror(errno))); + gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(srcfn.c_str())(strerror(errno))); return false; } - dest_fd = open(output_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE, S_IRUSR | S_IWUSR); + + dest_fd = open(destfn.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE, S_IRUSR | S_IWUSR); if (dest_fd < 0) { - gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(output_file)(strerror(errno))); + gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(destfn.c_str())(strerror(errno))); goto exit; } - bs = (int)(RW_Block_Size); + + LOGINFO("Reading '%s', writing '%s'\n", srcfn.c_str(), destfn.c_str()); + + if (part_settings->adbbackup) { + RW_Block_Size = MAX_ADB_READ; + bs = MAX_ADB_READ; + } + else { + RW_Block_Size = 1048576LLU; // 1MB + bs = (ssize_t)(RW_Block_Size); + } + buffer = malloc((size_t)bs); if (!buffer) { LOGINFO("Raw_Read_Write failed to malloc\n"); goto exit; } - LOGINFO("Reading '%s', writing '%s'\n", input_file.c_str(), output_file.c_str()); - if (progress) - progress->SetPartitionSize(input_size); + + if (part_settings->progress) + part_settings->progress->SetPartitionSize(part_settings->total_restore_size); + while (Remain > 0) { if (Remain < RW_Block_Size) - bs = (int)(Remain); - if (read(src_fd, buffer, bs) != bs) { + bs = (ssize_t)(Remain); + if (read(src_fd, buffer, bs) != bs) { LOGINFO("Error reading source fd (%s)\n", strerror(errno)); goto exit; } @@ -2243,14 +2282,14 @@ bool TWPartition::Raw_Read_Write(const string& input_file, const string& output_ goto exit; } backedup_size += (unsigned long long)(bs); - Remain -= (unsigned long long)(bs); - if (progress) - progress->UpdateSize(backedup_size); + Remain = Remain - (unsigned long long)(bs); + if (part_settings->progress) + part_settings->progress->UpdateSize(backedup_size); if (PartitionManager.Check_Backup_Cancel() != 0) goto exit; } - if (progress) - progress->UpdateDisplayDetails(true); + if (part_settings->progress) + part_settings->progress->UpdateDisplayDetails(true); fsync(dest_fd); ret = true; exit: @@ -2263,19 +2302,22 @@ exit: return ret; } -bool TWPartition::Backup_Dump_Image(const string& backup_folder, ProgressTracking *progress) { +bool TWPartition::Backup_Dump_Image(PartitionSettings *part_settings) { string Full_FileName, Command; + int use_compression, adb_control_bu_fd; + unsigned long long compressed; TWFunc::GUI_Operation_Text(TW_BACKUP_TEXT, Display_Name, gui_parse_text("{@backing}")); gui_msg(Msg("backing_up=Backing up {1}...")(Backup_Display_Name)); - if (progress) - progress->SetPartitionSize(Backup_Size); + if (part_settings->progress) + part_settings->progress->SetPartitionSize(Backup_Size); Backup_FileName = Backup_Name + "." + Current_File_System + ".win"; - Full_FileName = backup_folder + "/" + Backup_FileName; + Full_FileName = part_settings->Full_Backup_Path + "/" + Backup_FileName; Command = "dump_image " + MTD_Name + " '" + Full_FileName + "'"; + LOGINFO("Backup command: '%s'\n", Command.c_str()); TWFunc::Exec_Cmd(Command); tw_set_default_metadata(Full_FileName.c_str()); @@ -2284,23 +2326,26 @@ bool TWPartition::Backup_Dump_Image(const string& backup_folder, ProgressTrackin gui_msg(Msg(msg::kError, "backup_size=Backup file size for '{1}' is 0 bytes.")(Full_FileName)); return false; } - if (progress) - progress->UpdateSize(Backup_Size); + if (part_settings->progress) + part_settings->progress->UpdateSize(Backup_Size); + return true; } -unsigned long long TWPartition::Get_Restore_Size(const string& restore_folder) { - InfoManager restore_info(restore_folder + "/" + Backup_Name + ".info"); - if (restore_info.LoadValues() == 0) { - if (restore_info.GetValue("backup_size", Restore_Size) == 0) { - LOGINFO("Read info file, restore size is %llu\n", Restore_Size); - return Restore_Size; +unsigned long long TWPartition::Get_Restore_Size(PartitionSettings *part_settings) { + if (!part_settings->adbbackup) { + InfoManager restore_info(part_settings->Restore_Name + "/" + Backup_Name + ".info"); + if (restore_info.LoadValues() == 0) { + if (restore_info.GetValue("backup_size", Restore_Size) == 0) { + LOGINFO("Read info file, restore size is %llu\n", Restore_Size); + return Restore_Size; + } } } - string Full_FileName, Restore_File_System = Get_Restore_File_System(restore_folder); - Full_FileName = restore_folder + "/" + Backup_FileName; + string Full_FileName, Restore_File_System = Get_Restore_File_System(part_settings); + Full_FileName = part_settings->Restore_Name + "/" + Backup_FileName; if (Is_Image(Restore_File_System)) { Restore_Size = TWFunc::Get_File_Size(Full_FileName); return Restore_Size; @@ -2309,7 +2354,7 @@ unsigned long long TWPartition::Get_Restore_Size(const string& restore_folder) { twrpTar tar; tar.setdir(Backup_Path); tar.setfn(Full_FileName); - tar.backup_name = Backup_Name; + tar.backup_name = Full_FileName; #ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS string Password; DataManager::GetValue("tw_restore_password", Password); @@ -2317,14 +2362,16 @@ unsigned long long TWPartition::Get_Restore_Size(const string& restore_folder) { tar.setpassword(Password); #endif tar.partition_name = Backup_Name; - tar.backup_folder = restore_folder; + tar.backup_folder = part_settings->Restore_Name; + tar.part_settings = part_settings; Restore_Size = tar.get_size(); return Restore_Size; } -bool TWPartition::Restore_Tar(const string& restore_folder, const string& Restore_File_System, ProgressTracking *progress) { +bool TWPartition::Restore_Tar(PartitionSettings *part_settings) { string Full_FileName; bool ret = false; + string Restore_File_System = Get_Restore_File_System(part_settings); if (Has_Android_Secure) { if (!Wipe_AndSec()) @@ -2347,8 +2394,9 @@ bool TWPartition::Restore_Tar(const string& restore_folder, const string& Restor if (!ReMount_RW(true)) return false; - Full_FileName = restore_folder + "/" + Backup_FileName; + Full_FileName = part_settings->Restore_Name + "/" + part_settings->Backup_FileName; twrpTar tar; + tar.part_settings = part_settings; tar.setdir(Backup_Path); tar.setfn(Full_FileName); tar.backup_name = Backup_Name; @@ -2358,8 +2406,8 @@ bool TWPartition::Restore_Tar(const string& restore_folder, const string& Restor if (!Password.empty()) tar.setpassword(Password); #endif - progress->SetPartitionSize(Get_Restore_Size(restore_folder)); - if (tar.extractTarFork(progress) != 0) + part_settings->progress->SetPartitionSize(Get_Restore_Size(part_settings)); + if (tar.extractTarFork() != 0) ret = false; else ret = true; @@ -2389,19 +2437,30 @@ bool TWPartition::Restore_Tar(const string& restore_folder, const string& Restor return ret; } -bool TWPartition::Restore_Image(const string& restore_folder, const string& Restore_File_System, ProgressTracking *progress) { +bool TWPartition::Restore_Image(PartitionSettings *part_settings) { string Full_FileName; + string Restore_File_System = Get_Restore_File_System(part_settings); TWFunc::GUI_Operation_Text(TW_RESTORE_TEXT, Backup_Display_Name, gui_parse_text("{@restoring_hdr}")); gui_msg(Msg("restoring=Restoring {1}...")(Backup_Display_Name)); - Full_FileName = restore_folder + "/" + Backup_FileName; + + if (part_settings->adbbackup) + Full_FileName = TW_ADB_RESTORE; + else + Full_FileName = part_settings->Full_Backup_Path + part_settings->Backup_FileName; if (Restore_File_System == "emmc") { - unsigned long long file_size = (unsigned long long)(TWFunc::Get_File_Size(Full_FileName)); - if (!Raw_Read_Write(Full_FileName, Actual_Block_Device, file_size, progress)) + if (!part_settings->adbbackup) + part_settings->total_restore_size = (uint64_t)(TWFunc::Get_File_Size(Full_FileName)); + if (!Raw_Read_Write(part_settings)) return false; } else if (Restore_File_System == "mtd" || Restore_File_System == "bml") { - if (!Flash_Image_FI(Full_FileName, progress)) + if (!Flash_Image_FI(Full_FileName, part_settings->progress)) + return false; + } + + if (part_settings->adbbackup) { + if (!twadbbu::Write_TWEOF()) return false; } return true; @@ -2544,12 +2603,14 @@ uint64_t TWPartition::Get_Max_FileSize() { return maxFileSize - 1; } -bool TWPartition::Flash_Image(const string& Filename) { - string Restore_File_System; +bool TWPartition::Flash_Image(PartitionSettings *part_settings) { + string Restore_File_System, full_filename; + + full_filename = part_settings->Restore_Name + "/" + part_settings->Backup_FileName; - LOGINFO("Image filename is: %s\n", Filename.c_str()); + LOGINFO("Image filename is: %s\n", part_settings->Backup_FileName.c_str()); - if (Backup_Method == FILES) { + if (Backup_Method == BM_FILES) { LOGERR("Cannot flash images to file systems\n"); return false; } else if (!Can_Flash_Img) { @@ -2560,22 +2621,23 @@ bool TWPartition::Flash_Image(const string& Filename) { LOGERR("Unable to find partition size for '%s'\n", Mount_Point.c_str()); return false; } - unsigned long long image_size = TWFunc::Get_File_Size(Filename); + unsigned long long image_size = TWFunc::Get_File_Size(full_filename); if (image_size > Size) { LOGINFO("Size (%llu bytes) of image '%s' is larger than target device '%s' (%llu bytes)\n", - image_size, Filename.c_str(), Actual_Block_Device.c_str(), Size); + image_size, part_settings->Backup_FileName.c_str(), Actual_Block_Device.c_str(), Size); gui_err("img_size_err=Size of image is larger than target device"); return false; } - if (Backup_Method == DD) { - if (Is_Sparse_Image(Filename)) { - return Flash_Sparse_Image(Filename); + if (Backup_Method == BM_DD) { + if (!part_settings->adbbackup) { + if (Is_Sparse_Image(full_filename)) { + return Flash_Sparse_Image(full_filename); + } } - unsigned long long file_size = (unsigned long long)(TWFunc::Get_File_Size(Filename)); - ProgressTracking pt(file_size); - return Raw_Read_Write(Filename, Actual_Block_Device, file_size, &pt); - } else if (Backup_Method == FLASH_UTILS) { - return Flash_Image_FI(Filename, NULL); + unsigned long long file_size = (unsigned long long)(TWFunc::Get_File_Size(full_filename)); + return Raw_Read_Write(part_settings); + } else if (Backup_Method == BM_FLASH_UTILS) { + return Flash_Image_FI(full_filename, NULL); } } @@ -2590,6 +2652,7 @@ bool TWPartition::Is_Sparse_Image(const string& Filename) { gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(Filename)(strerror(errno))); return false; } + if (read(fd, &magic, sizeof(magic)) != sizeof(magic)) { gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(Filename)(strerror(errno))); close(fd); @@ -2637,6 +2700,10 @@ void TWPartition::Change_Mount_Read_Only(bool new_value) { Mount_Read_Only = new_value; } +bool TWPartition::Is_Read_Only() { + return Mount_Read_Only; +} + int TWPartition::Check_Lifetime_Writes() { bool original_read_only = Mount_Read_Only; int ret = 1; diff --git a/partitionmanager.cpp b/partitionmanager.cpp index 320944c3f..96e30025e 100644 --- a/partitionmanager.cpp +++ b/partitionmanager.cpp @@ -27,6 +27,7 @@ #include <time.h> #include <errno.h> #include <fcntl.h> +#include <zlib.h> #include <iostream> #include <iomanip> #include <sys/wait.h> @@ -44,6 +45,7 @@ #include "tw_atomic.hpp" #include "gui/gui.hpp" #include "progresstracking.hpp" +#include "adbbu/libtwadbbu.hpp" #ifdef TW_HAS_MTP #include "mtp/mtp_MtpServer.hpp" @@ -68,7 +70,6 @@ TWPartitionManager::TWPartitionManager(void) { mtp_was_enabled = false; mtp_write_fd = -1; stop_backup.set_value(0); - tar_fork_pid = 0; } int TWPartitionManager::Process_Fstab(string Fstab_Filename, bool Display_Error) { @@ -472,6 +473,7 @@ int TWPartitionManager::Check_Backup_Name(bool Display_Error) { if (TWFunc::Path_Exists(tw_image_dir)) { if (Display_Error) gui_err("backup_name_exists=A backup with that name already exists!"); + return -4; } // No problems found, return 0 @@ -481,7 +483,7 @@ int TWPartitionManager::Check_Backup_Name(bool Display_Error) { bool TWPartitionManager::Make_MD5(bool generate_md5, string Backup_Folder, string Backup_Filename) { string command; - string Full_File = Backup_Folder + Backup_Filename; + string Full_File = Backup_Folder + "/" + Backup_Filename; string result; twrpDigest md5sum; @@ -490,9 +492,8 @@ bool TWPartitionManager::Make_MD5(bool generate_md5, string Backup_Folder, strin TWFunc::GUI_Operation_Text(TW_GENERATE_MD5_TEXT, gui_parse_text("{@generating_md51}")); gui_msg("generating_md52= * Generating md5..."); - if (TWFunc::Path_Exists(Full_File)) { - md5sum.setfn(Backup_Folder + Backup_Filename); + md5sum.setfn(Full_File); if (md5sum.computeMD5() == 0) if (md5sum.write_md5digest() == 0) gui_msg("md5_created= * MD5 Created."); @@ -533,13 +534,13 @@ bool TWPartitionManager::Make_MD5(bool generate_md5, string Backup_Folder, strin return true; } -bool TWPartitionManager::Backup_Partition(TWPartition* Part, const string& Backup_Folder, bool generate_md5, unsigned long *img_time, unsigned long *file_time, ProgressTracking *progress) { - time_t start, stop; - int use_compression; - string backup_log = Backup_Folder + "recovery.log"; +bool TWPartitionManager::Backup_Partition(PartitionSettings *part_settings) { + time_t start, stop; + int use_compression, adb_control_bu_fd; + string backup_log = part_settings->Backup_Folder + "/recovery.log"; - if (Part == NULL) + if (part_settings->Part == NULL) return true; DataManager::GetValue(TW_USE_COMPRESSION_VAR, use_compression); @@ -547,25 +548,28 @@ bool TWPartitionManager::Backup_Partition(TWPartition* Part, const string& Backu TWFunc::SetPerformanceMode(true); time(&start); - if (Part->Backup(Backup_Folder, tar_fork_pid, progress)) { + part_settings->Backup_FileName = part_settings->Part->Backup_Name + "." + part_settings->Part->Current_File_System + ".win"; + if (part_settings->Part->Backup(part_settings, &tar_fork_pid)) { bool md5Success = false; - if (Part->Has_SubPartition) { + if (part_settings->Part->Has_SubPartition) { std::vector<TWPartition*>::iterator subpart; for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) { - if ((*subpart)->Can_Be_Backed_Up && (*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point) { - if (!(*subpart)->Backup(Backup_Folder, tar_fork_pid, progress)) { + if ((*subpart)->Can_Be_Backed_Up && (*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == part_settings->Part->Mount_Point) { + if (!(*subpart)->Backup(part_settings, &tar_fork_pid)) { TWFunc::SetPerformanceMode(false); - Clean_Backup_Folder(Backup_Folder); + Clean_Backup_Folder(part_settings->Backup_Folder); TWFunc::copy_file("/tmp/recovery.log", backup_log, 0644); tw_set_default_metadata(backup_log.c_str()); return false; } sync(); sync(); - if (!Make_MD5(generate_md5, Backup_Folder, (*subpart)->Backup_FileName)) { - TWFunc::SetPerformanceMode(false); - return false; + if (!part_settings->adbbackup) { + if (!Make_MD5(part_settings->generate_md5, part_settings->Backup_Folder, (*subpart)->Backup_FileName)) { + TWFunc::SetPerformanceMode(false); + return false; + } } } } @@ -573,17 +577,23 @@ bool TWPartitionManager::Backup_Partition(TWPartition* Part, const string& Backu time(&stop); int backup_time = (int) difftime(stop, start); LOGINFO("Partition Backup time: %d\n", backup_time); - if (Part->Backup_Method == 1) { - *file_time += backup_time; + if (part_settings->Part->Backup_Method == BM_FILES) { + part_settings->file_time += backup_time; } else { - *img_time += backup_time; + part_settings->img_time += backup_time; + } - md5Success = Make_MD5(generate_md5, Backup_Folder, Part->Backup_FileName); + if (!part_settings->adbbackup) { + md5Success = Make_MD5(part_settings->generate_md5, part_settings->Backup_Folder, part_settings->Part->Backup_FileName); + } + else + md5Success = true; TWFunc::SetPerformanceMode(false); + return md5Success; } else { - Clean_Backup_Folder(Backup_Folder); + Clean_Backup_Folder(part_settings->Backup_Folder); TWFunc::copy_file("/tmp/recovery.log", backup_log, 0644); tw_set_default_metadata(backup_log.c_str()); TWFunc::SetPerformanceMode(false); @@ -648,12 +658,12 @@ int TWPartitionManager::Cancel_Backup() { return 0; } -int TWPartitionManager::Run_Backup(void) { - int check, do_md5, partition_count = 0, disable_free_space_check = 0; - string Backup_Folder, Backup_Name, Full_Backup_Path, Backup_List, backup_path; - unsigned long long total_bytes = 0, file_bytes = 0, img_bytes = 0, free_space = 0, img_bytes_remaining, file_bytes_remaining, subpart_size; - unsigned long img_time = 0, file_time = 0; - TWPartition* backup_part = NULL; +int TWPartitionManager::Run_Backup(bool adbbackup) { + PartitionSettings part_settings; + int check, partition_count = 0, disable_free_space_check = 0, do_md5 = 0; + int gui_adb_backup; + string Backup_Name, Backup_List, backup_path; + unsigned long long total_bytes = 0, free_space = 0, subpart_size; TWPartition* storage = NULL; std::vector<TWPartition*>::iterator subpart; struct tm *t; @@ -663,6 +673,19 @@ int TWPartitionManager::Run_Backup(void) { seconds = time(0); t = localtime(&seconds); + part_settings.img_bytes_remaining = 0; + part_settings.file_bytes_remaining = 0; + part_settings.img_time = 0; + part_settings.file_time = 0; + part_settings.img_bytes = 0; + part_settings.file_bytes = 0; + part_settings.PM_Method = PM_BACKUP; + + DataManager::GetValue("tw_enable_adb_backup", gui_adb_backup); + if (gui_adb_backup == true) + adbbackup = true; + + part_settings.adbbackup = adbbackup; time(&total_start); Update_System_Details(); @@ -670,23 +693,26 @@ int TWPartitionManager::Run_Backup(void) { if (!Mount_Current_Storage(true)) return false; + DataManager::GetValue(TW_SKIP_MD5_GENERATE_VAR, do_md5); if (do_md5 == 0) - do_md5 = true; + part_settings.generate_md5 = true; else - do_md5 = false; + part_settings.generate_md5 = false; - DataManager::GetValue(TW_BACKUPS_FOLDER_VAR, Backup_Folder); - DataManager::GetValue(TW_BACKUP_NAME, Backup_Name); - if (Backup_Name == gui_lookup("curr_date", "(Current Date)")) { - Backup_Name = TWFunc::Get_Current_Date(); - } else if (Backup_Name == gui_lookup("auto_generate", "(Auto Generate)") || Backup_Name == "0" || Backup_Name.empty()) { + DataManager::GetValue(TW_BACKUPS_FOLDER_VAR, part_settings.Backup_Folder); + DataManager::GetValue(TW_BACKUP_NAME, part_settings.Backup_Name); + if (part_settings.Backup_Name == gui_lookup("curr_date", "(Current Date)")) { + part_settings.Backup_Name = TWFunc::Get_Current_Date(); + } else if (part_settings.Backup_Name == gui_lookup("auto_generate", "(Auto Generate)") || part_settings.Backup_Name == "0" || part_settings.Backup_Name.empty()) { TWFunc::Auto_Generate_Backup_Name(); - DataManager::GetValue(TW_BACKUP_NAME, Backup_Name); + DataManager::GetValue(TW_BACKUP_NAME, part_settings.Backup_Name); } - LOGINFO("Backup Name is: '%s'\n", Backup_Name.c_str()); - Full_Backup_Path = Backup_Folder + "/" + Backup_Name + "/"; - LOGINFO("Full_Backup_Path is: '%s'\n", Full_Backup_Path.c_str()); + + LOGINFO("Backup Name is: '%s'\n", part_settings.Backup_Name.c_str()); + part_settings.Full_Backup_Path = part_settings.Backup_Folder + "/" + part_settings.Backup_Name + "/"; + + LOGINFO("Full_Backup_Path is: '%s'\n", part_settings.Full_Backup_Path.c_str()); LOGINFO("Calculating backup details...\n"); DataManager::GetValue("tw_backup_list", Backup_List); @@ -694,23 +720,23 @@ int TWPartitionManager::Run_Backup(void) { end_pos = Backup_List.find(";", start_pos); while (end_pos != string::npos && start_pos < Backup_List.size()) { backup_path = Backup_List.substr(start_pos, end_pos - start_pos); - backup_part = Find_Partition_By_Path(backup_path); - if (backup_part != NULL) { + part_settings.Part = Find_Partition_By_Path(backup_path); + if (part_settings.Part != NULL) { partition_count++; - if (backup_part->Backup_Method == 1) - file_bytes += backup_part->Backup_Size; + if (part_settings.Part->Backup_Method == BM_FILES) + part_settings.file_bytes += part_settings.Part->Backup_Size; else - img_bytes += backup_part->Backup_Size; - if (backup_part->Has_SubPartition) { + part_settings.img_bytes += part_settings.Part->Backup_Size; + if (part_settings.Part->Has_SubPartition) { std::vector<TWPartition*>::iterator subpart; for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) { - if ((*subpart)->Can_Be_Backed_Up && (*subpart)->Is_Present && (*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == backup_part->Mount_Point) { + if ((*subpart)->Can_Be_Backed_Up && (*subpart)->Is_Present && (*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == part_settings.Part->Mount_Point) { partition_count++; - if ((*subpart)->Backup_Method == 1) - file_bytes += (*subpart)->Backup_Size; + if ((*subpart)->Backup_Method == BM_FILES) + part_settings.file_bytes += (*subpart)->Backup_Size; else - img_bytes += (*subpart)->Backup_Size; + part_settings.img_bytes += (*subpart)->Backup_Size; } } } @@ -726,8 +752,15 @@ int TWPartitionManager::Run_Backup(void) { gui_msg("no_partition_selected=No partitions selected for backup."); return false; } - total_bytes = file_bytes + img_bytes; + if (adbbackup) { + if (twadbbu::Write_ADB_Stream_Header(partition_count) == false) { + return false; + } + } + total_bytes = part_settings.file_bytes + part_settings.img_bytes; ProgressTracking progress(total_bytes); + part_settings.progress = &progress; + gui_msg(Msg("total_partitions_backup= * Total number of partitions to back up: {1}")(partition_count)); gui_msg(Msg("total_backup_size= * Total size of all data: {1}MB")(total_bytes / 1024 / 1024)); storage = Find_Partition_By_Path(DataManager::GetCurrentStoragePath()); @@ -740,6 +773,10 @@ int TWPartitionManager::Run_Backup(void) { } DataManager::GetValue("tw_disable_free_space", disable_free_space_check); + + if (adbbackup) + disable_free_space_check = true; + if (!disable_free_space_check) { if (free_space - (32 * 1024 * 1024) < total_bytes) { // We require an extra 32MB just in case @@ -747,12 +784,12 @@ int TWPartitionManager::Run_Backup(void) { return false; } } - img_bytes_remaining = img_bytes; - file_bytes_remaining = file_bytes; + part_settings.img_bytes_remaining = part_settings.img_bytes; + part_settings.file_bytes_remaining = part_settings.file_bytes; gui_msg("backup_started=[BACKUP STARTED]"); - gui_msg(Msg("backup_folder= * Backup Folder: {1}")(Full_Backup_Path)); - if (!TWFunc::Recursive_Mkdir(Full_Backup_Path)) { + gui_msg(Msg("backup_folder= * Backup Folder: {1}")(part_settings.Full_Backup_Path)); + if (!TWFunc::Recursive_Mkdir(part_settings.Full_Backup_Path)) { gui_err("fail_backup_folder=Failed to make backup folder."); return false; } @@ -765,9 +802,10 @@ int TWPartitionManager::Run_Backup(void) { if (stop_backup.get_value() != 0) return -1; backup_path = Backup_List.substr(start_pos, end_pos - start_pos); - backup_part = Find_Partition_By_Path(backup_path); - if (backup_part != NULL) { - if (!Backup_Partition(backup_part, Full_Backup_Path, do_md5, &img_time, &file_time, &progress)) + part_settings.Part = Find_Partition_By_Path(backup_path); + if (part_settings.Part != NULL) { + if (!Backup_Partition(&part_settings)) + return false; } else { gui_msg(Msg(msg::kError, "unable_to_locate_partition=Unable to locate '{1}' partition for backup calculations.")(backup_path)); @@ -777,26 +815,30 @@ int TWPartitionManager::Run_Backup(void) { } // Average BPS - if (img_time == 0) - img_time = 1; - if (file_time == 0) - file_time = 1; - int img_bps = (int)img_bytes / (int)img_time; - unsigned long long file_bps = file_bytes / (int)file_time; - - if (file_bytes != 0) + if (part_settings.img_time == 0) + part_settings.img_time = 1; + if (part_settings.file_time == 0) + part_settings.file_time = 1; + int img_bps = (int)part_settings.img_bytes / (int)part_settings.img_time; + unsigned long long file_bps = part_settings.file_bytes / (int)part_settings.file_time; + + if (part_settings.file_bytes != 0) gui_msg(Msg("avg_backup_fs=Average backup rate for file systems: {1} MB/sec")(file_bps / (1024 * 1024))); - if (img_bytes != 0) + if (part_settings.img_bytes != 0) gui_msg(Msg("avg_backup_img=Average backup rate for imaged drives: {1} MB/sec")(img_bps / (1024 * 1024))); time(&total_stop); int total_time = (int) difftime(total_stop, total_start); - uint64_t actual_backup_size = du.Get_Folder_Size(Full_Backup_Path); + + uint64_t actual_backup_size; + if (!adbbackup) + actual_backup_size = du.Get_Folder_Size(part_settings.Full_Backup_Path); + else + actual_backup_size = part_settings.file_bytes + part_settings.img_bytes; actual_backup_size /= (1024LLU * 1024LLU); - int prev_img_bps, use_compression; - unsigned long long prev_file_bps; - DataManager::GetValue(TW_BACKUP_AVG_IMG_RATE, prev_img_bps); + int prev_img_bps = 0, use_compression = 0; + unsigned long long prev_file_bps = 0; img_bps += (prev_img_bps * 4); img_bps /= 5; @@ -818,27 +860,40 @@ int TWPartitionManager::Run_Backup(void) { Update_System_Details(); UnMount_Main_Partitions(); gui_msg(Msg(msg::kHighlight, "backup_completed=[BACKUP COMPLETED IN {1} SECONDS]")(total_time)); // the end - string backup_log = Full_Backup_Path + "recovery.log"; + string backup_log = part_settings.Full_Backup_Path + "recovery.log"; TWFunc::copy_file("/tmp/recovery.log", backup_log, 0644); tw_set_default_metadata(backup_log.c_str()); + + if (part_settings.adbbackup) { + if (twadbbu::Write_ADB_Stream_Trailer() == false) { + return false; + } + } + part_settings.adbbackup = false; + DataManager::SetValue("tw_enable_adb_backup", 0); + return true; } -bool TWPartitionManager::Restore_Partition(TWPartition* Part, const string& Restore_Name, ProgressTracking *progress) { +bool TWPartitionManager::Restore_Partition(PartitionSettings *part_settings) { time_t Start, Stop; + TWFunc::SetPerformanceMode(true); + time(&Start); - if (!Part->Restore(Restore_Name, progress)) { + + if (!part_settings->Part->Restore(part_settings)) { TWFunc::SetPerformanceMode(false); return false; } - if (Part->Has_SubPartition) { + if (part_settings->Part->Has_SubPartition) { std::vector<TWPartition*>::iterator subpart; for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) { - if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point) { - if (!(*subpart)->Restore(Restore_Name, progress)) { + + if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == part_settings->Part->Mount_Point) { + if (!(*subpart)->Restore(part_settings)) { TWFunc::SetPerformanceMode(false); return false; } @@ -847,18 +902,27 @@ bool TWPartitionManager::Restore_Partition(TWPartition* Part, const string& Rest } time(&Stop); TWFunc::SetPerformanceMode(false); - gui_msg(Msg("restore_part_done=[{1} done ({2} seconds)]")(Part->Backup_Display_Name)((int)difftime(Stop, Start))); + gui_msg(Msg("restore_part_done=[{1} done ({2} seconds)]")(part_settings->Part->Backup_Display_Name)((int)difftime(Stop, Start))); + return true; } int TWPartitionManager::Run_Restore(const string& Restore_Name) { + PartitionSettings part_settings; int check_md5, check, partition_count = 0; TWPartition* restore_part = NULL; + time_t rStart, rStop; time(&rStart); string Restore_List, restore_path; size_t start_pos = 0, end_pos; - unsigned long long total_restore_size = 0, already_restored_size = 0; + + part_settings.Restore_Name = Restore_Name; + part_settings.Part = NULL; + part_settings.partition_count = 0; + part_settings.total_restore_size = 0; + part_settings.adbbackup = false; + part_settings.PM_Method = PM_RESTORE; gui_msg("restore_started=[RESTORE STARTED]"); gui_msg(Msg("restore_folder=Restore folder: '{1}'")(Restore_Name)); @@ -876,28 +940,31 @@ int TWPartitionManager::Run_Restore(const string& Restore_Name) { } gui_msg("calc_restore=Calculating restore details..."); DataManager::GetValue("tw_restore_selected", Restore_List); + if (!Restore_List.empty()) { end_pos = Restore_List.find(";", start_pos); while (end_pos != string::npos && start_pos < Restore_List.size()) { restore_path = Restore_List.substr(start_pos, end_pos - start_pos); - restore_part = Find_Partition_By_Path(restore_path); - if (restore_part != NULL) { - if (restore_part->Mount_Read_Only) { - gui_msg(Msg(msg::kError, "restore_read_only=Cannot restore {1} -- mounted read only.")(restore_part->Backup_Display_Name)); + part_settings.Part = Find_Partition_By_Path(restore_path); + if (part_settings.Part != NULL) { + part_settings.Backup_FileName = part_settings.Part->Backup_Name + "." + part_settings.Part->Current_File_System + ".win"; + if (part_settings.Part->Mount_Read_Only) { + gui_msg(Msg(msg::kError, "restore_read_only=Cannot restore {1} -- mounted read only.")(part_settings.Part->Backup_Display_Name)); return false; } - if (check_md5 > 0 && !restore_part->Check_MD5(Restore_Name)) + + if (check_md5 > 0 && !part_settings.Part->Check_MD5(Restore_Name)) return false; - partition_count++; - total_restore_size += restore_part->Get_Restore_Size(Restore_Name); - if (restore_part->Has_SubPartition) { + part_settings.partition_count++; + part_settings.total_restore_size += part_settings.Part->Get_Restore_Size(&part_settings); + if (part_settings.Part->Has_SubPartition) { std::vector<TWPartition*>::iterator subpart; for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) { - if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == restore_part->Mount_Point) { + if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == part_settings.Part->Mount_Point) { if (check_md5 > 0 && !(*subpart)->Check_MD5(Restore_Name)) return false; - total_restore_size += (*subpart)->Get_Restore_Size(Restore_Name); + part_settings.total_restore_size += (*subpart)->Get_Restore_Size(&part_settings); } } } @@ -909,25 +976,29 @@ int TWPartitionManager::Run_Restore(const string& Restore_Name) { } } - if (partition_count == 0) { + if (part_settings.partition_count == 0) { gui_err("no_part_restore=No partitions selected for restore."); return false; } - gui_msg(Msg("restore_part_count=Restoring {1} partitions...")(partition_count)); - gui_msg(Msg("total_restore_size=Total restore size is {1}MB")(total_restore_size / 1048576)); + gui_msg(Msg("restore_part_count=Restoring {1} partitions...")(part_settings.partition_count)); + gui_msg(Msg("total_restore_size=Total restore size is {1}MB")(part_settings.total_restore_size / 1048576)); DataManager::SetProgress(0.0); - ProgressTracking progress(total_restore_size); + ProgressTracking progress(part_settings.total_restore_size); + part_settings.progress = &progress; start_pos = 0; if (!Restore_List.empty()) { end_pos = Restore_List.find(";", start_pos); while (end_pos != string::npos && start_pos < Restore_List.size()) { restore_path = Restore_List.substr(start_pos, end_pos - start_pos); - restore_part = Find_Partition_By_Path(restore_path); - if (restore_part != NULL) { - partition_count++; - if (!Restore_Partition(restore_part, Restore_Name, &progress)) + + part_settings.Part = Find_Partition_By_Path(restore_path); + if (part_settings.Part != NULL) { + part_settings.partition_count++; + part_settings.Backup_FileName = part_settings.Part->Backup_Name + "." + part_settings.Part->Current_File_System + ".win"; + part_settings.Full_Backup_Path = part_settings.Backup_Folder + "/" + part_settings.Backup_FileName + "/"; + if (!Restore_Partition(&part_settings)) return false; } else { gui_msg(Msg(msg::kError, "restore_unable_locate=Unable to locate '{1}' partition for restoring.")(restore_path)); @@ -942,6 +1013,7 @@ int TWPartitionManager::Run_Restore(const string& Restore_Name) { time(&rStop); gui_msg(Msg(msg::kHighlight, "restore_completed=[RESTORE COMPLETED IN {1} SECONDS]")((int)difftime(rStop,rStart))); DataManager::SetValue("tw_file_progress", ""); + return true; } @@ -2170,21 +2242,23 @@ bool TWPartitionManager::Remove_MTP_Storage(unsigned int Storage_ID) { return false; } -bool TWPartitionManager::Flash_Image(string Filename) { +bool TWPartitionManager::Flash_Image(PartitionSettings *part_settings) { int check, partition_count = 0; TWPartition* flash_part = NULL; - string Flash_List, flash_path; + string Flash_List, flash_path, full_filename; size_t start_pos = 0, end_pos = 0; + full_filename = part_settings->Restore_Name + "/" + part_settings->Backup_FileName; + gui_msg("image_flash_start=[IMAGE FLASH STARTED]"); - gui_msg(Msg("img_to_flash=Image to flash: '{1}'")(Filename)); + gui_msg(Msg("img_to_flash=Image to flash: '{1}'")(full_filename)); - if (!TWFunc::Path_Exists(Filename)) { - if (!Mount_By_Path(Filename, true)) { + if (!TWFunc::Path_Exists(full_filename)) { + if (!Mount_By_Path(full_filename, true)) { return false; } - if (!TWFunc::Path_Exists(Filename)) { - gui_msg(Msg(msg::kError, "unable_to_locate=Unable to locate {1}.")(Filename)); + if (!TWFunc::Path_Exists(full_filename)) { + gui_msg(Msg(msg::kError, "unable_to_locate=Unable to locate {1}.")(full_filename)); return false; } } @@ -2218,7 +2292,7 @@ bool TWPartitionManager::Flash_Image(string Filename) { DataManager::SetProgress(0.0); if (flash_part) { - if (!flash_part->Flash_Image(Filename)) + if (!flash_part->Flash_Image(part_settings)) return false; } else { gui_err("invalid_flash=Invalid flash partition specified."); diff --git a/partitions.hpp b/partitions.hpp index 1ba0691eb..705254612 100644 --- a/partitions.hpp +++ b/partitions.hpp @@ -35,18 +35,46 @@ struct PartitionList { unsigned int selected; }; +enum PartitionManager_Op { // PartitionManager Restore Mode for Raw_Read_Write() + PM_BACKUP = 0, + PM_RESTORE = 1, +}; + +class TWPartition; + +struct PartitionSettings { // Settings for backup session + TWPartition* Part; // Partition to pass to the partition backup loop + std::string Backup_Folder; // Backup folder to put backup into + std::string Full_Backup_Path; // Path to the current backup storage setting + std::string Backup_Name; // Name of partition + std::string Restore_Name; // Path to restore folder + std::string Backup_FileName; // Name of the file to restore + bool adbbackup; // tell the system we are backing up over adb + bool adb_compression; // 0 == uncompressed, 1 == compressed + bool generate_md5; // tell system to create md5 for partitions + uint64_t total_restore_size; // Total size of restored backup + uint64_t img_bytes_remaining; // remaining img/emmc bytes to backup for progress indicator + uint64_t file_bytes_remaining; // remaining file bytes to backup for progress indicator + uint64_t img_time; // used to calculate how fast we backup images + uint64_t file_time; // used to calculate how fast we backup files + uint64_t img_bytes; // total image bytes of all emmc partitions + uint64_t file_bytes; // total file bytes of all file based partitions + int partition_count; // Number of partitions to restore + ProgressTracking *progress; + enum PartitionManager_Op PM_Method; //Current operation of backup or restore +}; + +enum Backup_Method_enum { + BM_NONE = 0, + BM_FILES = 1, + BM_DD = 2, + BM_FLASH_UTILS = 3, +}; + // Partition class class TWPartition { public: - enum Backup_Method_enum { - NONE = 0, - FILES = 1, - DD = 2, - FLASH_UTILS = 3, - }; - -public: TWPartition(); virtual ~TWPartition(); @@ -65,18 +93,19 @@ public: bool Repair(); // Repairs the current file system bool Can_Resize(); // Checks to see if we have everything needed to be able to resize the current file system bool Resize(); // Resizes the current file system - bool Backup(const string& backup_folder, pid_t &tar_fork_pid, ProgressTracking *progress); // Backs up the partition to the folder specified + bool Backup(PartitionSettings *part_settings, pid_t *tar_fork_pid); // Backs up the partition to the folder specified bool Check_MD5(string restore_folder); // Checks MD5 of a backup - bool Restore(const string& restore_folder, ProgressTracking *progress); // Restores the partition using the backup folder provided - unsigned long long Get_Restore_Size(const string& restore_folder); // Returns the overall restore size of the backup + bool Restore(PartitionSettings *part_settings); // Restores the partition using the backup folder provided + unsigned long long Get_Restore_Size(PartitionSettings *part_settings);// Returns the overall restore size of the backup string Backup_Method_By_Name(); // Returns a string of the backup method for human readable output bool Decrypt(string Password); // Decrypts the partition, return 0 for failure and -1 for success bool Wipe_Encryption(); // Ignores wipe commands for /data/media devices and formats the original block device void Check_FS_Type(); // Checks the fs type using blkid, does not do anything on MTD / yaffs2 because this crashes on some devices bool Update_Size(bool Display_Error); // Updates size information void Recreate_Media_Folder(); // Recreates the /data/media folder - bool Flash_Image(const string& Filename); // Flashes an image to the partition + bool Flash_Image(PartitionSettings *part_settings); // Flashes an image to the partition void Change_Mount_Read_Only(bool new_value); // Changes Mount_Read_Only to new_value + bool Is_Read_Only(); // Check if system is read-only in TWRP int Check_Lifetime_Writes(); int Decrypt_Adopted(); void Revert_Adopted(); @@ -85,6 +114,7 @@ public: public: string Current_File_System; // Current file system string Actual_Block_Device; // Actual block device (one of primary, alternate, or decrypted) + string Backup_Display_Name; // Name displayed in the partition list for backup selection string MTD_Name; // Name of the partition for MTD devices bool Is_Present; // Indicates if the partition is currently present as a block device string Crypto_Key_Location; // Location of the crypto key used for decrypting encrypted data partitions @@ -123,13 +153,13 @@ private: bool Wipe_NTFS(); // Uses mkntfs to wipe bool Wipe_Data_Without_Wiping_Media(); // Uses rm -rf to wipe but does not wipe /data/media bool Wipe_Data_Without_Wiping_Media_Func(const string& parent); // Uses rm -rf to wipe but does not wipe /data/media - bool Backup_Tar(const string& backup_folder, ProgressTracking *progress, pid_t &tar_fork_pid); // Backs up using tar for file systems - bool Backup_Image(const string& backup_folder, ProgressTracking *progress); // Backs up using raw read/write for emmc memory types - bool Raw_Read_Write(const string& input_file, const string& output_file, const unsigned long long input_size, ProgressTracking *progress); - bool Backup_Dump_Image(const string& backup_folder, ProgressTracking *progress); // Backs up using dump_image for MTD memory types - string Get_Restore_File_System(const string& restore_folder); // Returns the file system that was in place at the time of the backup - bool Restore_Tar(const string& restore_folder, const string& Restore_File_System, ProgressTracking *progress); // Restore using tar for file systems - bool Restore_Image(const string& restore_folder, const string& Restore_File_System, ProgressTracking *progress); // Restore using raw read/write for images + bool Backup_Tar(PartitionSettings *part_settings, pid_t *tar_fork_pid); // Backs up using tar for file systems + bool Backup_Image(PartitionSettings *part_settings); // Backs up using raw read/write for emmc memory types + bool Raw_Read_Write(PartitionSettings *part_settings); + bool Backup_Dump_Image(PartitionSettings *part_settings); // Backs up using dump_image for MTD memory types + string Get_Restore_File_System(PartitionSettings *part_settings); // Returns the file system that was in place at the time of the backup + bool Restore_Tar(PartitionSettings *part_settings); // Restore using tar for file systems + bool Restore_Image(PartitionSettings *part_settings); // Restore using dd for images bool Get_Size_Via_statfs(bool Display_Error); // Get Partition size, used, and free space using statfs bool Get_Size_Via_df(bool Display_Error); // Get Partition size, used, and free space using df command bool Make_Dir(string Path, bool Display_Error); // Creates a directory if it doesn't already exist @@ -170,7 +200,6 @@ private: bool Mount_To_Decrypt; // Mount this partition during decrypt (/vendor, /firmware, etc in case we need proprietary libs or firmware files) string Display_Name; // Display name for the GUI string Backup_Name; // Backup name -- used for backup filenames - string Backup_Display_Name; // Name displayed in the partition list for backup selection string Storage_Name; // Name displayed in the partition list for storage selection string Backup_FileName; // Actual backup filename Backup_Method_enum Backup_Method; // Method used for backup @@ -214,8 +243,10 @@ public: int Mount_Settings_Storage(bool Display_Error); // Mounts the settings file storage location (usually internal) TWPartition* Find_Partition_By_Path(string Path); // Returns a pointer to a partition based on path int Check_Backup_Name(bool Display_Error); // Checks the current backup name to ensure that it is valid - int Run_Backup(); // Initiates a backup in the current storage + int Run_Backup(bool adbbackup); // Initiates a backup in the current storage int Run_Restore(const string& Restore_Name); // Restores a backup + bool Write_ADB_Stream_Header(uint64_t partition_count); // Write ADB header over twrpbu FIFO + bool Write_ADB_Stream_Trailer(); // Write ADB trailer over twrpbu FIFO void Set_Restore_Files(string Restore_Name); // Used to gather a list of available backup partitions for the user to select for a restore int Wipe_By_Path(string Path); // Wipes a partition based on path int Wipe_By_Path(string Path, string New_File_System); // Wipes a partition based on path @@ -250,21 +281,21 @@ public: bool Add_MTP_Storage(unsigned int Storage_ID); // Adds or removes an MTP Storage partition bool Remove_MTP_Storage(string Mount_Point); // Adds or removes an MTP Storage partition bool Remove_MTP_Storage(unsigned int Storage_ID); // Adds or removes an MTP Storage partition - bool Flash_Image(string Filename); // Flashes an image to a selected partition from the partition list void Translate_Partition(const char* path, const char* resource_name, const char* default_value); void Translate_Partition(const char* path, const char* resource_name, const char* default_value, const char* storage_resource_name, const char* storage_default_value); void Translate_Partition_Display_Names(); // Updates display names based on translations void Decrypt_Adopted(); // Attempt to identy and decrypt any adopted storage partitions void Remove_Partition_By_Path(string Path); // Removes / erases a partition entry from the partition list + bool Flash_Image(PartitionSettings *part_settings); // Flashes an image to a selected partition from the partition list + bool Restore_Partition(struct PartitionSettings *part_settings); // Restore the partitions based on type TWAtomicInt stop_backup; private: void Setup_Settings_Storage_Partition(TWPartition* Part); // Sets up settings storage void Setup_Android_Secure_Location(TWPartition* Part); // Sets up .android_secure if needed bool Make_MD5(bool generate_md5, string Backup_Folder, string Backup_Filename); // Generates an MD5 after a backup is made - bool Backup_Partition(TWPartition* Part, const string& Backup_Folder, bool generate_md5, unsigned long *img_time, unsigned long *file_time, ProgressTracking *progress); - bool Restore_Partition(TWPartition* Part, const string& Restore_Name, ProgressTracking *progress); + bool Backup_Partition(struct PartitionSettings *part_settings); // Backup the partitions based on type void Output_Partition(TWPartition* Part); // Outputs partition details to the log TWPartition* Find_Partition_By_MTP_Storage_ID(unsigned int Storage_ID); // Returns a pointer to a partition based on MTP Storage ID bool Add_Remove_MTP_Storage(TWPartition* Part, int message_type); // Adds or removes an MTP Storage partition @@ -273,7 +304,8 @@ private: pid_t mtppid; bool mtp_was_enabled; int mtp_write_fd; - pid_t tar_fork_pid; + pid_t tar_fork_pid; // PID of twrpTar fork + Backup_Method_enum Backup_Method; // Method used for backup private: std::vector<TWPartition*> Partitions; // Vector list of all partitions diff --git a/prebuilt/Android.mk b/prebuilt/Android.mk index cba396af2..3ec4c03a2 100644 --- a/prebuilt/Android.mk +++ b/prebuilt/Android.mk @@ -4,6 +4,7 @@ RELINK := $(LOCAL_PATH)/relink.sh #dummy file to trigger required modules include $(CLEAR_VARS) + LOCAL_MODULE := teamwin LOCAL_MODULE_TAGS := eng LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES @@ -13,6 +14,7 @@ LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin RELINK_SOURCE_FILES += $(TARGET_RECOVERY_ROOT_OUT)/sbin/dump_image RELINK_SOURCE_FILES += $(TARGET_RECOVERY_ROOT_OUT)/sbin/flash_image RELINK_SOURCE_FILES += $(TARGET_RECOVERY_ROOT_OUT)/sbin/erase_image +RELINK_SOURCE_FILES += $(TARGET_RECOVERY_ROOT_OUT)/sbin/bu ifneq ($(TW_USE_TOOLBOX), true) RELINK_SOURCE_FILES += $(TARGET_OUT_OPTIONAL_EXECUTABLES)/busybox else @@ -77,6 +79,7 @@ RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libminadbd.so RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libminzip.so RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libmtdutils.so RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libtar.so +RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libtwadbbu.so RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libutil-linux.so RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libblkid.so RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libmmcutils.so @@ -225,7 +228,6 @@ ifeq ($(TWRP_INCLUDE_LOGCAT), true) endif endif TWRP_AUTOGEN := $(intermediates)/teamwin - GEN := $(intermediates)/teamwin $(GEN): $(RELINK) $(GEN): $(RELINK_SOURCE_FILES) $(call intermediates-dir-for,EXECUTABLES,recovery)/recovery diff --git a/twrp-functions.cpp b/twrp-functions.cpp index 1c633e7e4..8cc094fc2 100644 --- a/twrp-functions.cpp +++ b/twrp-functions.cpp @@ -151,7 +151,7 @@ bool TWFunc::Path_Exists(string Path) { return true; } -int TWFunc::Get_File_Type(string fn) { +Archive_Type TWFunc::Get_File_Type(string fn) { string::size_type i = 0; int firstbyte = 0, secondbyte = 0; char header[3]; @@ -164,13 +164,10 @@ int TWFunc::Get_File_Type(string fn) { secondbyte = header[++i] & 0xff; if (firstbyte == 0x1f && secondbyte == 0x8b) - return 1; // Compressed + return COMPRESSED; else if (firstbyte == 0x4f && secondbyte == 0x41) - return 2; // Encrypted - else - return 0; // Unknown - - return 0; + return ENCRYPTED; + return UNCOMPRESSED; // default } int TWFunc::Try_Decrypting_File(string fn, string password) { @@ -752,7 +749,7 @@ bool TWFunc::Try_Decrypting_Backup(string Restore_Path, string Password) { while ((de = readdir(d)) != NULL) { Filename = Restore_Path; Filename += de->d_name; - if (TWFunc::Get_File_Type(Filename) == 2) { + if (TWFunc::Get_File_Type(Filename) == ENCRYPTED) { if (TWFunc::Try_Decrypting_File(Filename, Password) < 2) { DataManager::SetValue("tw_restore_password", ""); // Clear the bad password DataManager::SetValue("tw_restore_display", ""); // Also clear the display mask diff --git a/twrp-functions.hpp b/twrp-functions.hpp index 3f9b2ff5a..550c946f0 100644 --- a/twrp-functions.hpp +++ b/twrp-functions.hpp @@ -34,6 +34,13 @@ typedef enum rb_download, } RebootCommand; +enum Archive_Type { + UNCOMPRESSED = 0, + COMPRESSED, + ENCRYPTED, + COMPRESSED_ENCRYPTED +}; + // Partition class class TWFunc { @@ -46,7 +53,7 @@ public: static int Exec_Cmd(const string& cmd); //execute a command static int Wait_For_Child(pid_t pid, int *status, string Child_Name); // Waits for pid to exit and checks exit status static bool Path_Exists(string Path); // Returns true if the path exists - static int Get_File_Type(string fn); // Determines file type, 0 for unknown, 1 for gzip, 2 for OAES encrypted + static Archive_Type Get_File_Type(string fn); // Determines file type, 0 for unknown, 1 for gzip, 2 for OAES encrypted static int Try_Decrypting_File(string fn, string password); // -1 for some error, 0 for failed to decrypt, 1 for decrypted, 3 for decrypted and found gzip format static unsigned long Get_File_Size(const string& Path); // Returns the size of a file static std::string Remove_Trailing_Slashes(const std::string& path, bool leaveLast = false); // Normalizes the path, e.g /data//media/ -> /data/media diff --git a/twrpDigest.cpp b/twrpDigest.cpp index 0dd3ea904..ab8f456f5 100644 --- a/twrpDigest.cpp +++ b/twrpDigest.cpp @@ -48,13 +48,47 @@ void twrpDigest::setfn(const string& fn) { md5fn = fn; } +void twrpDigest::initMD5(void) { + MD5Init(&md5c); + md5string = ""; +} + +int twrpDigest::updateMD5stream(unsigned char* stream, int len) { + if (md5fn.empty()) { + MD5Update(&md5c, stream, len); + } + else { + return -1; + } + return 0; +} + +void twrpDigest::finalizeMD5stream() { + MD5Final(md5sum, &md5c); +} + +string twrpDigest::createMD5string() { + int i; + char hex[3]; + + for (i = 0; i < 16; ++i) { + snprintf(hex, 3, "%02x", md5sum[i]); + md5string += hex; + } + if (!md5fn.empty()) { + md5string += " "; + md5string += basename((char*) md5fn.c_str()); + md5string += + "\n"; + } + return md5string; +} + int twrpDigest::computeMD5(void) { string line; - struct MD5Context md5c; FILE *file; int len; unsigned char buf[1024]; - MD5Init(&md5c); + initMD5(); file = fopen(md5fn.c_str(), "rb"); if (file == NULL) return -1; @@ -67,21 +101,13 @@ int twrpDigest::computeMD5(void) { } int twrpDigest::write_md5digest(void) { - int i; - string md5string, md5file; - char hex[3]; + string md5file, md5str; md5file = md5fn + ".md5"; - for (i = 0; i < 16; ++i) { - snprintf(hex, 3, "%02x", md5sum[i]); - md5string += hex; - } - md5string += " "; - md5string += basename((char*) md5fn.c_str()); - md5string += + "\n"; - TWFunc::write_file(md5file, md5string); + md5str = createMD5string(); + TWFunc::write_file(md5file, md5str); tw_set_default_metadata(md5file.c_str()); - LOGINFO("MD5 for %s: %s\n", md5fn.c_str(), md5string.c_str()); + LOGINFO("MD5 for %s: %s\n", md5fn.c_str(), md5str.c_str()); return 0; } @@ -124,7 +150,7 @@ int twrpDigest::verify_md5digest(void) { string buf; char hex[3]; int i, ret; - string md5string; + string md5str; ret = read_md5digest(); if (ret != 0) @@ -136,9 +162,9 @@ int twrpDigest::verify_md5digest(void) { computeMD5(); for (i = 0; i < 16; ++i) { snprintf(hex, 3, "%02x", md5sum[i]); - md5string += hex; + md5str += hex; } - if (tokens.at(0) != md5string) { + if (tokens.at(0) != md5str) { gui_err("md5_fail=MD5 does not match"); return -2; } diff --git a/twrpDigest.hpp b/twrpDigest.hpp index 2c08ec546..7ec25edad 100644 --- a/twrpDigest.hpp +++ b/twrpDigest.hpp @@ -29,10 +29,16 @@ public: int computeMD5(void); int verify_md5digest(void); int write_md5digest(void); + int updateMD5stream(unsigned char* stream, int len); + void finalizeMD5stream(void); + string createMD5string(void); + void initMD5(void); private: int read_md5digest(void); + struct MD5Context md5c; string md5fn; string line; unsigned char md5sum[MD5LENGTH]; + string md5string; }; diff --git a/twrpTar.cpp b/twrpTar.cpp index b46f10f60..dcbb28202 100644 --- a/twrpTar.cpp +++ b/twrpTar.cpp @@ -38,9 +38,13 @@ extern "C" { #include <dirent.h> #include <libgen.h> #include <sys/mman.h> +#include <sys/ioctl.h> +#include <zlib.h> +#include <semaphore.h> #include "twrpTar.hpp" #include "twcommon.h" #include "variables.h" +#include "adbbu/libtwadbbu.hpp" #include "twrp-functions.hpp" #include "gui/gui.hpp" #include "progresstracking.hpp" @@ -91,19 +95,30 @@ void twrpTar::Signal_Kill(int signum) { _exit(255); } -int twrpTar::createTarFork(ProgressTracking *progress, pid_t &fork_pid) { +void twrpTar::Set_Archive_Type(Archive_Type archive_type) { + current_archive_type = archive_type; +} + +int twrpTar::createTarFork(pid_t *tar_fork_pid) { int status = 0; - pid_t rc_pid, tar_fork_pid; + pid_t rc_pid; int progress_pipe[2], ret; + char cmd[512]; file_count = 0; + if (part_settings->adbbackup) { + std::string Backup_FileName(tarfn); + if (!twadbbu::Write_TWFN(Backup_FileName, Total_Backup_Size, use_compression)) + return -1; + } + if (pipe(progress_pipe) < 0) { LOGINFO("Error creating progress tracking pipe\n"); gui_err("backup_error=Error creating backup."); return -1; } - if ((tar_fork_pid = fork()) == -1) { + if ((*tar_fork_pid = fork()) == -1) { LOGINFO("create tar failed to fork.\n"); gui_err("backup_error=Error creating backup."); close(progress_pipe[0]); @@ -111,7 +126,7 @@ int twrpTar::createTarFork(ProgressTracking *progress, pid_t &fork_pid) { return -1; } - if (tar_fork_pid == 0) { + if (*tar_fork_pid == 0) { // Child process // Child closes input side of progress pipe signal(SIGUSR2, twrpTar::Signal_Kill); @@ -254,6 +269,7 @@ int twrpTar::createTarFork(ProgressTracking *progress, pid_t &fork_pid) { reg.use_compression = use_compression; reg.split_archives = 1; reg.progress_pipe_fd = progress_pipe_fd; + reg.part_settings = part_settings; LOGINFO("Creating unencrypted backup...\n"); if (createList((void*)®) != 0) { LOGINFO("Error creating unencrypted backup.\n"); @@ -297,6 +313,7 @@ int twrpTar::createTarFork(ProgressTracking *progress, pid_t &fork_pid) { enc[i].use_compression = use_compression; enc[i].split_archives = 1; enc[i].progress_pipe_fd = progress_pipe_fd; + enc[i].part_settings = part_settings; LOGINFO("Start encryption thread %i\n", i); ret = pthread_create(&enc_thread[i], &tattr, createList, (void*)&enc[i]); if (ret) { @@ -371,7 +388,8 @@ int twrpTar::createTarFork(ProgressTracking *progress, pid_t &fork_pid) { reg.use_compression = use_compression; reg.setsize(Total_Backup_Size); reg.progress_pipe_fd = progress_pipe_fd; - if (Total_Backup_Size > MAX_ARCHIVE_SIZE) { + reg.part_settings = part_settings; + if (Total_Backup_Size > MAX_ARCHIVE_SIZE && !part_settings->adbbackup) { gui_msg("split_backup=Breaking backup file into multiple archives..."); reg.split_archives = 1; } else { @@ -393,8 +411,6 @@ int twrpTar::createTarFork(ProgressTracking *progress, pid_t &fork_pid) { unsigned long long fs, size_backup = 0, files_backup = 0, file_count = 0; int first_data = 0; - fork_pid = tar_fork_pid; - // Parent closes output side close(progress_pipe[1]); @@ -408,14 +424,14 @@ int twrpTar::createTarFork(ProgressTracking *progress, pid_t &fork_pid) { } else if (first_data == 1) { // Second incoming data is total size first_data = 2; - progress->SetSizeCount(fs, file_count); + part_settings->progress->SetSizeCount(fs, file_count); } else { if (fs > 0) { size_backup += fs; - progress->UpdateSize(size_backup); + part_settings->progress->UpdateSize(size_backup); } else { // fs == 0 increments the file counter files_backup++; - progress->UpdateSizeCount(size_backup, files_backup); + part_settings->progress->UpdateSizeCount(size_backup, files_backup); } } } @@ -423,29 +439,31 @@ int twrpTar::createTarFork(ProgressTracking *progress, pid_t &fork_pid) { #ifndef BUILD_TWRPTAR_MAIN DataManager::SetValue("tw_file_progress", ""); DataManager::SetValue("tw_size_progress", ""); - progress->DisplayFileCount(false); - progress->UpdateDisplayDetails(true); - - InfoManager backup_info(backup_folder + partition_name + ".info"); - backup_info.SetValue("backup_size", size_backup); - if (use_compression && use_encryption) - backup_info.SetValue("backup_type", 3); - else if (use_encryption) - backup_info.SetValue("backup_type", 2); - else if (use_compression) - backup_info.SetValue("backup_type", 1); - else - backup_info.SetValue("backup_type", 0); - backup_info.SetValue("file_count", files_backup); - backup_info.SaveValues(); + part_settings->progress->DisplayFileCount(false); + part_settings->progress->UpdateDisplayDetails(true); + + if (!part_settings->adbbackup) { + InfoManager backup_info(backup_folder + partition_name + ".info"); + backup_info.SetValue("backup_size", size_backup); + if (use_compression && use_encryption) + backup_info.SetValue("backup_type", COMPRESSED_ENCRYPTED); + else if (use_encryption) + backup_info.SetValue("backup_type", ENCRYPTED); + else if (use_compression) + backup_info.SetValue("backup_type", COMPRESSED); + else + backup_info.SetValue("backup_type", UNCOMPRESSED); + backup_info.SetValue("file_count", files_backup); + backup_info.SaveValues(); + } #endif //ndef BUILD_TWRPTAR_MAIN - if (TWFunc::Wait_For_Child(tar_fork_pid, &status, "createTarFork()") != 0) + if (TWFunc::Wait_For_Child(*tar_fork_pid, &status, "createTarFork()") != 0) return -1; } return 0; } -int twrpTar::extractTarFork(ProgressTracking *progress) { +int twrpTar::extractTarFork() { int status = 0; pid_t rc_pid, tar_fork_pid; int progress_pipe[2], ret; @@ -463,12 +481,13 @@ int twrpTar::extractTarFork(ProgressTracking *progress) { { close(progress_pipe[0]); progress_pipe_fd = progress_pipe[1]; - if (TWFunc::Path_Exists(tarfn)) { + if (TWFunc::Path_Exists(tarfn) || part_settings->adbbackup) { LOGINFO("Single archive\n"); if (extract() != 0) _exit(-1); - else + else { _exit(0); + } } else { LOGINFO("Multiple archives\n"); string temp; @@ -494,6 +513,7 @@ int twrpTar::extractTarFork(ProgressTracking *progress) { tars[0].basefn = basefn; tars[0].thread_id = 0; tars[0].progress_pipe_fd = progress_pipe_fd; + tars[0].part_settings = part_settings; if (extractMulti((void*)&tars[0]) != 0) { LOGINFO("Error extracting split archive.\n"); gui_err("restore_error=Error during restore process."); @@ -535,6 +555,7 @@ int twrpTar::extractTarFork(ProgressTracking *progress) { tars[i].setpassword(password); tars[i].thread_id = i; tars[i].progress_pipe_fd = progress_pipe_fd; + tars[i].part_settings = part_settings; LOGINFO("Creating extract thread ID %i\n", i); ret = pthread_create(&tar_thread[i], &tattr, extractMulti, (void*)&tars[i]); if (ret) { @@ -596,10 +617,10 @@ int twrpTar::extractTarFork(ProgressTracking *progress) { // Read progress data from children while (read(progress_pipe[0], &fs, sizeof(fs)) > 0) { size_backup += fs; - progress->UpdateSize(size_backup); + part_settings->progress->UpdateSize(size_backup); } close(progress_pipe[0]); - progress->UpdateDisplayDetails(true); + part_settings->progress->UpdateDisplayDetails(true); if (TWFunc::Wait_For_Child(tar_fork_pid, &status, "extractTarFork()") != 0) return -1; @@ -675,18 +696,31 @@ int twrpTar::extractTar() { gui_err("restore_error=Error during restore process."); return -1; } + if (part_settings->adbbackup) { + if (!twadbbu::Write_TWEOF()) + return -1; + } return 0; } int twrpTar::extract() { - Archive_Current_Type = TWFunc::Get_File_Type(tarfn); + if (!part_settings->adbbackup) { + LOGINFO("Setting archive type\n"); + Set_Archive_Type(TWFunc::Get_File_Type(tarfn)); + } + else { + if (part_settings->adb_compression == 1) + current_archive_type = COMPRESSED; + else + current_archive_type = UNCOMPRESSED; + } - if (Archive_Current_Type == 1) { + if (current_archive_type == COMPRESSED) { //if you return the extractTGZ function directly, stack crashes happen LOGINFO("Extracting gzipped tar\n"); int ret = extractTar(); return ret; - } else if (Archive_Current_Type == 2) { + } else if (current_archive_type == ENCRYPTED) { int ret = TWFunc::Try_Decrypting_File(tarfn, password); if (ret < 1) { gui_msg(Msg(msg::kError, "fail_decrypt_tar=Failed to decrypt tar file '{1}'")(tarfn)); @@ -699,7 +733,7 @@ int twrpTar::extract() { } if (ret == 3) { LOGINFO("Extracting encrypted and compressed tar.\n"); - Archive_Current_Type = 3; + current_archive_type = COMPRESSED_ENCRYPTED; } else LOGINFO("Extracting encrypted tar.\n"); return extractTar(); @@ -727,7 +761,12 @@ int twrpTar::tarList(std::vector<TarListStruct> *TarList, unsigned thread_id) { } else { include_root_dir = false; } - LOGINFO("Creating tar file '%s'\n", tarfn.c_str()); + + if (part_settings->adbbackup) + LOGINFO("Writing tar file '%s' to adb backup\n", tarfn.c_str()); + else + LOGINFO("Creating tar file '%s'\n", tarfn.c_str()); + if (createTar() != 0) { LOGINFO("Error creating tar '%s' for thread %i\n", tarfn.c_str(), thread_id); gui_err("backup_error=Error creating backup."); @@ -786,7 +825,6 @@ int twrpTar::tarList(std::vector<TarListStruct> *TarList, unsigned thread_id) { } void* twrpTar::createList(void *cookie) { - twrpTar* threadTar = (twrpTar*) cookie; if (threadTar->tarList(threadTar->ItemList, threadTar->thread_id) != 0) { LOGINFO("ERROR tarList for thread ID %i\n", threadTar->thread_id); @@ -797,7 +835,6 @@ void* twrpTar::createList(void *cookie) { } void* twrpTar::extractMulti(void *cookie) { - twrpTar* threadTar = (twrpTar*) cookie; int archive_count = 0; string temp = threadTar->basefn + "%i%02i"; @@ -844,7 +881,7 @@ int twrpTar::createTar() { if (use_encryption && use_compression) { // Compressed and encrypted - Archive_Current_Type = 3; + current_archive_type = COMPRESSED_ENCRYPTED; LOGINFO("Using encryption and compression...\n"); int i, pipes[4]; @@ -858,7 +895,7 @@ int twrpTar::createTar() { gui_err("backup_error=Error creating backup."); return -1; } - int output_fd = open(tarfn.c_str(), O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + output_fd = open(tarfn.c_str(), O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (output_fd < 0) { gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno))); for (i = 0; i < 4; i++) @@ -936,10 +973,16 @@ int twrpTar::createTar() { } } else if (use_compression) { // Compressed - Archive_Current_Type = 1; + current_archive_type = COMPRESSED; LOGINFO("Using compression...\n"); int pigzfd[2]; - int output_fd = open(tarfn.c_str(), O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + if (part_settings->adbbackup) { + LOGINFO("opening TW_ADB_BACKUP compressed stream\n"); + output_fd = open(TW_ADB_BACKUP, O_WRONLY); + } + else { + output_fd = open(tarfn.c_str(), O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + } if (output_fd < 0) { gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno))); close(pigzfd[0]); @@ -988,10 +1031,10 @@ int twrpTar::createTar() { } } else if (use_encryption) { // Encrypted - Archive_Current_Type = 2; + current_archive_type = ENCRYPTED; LOGINFO("Using encryption...\n"); int oaesfd[2]; - int output_fd = open(tarfn.c_str(), O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + output_fd = open(tarfn.c_str(), O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (output_fd < 0) { gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno))); return -1; @@ -1041,10 +1084,22 @@ int twrpTar::createTar() { // Not compressed or encrypted init_libtar_buffer(0, progress_pipe_fd); tar_type = { open, close, read, write_tar }; - if (tar_open(&t, charTarFile, &tar_type, O_WRONLY | O_CREAT | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TAR_GNU | TAR_STORE_SELINUX) == -1) { - LOGINFO("tar_open error opening '%s'\n", tarfn.c_str()); - gui_err("backup_error=Error creating backup."); - return -1; + if (part_settings->adbbackup) { + LOGINFO("Opening TW_ADB_BACKUP uncompressed stream\n"); + tar_type = { open, close, read, write_tar_no_buffer }; + output_fd = open(TW_ADB_BACKUP, O_WRONLY); + if(tar_fdopen(&t, output_fd, charRootDir, &tar_type, O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TAR_GNU | TAR_STORE_SELINUX) != 0) { + close(output_fd); + LOGERR("tar_fdopen failed\n"); + return -1; + } + } + else { + if (tar_open(&t, charTarFile, &tar_type, O_WRONLY | O_CREAT | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TAR_GNU | TAR_STORE_SELINUX) == -1) { + LOGERR("tar_open error opening '%s'\n", tarfn.c_str()); + gui_err("backup_error=Error creating backup."); + return -1; + } } } return 0; @@ -1055,10 +1110,10 @@ int twrpTar::openTar() { char* charTarFile = (char*) tarfn.c_str(); string Password; - if (Archive_Current_Type == 3) { + if (current_archive_type == COMPRESSED_ENCRYPTED) { LOGINFO("Opening encrypted and compressed backup...\n"); int i, pipes[4]; - int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE); + input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE); if (input_fd < 0) { gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno))); return -1; @@ -1144,10 +1199,10 @@ int twrpTar::openTar() { } } } - } else if (Archive_Current_Type == 2) { + } else if (current_archive_type == ENCRYPTED) { LOGINFO("Opening encrypted backup...\n"); int oaesfd[2]; - int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE); + input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE); if (input_fd < 0) { gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno))); return -1; @@ -1192,14 +1247,22 @@ int twrpTar::openTar() { return -1; } } - } else if (Archive_Current_Type == 1) { - LOGINFO("Opening as a gzip...\n"); + } else if (current_archive_type == COMPRESSED) { int pigzfd[2]; - int input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE); + + LOGINFO("Opening as a gzip...\n"); + if (part_settings->adbbackup) { + LOGINFO("opening TW_ADB_RESTORE compressed stream\n"); + input_fd = open(TW_ADB_RESTORE, O_RDONLY | O_LARGEFILE); + } + else + input_fd = open(tarfn.c_str(), O_RDONLY | O_LARGEFILE); + if (input_fd < 0) { gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(tarfn)(strerror(errno))); return -1; } + if (pipe(pigzfd) < 0) { LOGINFO("Error creating pipe\n"); gui_err("restore_error=Error during restore process."); @@ -1218,8 +1281,8 @@ int twrpTar::openTar() { } else if (pigz_pid == 0) { // Child close(pigzfd[0]); - dup2(input_fd, 0); // remap input fd to stdin dup2(pigzfd[1], 1); // remap stdout + dup2(input_fd, 0); // remap input fd to stdin if (execlp("pigz", "pigz", "-d", "-c", NULL) < 0) { close(pigzfd[1]); close(input_fd); @@ -1231,17 +1294,30 @@ int twrpTar::openTar() { // Parent close(pigzfd[1]); // close parent output fd = pigzfd[0]; // copy parent input - if(tar_fdopen(&t, fd, charRootDir, NULL, O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TAR_GNU | TAR_STORE_SELINUX) != 0) { + if (tar_fdopen(&t, fd, charRootDir, NULL, O_RDONLY | O_LARGEFILE , S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TAR_GNU | TAR_STORE_SELINUX) != 0) { close(fd); LOGINFO("tar_fdopen failed\n"); gui_err("restore_error=Error during restore process."); return -1; } } - } else if (tar_open(&t, charTarFile, NULL, O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TAR_GNU | TAR_STORE_SELINUX) != 0) { - LOGINFO("Unable to open tar archive '%s'\n", charTarFile); - gui_err("restore_error=Error during restore process."); - return -1; + } else { + if (part_settings->adbbackup) { + LOGINFO("Opening TW_ADB_RESTORE uncompressed stream\n"); + input_fd = open(TW_ADB_RESTORE, O_RDONLY); + if (tar_fdopen(&t, input_fd, charRootDir, NULL, O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TAR_GNU | TAR_STORE_SELINUX) != 0) { + LOGERR("Unable to open tar archive '%s'\n", charTarFile); + gui_err("restore_error=Error during restore process."); + return -1; + } + } + else { + if (tar_open(&t, charTarFile, NULL, O_RDONLY | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, TAR_GNU | TAR_STORE_SELINUX) != 0) { + LOGERR("Unable to open tar archive '%s'\n", charTarFile); + gui_err("restore_error=Error during restore process."); + return -1; + } + } } return 0; } @@ -1281,6 +1357,7 @@ int twrpTar::addFile(string fn, bool include_root) { } int twrpTar::closeTar() { + LOGINFO("Closing tar\n"); flush_libtar_buffer(t->fd); if (tar_append_eof(t) != 0) { LOGINFO("tar_append_eof(): %s\n", strerror(errno)); @@ -1291,7 +1368,7 @@ int twrpTar::closeTar() { LOGINFO("Unable to close tar archive: '%s'\n", tarfn.c_str()); return -1; } - if (Archive_Current_Type > 0) { + if (current_archive_type > 0) { close(fd); int status; if (pigz_pid > 0 && TWFunc::Wait_For_Child(pigz_pid, &status, "pigz") != 0) @@ -1300,19 +1377,27 @@ int twrpTar::closeTar() { return -1; } free_libtar_buffer(); - if (use_compression && !use_encryption) { - string gzname = tarfn + ".gz"; - if (TWFunc::Path_Exists(gzname)) { - rename(gzname.c_str(), tarfn.c_str()); + if (!part_settings->adbbackup) { + if (use_compression && !use_encryption) { + string gzname = tarfn + ".gz"; + if (TWFunc::Path_Exists(gzname)) { + rename(gzname.c_str(), tarfn.c_str()); + } + } + if (TWFunc::Get_File_Size(tarfn) == 0) { + gui_msg(Msg(msg::kError, "backup_size=Backup file size for '{1}' is 0 bytes.")(tarfn)); + return -1; } - } - if (TWFunc::Get_File_Size(tarfn) == 0) { - gui_msg(Msg(msg::kError, "backup_size=Backup file size for '{1}' is 0 bytes.")(tarfn)); - return -1; - } #ifndef BUILD_TWRPTAR_MAIN - tw_set_default_metadata(tarfn.c_str()); + tw_set_default_metadata(tarfn.c_str()); #endif + } + else { + if (!twadbbu::Write_TWEOF()) + return -1; + } + close(input_fd); + close(output_fd); return 0; } @@ -1335,7 +1420,7 @@ int twrpTar::entryExists(string entry) { char* searchstr = (char*)entry.c_str(); int ret; - Archive_Current_Type = TWFunc::Get_File_Type(tarfn); + Set_Archive_Type(TWFunc::Get_File_Type(tarfn)); if (openTar() == -1) ret = 0; @@ -1349,15 +1434,14 @@ int twrpTar::entryExists(string entry) { } unsigned long long twrpTar::get_size() { - if (TWFunc::Path_Exists(tarfn)) { + if (TWFunc::Path_Exists(tarfn) && !part_settings->adbbackup) { LOGINFO("Single archive\n"); - int type = 0; - return uncompressedSize(tarfn, &type); + return uncompressedSize(tarfn); } else { LOGINFO("Multiple archives\n"); string temp; char actual_filename[255]; - int archive_count = 0, i, type = 0, temp_type = 0; + int archive_count = 0; unsigned long long total_restore_size = 0; basefn = tarfn; @@ -1365,46 +1449,45 @@ unsigned long long twrpTar::get_size() { tarfn += "000"; thread_id = 0; sprintf(actual_filename, temp.c_str(), thread_id, archive_count); - if (!TWFunc::Path_Exists(actual_filename)) { - LOGERR("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str()); - return 0; - } - for (i = 0; i < 9; i++) { - archive_count = 0; - sprintf(actual_filename, temp.c_str(), i, archive_count); - while (TWFunc::Path_Exists(actual_filename)) { - total_restore_size += uncompressedSize(actual_filename, &temp_type); - if (temp_type > type) - type = temp_type; - archive_count++; - if (archive_count > 99) - break; + if (!part_settings->adbbackup) { + if (!TWFunc::Path_Exists(actual_filename)) { + LOGERR("Unable to locate '%s' or '%s'\n", basefn.c_str(), tarfn.c_str()); + return 0; + } + for (int i = 0; i < 9; i++) { + archive_count = 0; sprintf(actual_filename, temp.c_str(), i, archive_count); + while (TWFunc::Path_Exists(actual_filename)) { + total_restore_size += uncompressedSize(actual_filename); + archive_count++; + if (archive_count > 99) + break; + sprintf(actual_filename, temp.c_str(), i, archive_count); + } } + #ifndef BUILD_TWRPTAR_MAIN + if (!part_settings->adbbackup) { + InfoManager backup_info(tarfn + ".info"); + backup_info.SetValue("backup_size", total_restore_size); + backup_info.SetValue("backup_type", current_archive_type); + backup_info.SaveValues(); + } + #endif //ndef BUILD_TWRPTAR_MAIN } -#ifndef BUILD_TWRPTAR_MAIN - InfoManager backup_info(backup_folder + "/" + partition_name + ".info"); - backup_info.SetValue("backup_size", total_restore_size); - backup_info.SetValue("backup_type", type); - backup_info.SaveValues(); -#endif //ndef BUILD_TWRPTAR_MAIN return total_restore_size; } return 0; } -unsigned long long twrpTar::uncompressedSize(string filename, int *archive_type) { - int type = 0; +unsigned long long twrpTar::uncompressedSize(string filename) { unsigned long long total_size = 0; string Tar, Command, result; vector<string> split; - Tar = TWFunc::Get_Filename(filename); - type = TWFunc::Get_File_Type(filename); - if (type == 0) { + Set_Archive_Type(TWFunc::Get_File_Type(tarfn)); + if (current_archive_type == UNCOMPRESSED) { total_size = TWFunc::Get_File_Size(filename); - *archive_type = 0; - } else if (type == 1) { + } else if (current_archive_type == COMPRESSED) { // Compressed Command = "pigz -l '" + filename + "'"; /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '"; @@ -1421,11 +1504,9 @@ unsigned long long twrpTar::uncompressedSize(string filename, int *archive_type) if (split.size() > 4) total_size = atoi(split[5].c_str()); } - *archive_type = 1; - } else if (type == 2) { + } else if (current_archive_type == COMPRESSED_ENCRYPTED) { // File is encrypted and may be compressed int ret = TWFunc::Try_Decrypting_File(filename, password); - *archive_type = 2; if (ret < 1) { gui_msg(Msg(msg::kError, "fail_decrypt_tar=Failed to decrypt tar file '{1}'")(tarfn)); total_size = TWFunc::Get_File_Size(filename); @@ -1433,7 +1514,6 @@ unsigned long long twrpTar::uncompressedSize(string filename, int *archive_type) LOGERR("Decrypted file is not in tar format.\n"); total_size = TWFunc::Get_File_Size(filename); } else if (ret == 3) { - *archive_type = 3; Command = "openaes dec --key \"" + password + "\" --in '" + filename + "' | pigz -l"; /* if we set Command = "pigz -l " + tarfn + " | sed '1d' | cut -f5 -d' '"; we get the uncompressed size at once. */ diff --git a/twrpTar.hpp b/twrpTar.hpp index 8ef50207f..49d373c13 100644 --- a/twrpTar.hpp +++ b/twrpTar.hpp @@ -29,6 +29,8 @@ extern "C" { #include <vector> #include "twrpDU.hpp" #include "progresstracking.hpp" +#include "partitions.hpp" +#include "twrp-functions.hpp" using namespace std; @@ -42,17 +44,19 @@ struct thread_data_struct { unsigned thread_id; }; + class twrpTar { public: twrpTar(); virtual ~twrpTar(); - int createTarFork(ProgressTracking *progress, pid_t &fork_pid); - int extractTarFork(ProgressTracking *progress); + int createTarFork(pid_t *tar_fork_pid); + int extractTarFork(); void setfn(string fn); void setdir(string dir); void setsize(unsigned long long backup_size); void setpassword(string pass); unsigned long long get_size(); + void Set_Archive_Type(Archive_Type archive_type); public: int use_encryption; @@ -64,6 +68,7 @@ public: int progress_pipe_fd; string partition_name; string backup_folder; + PartitionSettings *part_settings; private: int extract(); @@ -80,16 +85,17 @@ private: static void* createList(void *cookie); static void* extractMulti(void *cookie); int tarList(std::vector<TarListStruct> *TarList, unsigned thread_id); - unsigned long long uncompressedSize(string filename, int *archive_type); + unsigned long long uncompressedSize(string filename); static void Signal_Kill(int signum); - int Archive_Current_Type; + enum Archive_Type current_archive_type; unsigned long long Archive_Current_Size; unsigned long long Total_Backup_Size; bool include_root_dir; TAR *t; tartype_t tar_type; // Only used in createTar() but variable must persist while the tar is open int fd; + int input_fd; // this stores the fd for libtar to write to pid_t pigz_pid; pid_t oaes_pid; unsigned long long file_count; @@ -100,5 +106,7 @@ private: string password; std::vector<TarListStruct> *ItemList; + int output_fd; // this stores the output fd that gzip will read from + int adb_control_twrp_fd, adb_control_bu_fd; // fds for twrp to twrp bu and bu to twrp control fifos unsigned thread_id; }; |