mirror of
https://github.com/meizu-m86/twrp_multirom_m86
synced 2025-11-03 21:45:40 +08:00
ADB: Add adb backup for TWRP.
Functionality for client side to backup tar and image streams over adbd to the client under backup.ab. Using adb backup on the client side you can backup the partitions TWRP knows about. On the client side you can do the following: adb backup -f <filename> --twrp <options> where options are --compress: compress data system: backup system cache: backup cache data: backup data boot: backup boot etc for each partition. You can string multiple options, i.e. adb backup -f <filename> --twrp --compress cache system data adb backup in TWRP will take any option corresponding to TWRP fstab partitions, e.g. efs boot as well. If you do not specify the filename with the -f option, adb will backup your data to a filename backup.ab on the client. You can then rename the file and encrypt it with desktop tools. If you don't want to use command line arguments: adb backup --twrp will bring up the gui and allow you to choose partitions from the backup page. To restore the backup use the following convention: adb restore <filename> Structures are used to store metadata in binary inside of the file itself. If the metadata structure is modified, update the adb version so that it will invalidate older backups and not cause issues on restore. When restoring, we currently do not support picking specific partitions. It's all or nothing. Change-Id: Idb92c37fc9801dc8d89ed2a4570e9d12e76facf8
This commit is contained in:
@@ -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)
|
||||
|
||||
45
adbbu/Android.mk
Normal file
45
adbbu/Android.mk
Normal file
@@ -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)
|
||||
196
adbbu/libtwadbbu.cpp
Normal file
196
adbbu/libtwadbbu.cpp
Normal file
@@ -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;
|
||||
}
|
||||
44
adbbu/libtwadbbu.hpp
Normal file
44
adbbu/libtwadbbu.hpp
Normal file
@@ -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
|
||||
};
|
||||
101
adbbu/twadbstream.h
Normal file
101
adbbu/twadbstream.h
Normal file
@@ -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
|
||||
823
adbbu/twrpback.cpp
Normal file
823
adbbu/twrpback.cpp
Normal file
@@ -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;
|
||||
}
|
||||
49
adbbu/twrpback.hpp
Normal file
49
adbbu/twrpback.hpp
Normal file
@@ -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
|
||||
};
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
10
gui/gui.cpp
10
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
|
||||
269
partition.cpp
269
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))
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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));
|
||||
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;
|
||||
|
||||
LOGINFO("Image filename is: %s\n", Filename.c_str());
|
||||
full_filename = part_settings->Restore_Name + "/" + part_settings->Backup_FileName;
|
||||
|
||||
if (Backup_Method == FILES) {
|
||||
LOGINFO("Image filename is: %s\n", part_settings->Backup_FileName.c_str());
|
||||
|
||||
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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
bool TWPartitionManager::Backup_Partition(PartitionSettings *part_settings) {
|
||||
time_t start, stop;
|
||||
int use_compression;
|
||||
int use_compression, adb_control_bu_fd;
|
||||
string backup_log = part_settings->Backup_Folder + "/recovery.log";
|
||||
|
||||
string backup_log = 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 (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 (file_bytes != 0)
|
||||
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;
|
||||
|
||||
gui_msg("image_flash_start=[IMAGE FLASH STARTED]");
|
||||
gui_msg(Msg("img_to_flash=Image to flash: '{1}'")(Filename));
|
||||
full_filename = part_settings->Restore_Name + "/" + part_settings->Backup_FileName;
|
||||
|
||||
if (!TWFunc::Path_Exists(Filename)) {
|
||||
if (!Mount_By_Path(Filename, true)) {
|
||||
gui_msg("image_flash_start=[IMAGE FLASH STARTED]");
|
||||
gui_msg(Msg("img_to_flash=Image to flash: '{1}'")(full_filename));
|
||||
|
||||
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.");
|
||||
|
||||
@@ -35,17 +35,45 @@ 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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
296
twrpTar.cpp
296
twrpTar.cpp
@@ -38,9 +38,13 @@ extern "C" {
|
||||
#include <dirent.h>
|
||||
#include <libgen.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <zlib.h>
|
||||
#include <semaphore.h>
|
||||
#include "twrpTar.hpp"
|
||||
#include "twcommon.h"
|
||||
#include "variables.h"
|
||||
#include "adbbu/libtwadbbu.hpp"
|
||||
#include "twrp-functions.hpp"
|
||||
#include "gui/gui.hpp"
|
||||
#include "progresstracking.hpp"
|
||||
@@ -91,19 +95,30 @@ void twrpTar::Signal_Kill(int signum) {
|
||||
_exit(255);
|
||||
}
|
||||
|
||||
int twrpTar::createTarFork(ProgressTracking *progress, pid_t &fork_pid) {
|
||||
void twrpTar::Set_Archive_Type(Archive_Type archive_type) {
|
||||
current_archive_type = archive_type;
|
||||
}
|
||||
|
||||
int twrpTar::createTarFork(pid_t *tar_fork_pid) {
|
||||
int status = 0;
|
||||
pid_t rc_pid, tar_fork_pid;
|
||||
pid_t rc_pid;
|
||||
int progress_pipe[2], ret;
|
||||
char cmd[512];
|
||||
|
||||
file_count = 0;
|
||||
|
||||
if (part_settings->adbbackup) {
|
||||
std::string Backup_FileName(tarfn);
|
||||
if (!twadbbu::Write_TWFN(Backup_FileName, Total_Backup_Size, use_compression))
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pipe(progress_pipe) < 0) {
|
||||
LOGINFO("Error creating progress tracking pipe\n");
|
||||
gui_err("backup_error=Error creating backup.");
|
||||
return -1;
|
||||
}
|
||||
if ((tar_fork_pid = fork()) == -1) {
|
||||
if ((*tar_fork_pid = fork()) == -1) {
|
||||
LOGINFO("create tar failed to fork.\n");
|
||||
gui_err("backup_error=Error creating backup.");
|
||||
close(progress_pipe[0]);
|
||||
@@ -111,7 +126,7 @@ int twrpTar::createTarFork(ProgressTracking *progress, pid_t &fork_pid) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tar_fork_pid == 0) {
|
||||
if (*tar_fork_pid == 0) {
|
||||
// Child process
|
||||
// Child closes input side of progress pipe
|
||||
signal(SIGUSR2, twrpTar::Signal_Kill);
|
||||
@@ -254,6 +269,7 @@ int twrpTar::createTarFork(ProgressTracking *progress, pid_t &fork_pid) {
|
||||
reg.use_compression = use_compression;
|
||||
reg.split_archives = 1;
|
||||
reg.progress_pipe_fd = progress_pipe_fd;
|
||||
reg.part_settings = part_settings;
|
||||
LOGINFO("Creating unencrypted backup...\n");
|
||||
if (createList((void*)®) != 0) {
|
||||
LOGINFO("Error creating unencrypted backup.\n");
|
||||
@@ -297,6 +313,7 @@ int twrpTar::createTarFork(ProgressTracking *progress, pid_t &fork_pid) {
|
||||
enc[i].use_compression = use_compression;
|
||||
enc[i].split_archives = 1;
|
||||
enc[i].progress_pipe_fd = progress_pipe_fd;
|
||||
enc[i].part_settings = part_settings;
|
||||
LOGINFO("Start encryption thread %i\n", i);
|
||||
ret = pthread_create(&enc_thread[i], &tattr, createList, (void*)&enc[i]);
|
||||
if (ret) {
|
||||
@@ -371,7 +388,8 @@ int twrpTar::createTarFork(ProgressTracking *progress, pid_t &fork_pid) {
|
||||
reg.use_compression = use_compression;
|
||||
reg.setsize(Total_Backup_Size);
|
||||
reg.progress_pipe_fd = progress_pipe_fd;
|
||||
if (Total_Backup_Size > MAX_ARCHIVE_SIZE) {
|
||||
reg.part_settings = part_settings;
|
||||
if (Total_Backup_Size > MAX_ARCHIVE_SIZE && !part_settings->adbbackup) {
|
||||
gui_msg("split_backup=Breaking backup file into multiple archives...");
|
||||
reg.split_archives = 1;
|
||||
} else {
|
||||
@@ -393,8 +411,6 @@ int twrpTar::createTarFork(ProgressTracking *progress, pid_t &fork_pid) {
|
||||
unsigned long long fs, size_backup = 0, files_backup = 0, file_count = 0;
|
||||
int first_data = 0;
|
||||
|
||||
fork_pid = tar_fork_pid;
|
||||
|
||||
// Parent closes output side
|
||||
close(progress_pipe[1]);
|
||||
|
||||
@@ -408,14 +424,14 @@ int twrpTar::createTarFork(ProgressTracking *progress, pid_t &fork_pid) {
|
||||
} else if (first_data == 1) {
|
||||
// Second incoming data is total size
|
||||
first_data = 2;
|
||||
progress->SetSizeCount(fs, file_count);
|
||||
part_settings->progress->SetSizeCount(fs, file_count);
|
||||
} else {
|
||||
if (fs > 0) {
|
||||
size_backup += fs;
|
||||
progress->UpdateSize(size_backup);
|
||||
part_settings->progress->UpdateSize(size_backup);
|
||||
} else { // fs == 0 increments the file counter
|
||||
files_backup++;
|
||||
progress->UpdateSizeCount(size_backup, files_backup);
|
||||
part_settings->progress->UpdateSizeCount(size_backup, files_backup);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -423,29 +439,31 @@ int twrpTar::createTarFork(ProgressTracking *progress, pid_t &fork_pid) {
|
||||
#ifndef BUILD_TWRPTAR_MAIN
|
||||
DataManager::SetValue("tw_file_progress", "");
|
||||
DataManager::SetValue("tw_size_progress", "");
|
||||
progress->DisplayFileCount(false);
|
||||
progress->UpdateDisplayDetails(true);
|
||||
part_settings->progress->DisplayFileCount(false);
|
||||
part_settings->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();
|
||||
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;
|
||||
sprintf(actual_filename, temp.c_str(), i, archive_count);
|
||||
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. */
|
||||
|
||||
16
twrpTar.hpp
16
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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user