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:
bigbiff
2015-12-12 18:30:21 -05:00
committed by Ethan Yonker
parent 0ac2293a9e
commit ce8f83c48d
29 changed files with 2276 additions and 391 deletions

View File

@@ -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
View 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
View 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
View 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
View 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
View 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
View 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
};

View 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

View File

@@ -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

View File

@@ -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>

View File

@@ -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));
}
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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");
}

View File

@@ -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;

View File

@@ -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.");

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;
};

View File

@@ -38,9 +38,13 @@ extern "C" {
#include <dirent.h>
#include <libgen.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <zlib.h>
#include <semaphore.h>
#include "twrpTar.hpp"
#include "twcommon.h"
#include "variables.h"
#include "adbbu/libtwadbbu.hpp"
#include "twrp-functions.hpp"
#include "gui/gui.hpp"
#include "progresstracking.hpp"
@@ -91,19 +95,30 @@ void twrpTar::Signal_Kill(int signum) {
_exit(255);
}
int twrpTar::createTarFork(ProgressTracking *progress, pid_t &fork_pid) {
void twrpTar::Set_Archive_Type(Archive_Type archive_type) {
current_archive_type = archive_type;
}
int twrpTar::createTarFork(pid_t *tar_fork_pid) {
int status = 0;
pid_t rc_pid, tar_fork_pid;
pid_t rc_pid;
int progress_pipe[2], ret;
char cmd[512];
file_count = 0;
if (part_settings->adbbackup) {
std::string Backup_FileName(tarfn);
if (!twadbbu::Write_TWFN(Backup_FileName, Total_Backup_Size, use_compression))
return -1;
}
if (pipe(progress_pipe) < 0) {
LOGINFO("Error creating progress tracking pipe\n");
gui_err("backup_error=Error creating backup.");
return -1;
}
if ((tar_fork_pid = fork()) == -1) {
if ((*tar_fork_pid = fork()) == -1) {
LOGINFO("create tar failed to fork.\n");
gui_err("backup_error=Error creating backup.");
close(progress_pipe[0]);
@@ -111,7 +126,7 @@ int twrpTar::createTarFork(ProgressTracking *progress, pid_t &fork_pid) {
return -1;
}
if (tar_fork_pid == 0) {
if (*tar_fork_pid == 0) {
// Child process
// Child closes input side of progress pipe
signal(SIGUSR2, twrpTar::Signal_Kill);
@@ -254,6 +269,7 @@ int twrpTar::createTarFork(ProgressTracking *progress, pid_t &fork_pid) {
reg.use_compression = use_compression;
reg.split_archives = 1;
reg.progress_pipe_fd = progress_pipe_fd;
reg.part_settings = part_settings;
LOGINFO("Creating unencrypted backup...\n");
if (createList((void*)&reg) != 0) {
LOGINFO("Error creating unencrypted backup.\n");
@@ -297,6 +313,7 @@ int twrpTar::createTarFork(ProgressTracking *progress, pid_t &fork_pid) {
enc[i].use_compression = use_compression;
enc[i].split_archives = 1;
enc[i].progress_pipe_fd = progress_pipe_fd;
enc[i].part_settings = part_settings;
LOGINFO("Start encryption thread %i\n", i);
ret = pthread_create(&enc_thread[i], &tattr, createList, (void*)&enc[i]);
if (ret) {
@@ -371,7 +388,8 @@ int twrpTar::createTarFork(ProgressTracking *progress, pid_t &fork_pid) {
reg.use_compression = use_compression;
reg.setsize(Total_Backup_Size);
reg.progress_pipe_fd = progress_pipe_fd;
if (Total_Backup_Size > MAX_ARCHIVE_SIZE) {
reg.part_settings = part_settings;
if (Total_Backup_Size > MAX_ARCHIVE_SIZE && !part_settings->adbbackup) {
gui_msg("split_backup=Breaking backup file into multiple archives...");
reg.split_archives = 1;
} else {
@@ -393,8 +411,6 @@ int twrpTar::createTarFork(ProgressTracking *progress, pid_t &fork_pid) {
unsigned long long fs, size_backup = 0, files_backup = 0, file_count = 0;
int first_data = 0;
fork_pid = tar_fork_pid;
// Parent closes output side
close(progress_pipe[1]);
@@ -408,14 +424,14 @@ int twrpTar::createTarFork(ProgressTracking *progress, pid_t &fork_pid) {
} else if (first_data == 1) {
// Second incoming data is total size
first_data = 2;
progress->SetSizeCount(fs, file_count);
part_settings->progress->SetSizeCount(fs, file_count);
} else {
if (fs > 0) {
size_backup += fs;
progress->UpdateSize(size_backup);
part_settings->progress->UpdateSize(size_backup);
} else { // fs == 0 increments the file counter
files_backup++;
progress->UpdateSizeCount(size_backup, files_backup);
part_settings->progress->UpdateSizeCount(size_backup, files_backup);
}
}
}
@@ -423,29 +439,31 @@ int twrpTar::createTarFork(ProgressTracking *progress, pid_t &fork_pid) {
#ifndef BUILD_TWRPTAR_MAIN
DataManager::SetValue("tw_file_progress", "");
DataManager::SetValue("tw_size_progress", "");
progress->DisplayFileCount(false);
progress->UpdateDisplayDetails(true);
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. */

View File

@@ -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;
};