summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk6
-rw-r--r--adbbu/Android.mk45
-rw-r--r--adbbu/libtwadbbu.cpp196
-rw-r--r--adbbu/libtwadbbu.hpp44
-rw-r--r--adbbu/twadbstream.h101
-rw-r--r--adbbu/twrpback.cpp823
-rw-r--r--adbbu/twrpback.hpp49
-rw-r--r--gui/Android.mk1
-rw-r--r--gui/action.cpp19
-rw-r--r--gui/devices/common/res/languages/en.xml4
-rw-r--r--gui/gui.cpp10
-rw-r--r--gui/theme/common/landscape.xml3
-rw-r--r--gui/theme/common/languages/en.xml4
-rw-r--r--gui/theme/common/portrait.xml12
-rw-r--r--gui/theme/common/watch.xml18
-rw-r--r--openrecoveryscript.cpp289
-rw-r--r--openrecoveryscript.hpp3
-rw-r--r--orscmd/Android.mk2
-rw-r--r--orscmd/orscmd.cpp1
-rw-r--r--partition.cpp269
-rw-r--r--partitionmanager.cpp282
-rw-r--r--partitions.hpp82
-rw-r--r--prebuilt/Android.mk4
-rw-r--r--twrp-functions.cpp13
-rw-r--r--twrp-functions.hpp9
-rw-r--r--twrpDigest.cpp60
-rw-r--r--twrpDigest.hpp6
-rw-r--r--twrpTar.cpp296
-rw-r--r--twrpTar.hpp16
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*)&reg) != 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;
};