From ce8f83c48d200106ff61ad530c863b15c16949d9 Mon Sep 17 00:00:00 2001 From: bigbiff Date: Sat, 12 Dec 2015 18:30:21 -0500 Subject: 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 --twrp 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 --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 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 --- partition.cpp | 269 ++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 168 insertions(+), 101 deletions(-) (limited to 'partition.cpp') diff --git a/partition.cpp b/partition.cpp index 1261a2a26..bf87de38a 100644 --- a/partition.cpp +++ b/partition.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -46,6 +47,7 @@ #include "infomanager.hpp" #include "set_metadata.h" #include "gui/gui.hpp" +#include "adbbu/libtwadbbu.hpp" extern "C" { #include "mtdutils/mtdutils.h" #include "mtdutils/mounts.h" @@ -208,7 +210,7 @@ TWPartition::TWPartition() { Backup_Name = ""; Backup_FileName = ""; MTD_Name = ""; - Backup_Method = NONE; + Backup_Method = BM_NONE; Can_Encrypt_Backup = false; Use_Userdata_Encryption = false; Has_Data_Media = false; @@ -801,16 +803,16 @@ void TWPartition::Setup_File_System(bool Display_Error) { Make_Dir(Mount_Point, Display_Error); Display_Name = Mount_Point.substr(1, Mount_Point.size() - 1); Backup_Name = Display_Name; - Backup_Method = FILES; + Backup_Method = BM_FILES; } void TWPartition::Setup_Image(bool Display_Error) { Display_Name = Mount_Point.substr(1, Mount_Point.size() - 1); Backup_Name = Display_Name; if (Current_File_System == "emmc") - Backup_Method = DD; + Backup_Method = BM_DD; else if (Current_File_System == "mtd" || Current_File_System == "bml") - Backup_Method = FLASH_UTILS; + Backup_Method = BM_FLASH_UTILS; else LOGINFO("Unhandled file system '%s' on image '%s'\n", Current_File_System.c_str(), Display_Name.c_str()); if (Find_Partition_Size()) { @@ -1598,14 +1600,13 @@ bool TWPartition::Resize() { return false; } -bool TWPartition::Backup(const string& backup_folder, pid_t &tar_fork_pid, ProgressTracking *progress) { - if (Backup_Method == FILES) { - return Backup_Tar(backup_folder, progress, tar_fork_pid); - } - else if (Backup_Method == DD) - return Backup_Image(backup_folder, progress); - else if (Backup_Method == FLASH_UTILS) - return Backup_Dump_Image(backup_folder, progress); +bool TWPartition::Backup(PartitionSettings *part_settings, pid_t *tar_fork_pid) { + if (Backup_Method == BM_FILES) + return Backup_Tar(part_settings, tar_fork_pid); + else if (Backup_Method == BM_DD) + return Backup_Image(part_settings); + else if (Backup_Method == BM_FLASH_UTILS) + return Backup_Dump_Image(part_settings); LOGERR("Unknown backup method for '%s'\n", Mount_Point.c_str()); return false; } @@ -1658,53 +1659,49 @@ bool TWPartition::Check_MD5(string restore_folder) { return false; } -bool TWPartition::Restore(const string& restore_folder, ProgressTracking *progress) { - string Restore_File_System; - +bool TWPartition::Restore(PartitionSettings *part_settings) { TWFunc::GUI_Operation_Text(TW_RESTORE_TEXT, Display_Name, gui_parse_text("{@restoring_hdr}")); - LOGINFO("Restore filename is: %s\n", Backup_FileName.c_str()); + LOGINFO("Restore filename is: %s/%s\n", part_settings->Restore_Name.c_str(), part_settings->Backup_FileName.c_str()); - Restore_File_System = Get_Restore_File_System(restore_folder); + string Restore_File_System = Get_Restore_File_System(part_settings); if (Is_File_System(Restore_File_System)) - return Restore_Tar(restore_folder, Restore_File_System, progress); - else if (Is_Image(Restore_File_System)) { - return Restore_Image(restore_folder, Restore_File_System, progress); - } + return Restore_Tar(part_settings); + else if (Is_Image(Restore_File_System)) + return Restore_Image(part_settings); LOGERR("Unknown restore method for '%s'\n", Mount_Point.c_str()); return false; } -string TWPartition::Get_Restore_File_System(const string& restore_folder) { +string TWPartition::Get_Restore_File_System(PartitionSettings *part_settings) { size_t first_period, second_period; string Restore_File_System; // Parse backup filename to extract the file system before wiping - first_period = Backup_FileName.find("."); + first_period = part_settings->Backup_FileName.find("."); if (first_period == string::npos) { LOGERR("Unable to find file system (first period).\n"); return string(); } - Restore_File_System = Backup_FileName.substr(first_period + 1, Backup_FileName.size() - first_period - 1); + Restore_File_System = part_settings->Backup_FileName.substr(first_period + 1, part_settings->Backup_FileName.size() - first_period - 1); second_period = Restore_File_System.find("."); if (second_period == string::npos) { LOGERR("Unable to find file system (second period).\n"); return string(); } Restore_File_System.resize(second_period); - LOGINFO("Restore file system is: '%s'.\n", Restore_File_System.c_str()); return Restore_File_System; } string TWPartition::Backup_Method_By_Name() { - if (Backup_Method == NONE) + if (Backup_Method == BM_NONE) return "none"; - else if (Backup_Method == FILES) + else if (Backup_Method == BM_FILES) return "files"; - else if (Backup_Method == DD) + else if (Backup_Method == BM_DD) return "dd"; - else if (Backup_Method == FLASH_UTILS) + else if (Backup_Method == BM_FLASH_UTILS) return "flash_utils"; else return "undefined"; @@ -2141,7 +2138,7 @@ bool TWPartition::Wipe_Data_Without_Wiping_Media_Func(const string& parent __unu return false; } -bool TWPartition::Backup_Tar(const string& backup_folder, ProgressTracking *progress, pid_t &tar_fork_pid) { +bool TWPartition::Backup_Tar(PartitionSettings *part_settings, pid_t *tar_fork_pid) { string Full_FileName; twrpTar tar; @@ -2169,72 +2166,114 @@ bool TWPartition::Backup_Tar(const string& backup_folder, ProgressTracking *prog #endif Backup_FileName = Backup_Name + "." + Current_File_System + ".win"; - Full_FileName = backup_folder + "/" + Backup_FileName; + Full_FileName = part_settings->Full_Backup_Path + Backup_FileName; tar.has_data_media = Has_Data_Media; - Full_FileName = backup_folder + "/" + Backup_FileName; + tar.part_settings = part_settings; tar.setdir(Backup_Path); tar.setfn(Full_FileName); tar.setsize(Backup_Size); tar.partition_name = Backup_Name; - tar.backup_folder = backup_folder; - if (tar.createTarFork(progress, tar_fork_pid) != 0) + tar.backup_folder = part_settings->Full_Backup_Path; + if (tar.createTarFork(tar_fork_pid) != 0) return false; return true; } -bool TWPartition::Backup_Image(const string& backup_folder, ProgressTracking *progress) { - string Full_FileName; +bool TWPartition::Backup_Image(PartitionSettings *part_settings) { + string Full_FileName, adb_file_name; + int adb_control_bu_fd, compressed; TWFunc::GUI_Operation_Text(TW_BACKUP_TEXT, Display_Name, gui_parse_text("{@backing}")); gui_msg(Msg("backing_up=Backing up {1}...")(Backup_Display_Name)); Backup_FileName = Backup_Name + "." + Current_File_System + ".win"; - Full_FileName = backup_folder + "/" + Backup_FileName; - if (!Raw_Read_Write(Actual_Block_Device, Full_FileName, Backup_Size, progress)) - return false; + if (part_settings->adbbackup) { + Full_FileName = TW_ADB_BACKUP; + adb_file_name = part_settings->Full_Backup_Path + "/" + Backup_FileName; + } + else + Full_FileName = part_settings->Full_Backup_Path + "/" + Backup_FileName; - tw_set_default_metadata(Full_FileName.c_str()); - if (TWFunc::Get_File_Size(Full_FileName) == 0) { - gui_msg(Msg(msg::kError, "backup_size=Backup file size for '{1}' is 0 bytes.")(Full_FileName)); + part_settings->total_restore_size = Backup_Size; + + if (part_settings->adbbackup) { + if (!twadbbu::Write_TWIMG(adb_file_name, Backup_Size)) + return false; + } + + if (!Raw_Read_Write(part_settings)) return false; + + if (part_settings->adbbackup) { + if (!twadbbu::Write_TWEOF()) + return false; } return true; } -bool TWPartition::Raw_Read_Write(const string& input_file, const string& output_file, const unsigned long long input_size, ProgressTracking *progress) { - unsigned long long RW_Block_Size, Remain; - int src_fd = -1, dest_fd = -1, bs; +bool TWPartition::Raw_Read_Write(PartitionSettings *part_settings) { + unsigned long long RW_Block_Size, Remain = Backup_Size; + int src_fd = -1, dest_fd = -1; + ssize_t bs; bool ret = false; void* buffer = NULL; unsigned long long backedup_size = 0; + string srcfn, destfn; - RW_Block_Size = 1048576LLU; // 1MB - Remain = input_size; + if (part_settings->PM_Method == PM_BACKUP) { + srcfn = Actual_Block_Device; + if (part_settings->adbbackup) + destfn = TW_ADB_BACKUP; + else + destfn = part_settings->Full_Backup_Path + part_settings->Backup_FileName; + } + else { + destfn = Actual_Block_Device; + if (part_settings->adbbackup) { + srcfn = TW_ADB_RESTORE; + } else { + srcfn = part_settings->Restore_Name + "/" + part_settings->Backup_FileName; + Remain = TWFunc::Get_File_Size(srcfn); + } + } - src_fd = open(input_file.c_str(), O_RDONLY | O_LARGEFILE); + src_fd = open(srcfn.c_str(), O_RDONLY | O_LARGEFILE); if (src_fd < 0) { - gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(input_file)(strerror(errno))); + gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(srcfn.c_str())(strerror(errno))); return false; } - dest_fd = open(output_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE, S_IRUSR | S_IWUSR); + + dest_fd = open(destfn.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE, S_IRUSR | S_IWUSR); if (dest_fd < 0) { - gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(output_file)(strerror(errno))); + gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(destfn.c_str())(strerror(errno))); goto exit; } - bs = (int)(RW_Block_Size); + + LOGINFO("Reading '%s', writing '%s'\n", srcfn.c_str(), destfn.c_str()); + + if (part_settings->adbbackup) { + RW_Block_Size = MAX_ADB_READ; + bs = MAX_ADB_READ; + } + else { + RW_Block_Size = 1048576LLU; // 1MB + bs = (ssize_t)(RW_Block_Size); + } + buffer = malloc((size_t)bs); if (!buffer) { LOGINFO("Raw_Read_Write failed to malloc\n"); goto exit; } - LOGINFO("Reading '%s', writing '%s'\n", input_file.c_str(), output_file.c_str()); - if (progress) - progress->SetPartitionSize(input_size); + + if (part_settings->progress) + part_settings->progress->SetPartitionSize(part_settings->total_restore_size); + while (Remain > 0) { if (Remain < RW_Block_Size) - bs = (int)(Remain); - if (read(src_fd, buffer, bs) != bs) { + bs = (ssize_t)(Remain); + if (read(src_fd, buffer, bs) != bs) { LOGINFO("Error reading source fd (%s)\n", strerror(errno)); goto exit; } @@ -2243,14 +2282,14 @@ bool TWPartition::Raw_Read_Write(const string& input_file, const string& output_ goto exit; } backedup_size += (unsigned long long)(bs); - Remain -= (unsigned long long)(bs); - if (progress) - progress->UpdateSize(backedup_size); + Remain = Remain - (unsigned long long)(bs); + if (part_settings->progress) + part_settings->progress->UpdateSize(backedup_size); if (PartitionManager.Check_Backup_Cancel() != 0) goto exit; } - if (progress) - progress->UpdateDisplayDetails(true); + if (part_settings->progress) + part_settings->progress->UpdateDisplayDetails(true); fsync(dest_fd); ret = true; exit: @@ -2263,19 +2302,22 @@ exit: return ret; } -bool TWPartition::Backup_Dump_Image(const string& backup_folder, ProgressTracking *progress) { +bool TWPartition::Backup_Dump_Image(PartitionSettings *part_settings) { string Full_FileName, Command; + int use_compression, adb_control_bu_fd; + unsigned long long compressed; TWFunc::GUI_Operation_Text(TW_BACKUP_TEXT, Display_Name, gui_parse_text("{@backing}")); gui_msg(Msg("backing_up=Backing up {1}...")(Backup_Display_Name)); - if (progress) - progress->SetPartitionSize(Backup_Size); + if (part_settings->progress) + part_settings->progress->SetPartitionSize(Backup_Size); Backup_FileName = Backup_Name + "." + Current_File_System + ".win"; - Full_FileName = backup_folder + "/" + Backup_FileName; + Full_FileName = part_settings->Full_Backup_Path + "/" + Backup_FileName; Command = "dump_image " + MTD_Name + " '" + Full_FileName + "'"; + LOGINFO("Backup command: '%s'\n", Command.c_str()); TWFunc::Exec_Cmd(Command); tw_set_default_metadata(Full_FileName.c_str()); @@ -2284,23 +2326,26 @@ bool TWPartition::Backup_Dump_Image(const string& backup_folder, ProgressTrackin gui_msg(Msg(msg::kError, "backup_size=Backup file size for '{1}' is 0 bytes.")(Full_FileName)); return false; } - if (progress) - progress->UpdateSize(Backup_Size); + if (part_settings->progress) + part_settings->progress->UpdateSize(Backup_Size); + return true; } -unsigned long long TWPartition::Get_Restore_Size(const string& restore_folder) { - InfoManager restore_info(restore_folder + "/" + Backup_Name + ".info"); - if (restore_info.LoadValues() == 0) { - if (restore_info.GetValue("backup_size", Restore_Size) == 0) { - LOGINFO("Read info file, restore size is %llu\n", Restore_Size); - return Restore_Size; +unsigned long long TWPartition::Get_Restore_Size(PartitionSettings *part_settings) { + if (!part_settings->adbbackup) { + InfoManager restore_info(part_settings->Restore_Name + "/" + Backup_Name + ".info"); + if (restore_info.LoadValues() == 0) { + if (restore_info.GetValue("backup_size", Restore_Size) == 0) { + LOGINFO("Read info file, restore size is %llu\n", Restore_Size); + return Restore_Size; + } } } - string Full_FileName, Restore_File_System = Get_Restore_File_System(restore_folder); - Full_FileName = restore_folder + "/" + Backup_FileName; + string Full_FileName, Restore_File_System = Get_Restore_File_System(part_settings); + Full_FileName = part_settings->Restore_Name + "/" + Backup_FileName; if (Is_Image(Restore_File_System)) { Restore_Size = TWFunc::Get_File_Size(Full_FileName); return Restore_Size; @@ -2309,7 +2354,7 @@ unsigned long long TWPartition::Get_Restore_Size(const string& restore_folder) { twrpTar tar; tar.setdir(Backup_Path); tar.setfn(Full_FileName); - tar.backup_name = Backup_Name; + tar.backup_name = Full_FileName; #ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS string Password; DataManager::GetValue("tw_restore_password", Password); @@ -2317,14 +2362,16 @@ unsigned long long TWPartition::Get_Restore_Size(const string& restore_folder) { tar.setpassword(Password); #endif tar.partition_name = Backup_Name; - tar.backup_folder = restore_folder; + tar.backup_folder = part_settings->Restore_Name; + tar.part_settings = part_settings; Restore_Size = tar.get_size(); return Restore_Size; } -bool TWPartition::Restore_Tar(const string& restore_folder, const string& Restore_File_System, ProgressTracking *progress) { +bool TWPartition::Restore_Tar(PartitionSettings *part_settings) { string Full_FileName; bool ret = false; + string Restore_File_System = Get_Restore_File_System(part_settings); if (Has_Android_Secure) { if (!Wipe_AndSec()) @@ -2347,8 +2394,9 @@ bool TWPartition::Restore_Tar(const string& restore_folder, const string& Restor if (!ReMount_RW(true)) return false; - Full_FileName = restore_folder + "/" + Backup_FileName; + Full_FileName = part_settings->Restore_Name + "/" + part_settings->Backup_FileName; twrpTar tar; + tar.part_settings = part_settings; tar.setdir(Backup_Path); tar.setfn(Full_FileName); tar.backup_name = Backup_Name; @@ -2358,8 +2406,8 @@ bool TWPartition::Restore_Tar(const string& restore_folder, const string& Restor if (!Password.empty()) tar.setpassword(Password); #endif - progress->SetPartitionSize(Get_Restore_Size(restore_folder)); - if (tar.extractTarFork(progress) != 0) + part_settings->progress->SetPartitionSize(Get_Restore_Size(part_settings)); + if (tar.extractTarFork() != 0) ret = false; else ret = true; @@ -2389,19 +2437,30 @@ bool TWPartition::Restore_Tar(const string& restore_folder, const string& Restor return ret; } -bool TWPartition::Restore_Image(const string& restore_folder, const string& Restore_File_System, ProgressTracking *progress) { +bool TWPartition::Restore_Image(PartitionSettings *part_settings) { string Full_FileName; + string Restore_File_System = Get_Restore_File_System(part_settings); TWFunc::GUI_Operation_Text(TW_RESTORE_TEXT, Backup_Display_Name, gui_parse_text("{@restoring_hdr}")); gui_msg(Msg("restoring=Restoring {1}...")(Backup_Display_Name)); - Full_FileName = restore_folder + "/" + Backup_FileName; + + if (part_settings->adbbackup) + Full_FileName = TW_ADB_RESTORE; + else + Full_FileName = part_settings->Full_Backup_Path + part_settings->Backup_FileName; if (Restore_File_System == "emmc") { - unsigned long long file_size = (unsigned long long)(TWFunc::Get_File_Size(Full_FileName)); - if (!Raw_Read_Write(Full_FileName, Actual_Block_Device, file_size, progress)) + if (!part_settings->adbbackup) + part_settings->total_restore_size = (uint64_t)(TWFunc::Get_File_Size(Full_FileName)); + if (!Raw_Read_Write(part_settings)) return false; } else if (Restore_File_System == "mtd" || Restore_File_System == "bml") { - if (!Flash_Image_FI(Full_FileName, progress)) + if (!Flash_Image_FI(Full_FileName, part_settings->progress)) + return false; + } + + if (part_settings->adbbackup) { + if (!twadbbu::Write_TWEOF()) return false; } return true; @@ -2544,12 +2603,14 @@ uint64_t TWPartition::Get_Max_FileSize() { return maxFileSize - 1; } -bool TWPartition::Flash_Image(const string& Filename) { - string Restore_File_System; +bool TWPartition::Flash_Image(PartitionSettings *part_settings) { + string Restore_File_System, full_filename; + + full_filename = part_settings->Restore_Name + "/" + part_settings->Backup_FileName; - LOGINFO("Image filename is: %s\n", Filename.c_str()); + LOGINFO("Image filename is: %s\n", part_settings->Backup_FileName.c_str()); - if (Backup_Method == FILES) { + if (Backup_Method == BM_FILES) { LOGERR("Cannot flash images to file systems\n"); return false; } else if (!Can_Flash_Img) { @@ -2560,22 +2621,23 @@ bool TWPartition::Flash_Image(const string& Filename) { LOGERR("Unable to find partition size for '%s'\n", Mount_Point.c_str()); return false; } - unsigned long long image_size = TWFunc::Get_File_Size(Filename); + unsigned long long image_size = TWFunc::Get_File_Size(full_filename); if (image_size > Size) { LOGINFO("Size (%llu bytes) of image '%s' is larger than target device '%s' (%llu bytes)\n", - image_size, Filename.c_str(), Actual_Block_Device.c_str(), Size); + image_size, part_settings->Backup_FileName.c_str(), Actual_Block_Device.c_str(), Size); gui_err("img_size_err=Size of image is larger than target device"); return false; } - if (Backup_Method == DD) { - if (Is_Sparse_Image(Filename)) { - return Flash_Sparse_Image(Filename); + if (Backup_Method == BM_DD) { + if (!part_settings->adbbackup) { + if (Is_Sparse_Image(full_filename)) { + return Flash_Sparse_Image(full_filename); + } } - unsigned long long file_size = (unsigned long long)(TWFunc::Get_File_Size(Filename)); - ProgressTracking pt(file_size); - return Raw_Read_Write(Filename, Actual_Block_Device, file_size, &pt); - } else if (Backup_Method == FLASH_UTILS) { - return Flash_Image_FI(Filename, NULL); + unsigned long long file_size = (unsigned long long)(TWFunc::Get_File_Size(full_filename)); + return Raw_Read_Write(part_settings); + } else if (Backup_Method == BM_FLASH_UTILS) { + return Flash_Image_FI(full_filename, NULL); } } @@ -2590,6 +2652,7 @@ bool TWPartition::Is_Sparse_Image(const string& Filename) { gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(Filename)(strerror(errno))); return false; } + if (read(fd, &magic, sizeof(magic)) != sizeof(magic)) { gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(Filename)(strerror(errno))); close(fd); @@ -2637,6 +2700,10 @@ void TWPartition::Change_Mount_Read_Only(bool new_value) { Mount_Read_Only = new_value; } +bool TWPartition::Is_Read_Only() { + return Mount_Read_Only; +} + int TWPartition::Check_Lifetime_Writes() { bool original_read_only = Mount_Read_Only; int ret = 1; -- cgit v1.2.3