diff options
author | Ethan Yonker <dees_troy@teamw.in> | 2016-02-25 20:47:30 +0100 |
---|---|---|
committer | Dees Troy <dees_troy@teamw.in> | 2016-03-31 16:44:24 +0200 |
commit | 472f506817bb1af2fceb039ba148d15723944562 (patch) | |
tree | 187516086121c42b1b671f69b4fc252fe5498b1c | |
parent | DataManager Updates (diff) | |
download | android_bootable_recovery-472f506817bb1af2fceb039ba148d15723944562.tar android_bootable_recovery-472f506817bb1af2fceb039ba148d15723944562.tar.gz android_bootable_recovery-472f506817bb1af2fceb039ba148d15723944562.tar.bz2 android_bootable_recovery-472f506817bb1af2fceb039ba148d15723944562.tar.lz android_bootable_recovery-472f506817bb1af2fceb039ba148d15723944562.tar.xz android_bootable_recovery-472f506817bb1af2fceb039ba148d15723944562.tar.zst android_bootable_recovery-472f506817bb1af2fceb039ba148d15723944562.zip |
-rw-r--r-- | Android.mk | 1 | ||||
-rw-r--r-- | gui/twmsg.cpp | 7 | ||||
-rw-r--r-- | libtar/extract.c | 13 | ||||
-rw-r--r-- | partition.cpp | 231 | ||||
-rw-r--r-- | partitionmanager.cpp | 56 | ||||
-rw-r--r-- | partitions.hpp | 38 | ||||
-rw-r--r-- | progresstracking.cpp | 108 | ||||
-rw-r--r-- | progresstracking.hpp | 54 | ||||
-rw-r--r-- | tarWrite.c | 19 | ||||
-rw-r--r-- | tarWrite.h | 7 | ||||
-rw-r--r-- | twrp-functions.cpp | 42 | ||||
-rw-r--r-- | twrp-functions.hpp | 6 | ||||
-rw-r--r-- | twrpDigest.cpp | 4 | ||||
-rw-r--r-- | twrpDigest.hpp | 4 | ||||
-rw-r--r-- | twrpTar.cpp | 83 | ||||
-rw-r--r-- | twrpTar.h | 1 | ||||
-rw-r--r-- | twrpTar.hpp | 8 | ||||
-rw-r--r-- | twrpTarMain/Android.mk | 13 | ||||
-rw-r--r-- | twrpTarMain/twrpTarMain.cpp | 50 |
19 files changed, 507 insertions, 238 deletions
diff --git a/Android.mk b/Android.mk index 08dbf6e16..b2c06e851 100644 --- a/Android.mk +++ b/Android.mk @@ -54,6 +54,7 @@ LOCAL_SRC_FILES += \ data.cpp \ partition.cpp \ partitionmanager.cpp \ + progresstracking.cpp \ twinstall.cpp \ twrp-functions.cpp \ openrecoveryscript.cpp \ diff --git a/gui/twmsg.cpp b/gui/twmsg.cpp index 9fe9e5a94..57f192234 100644 --- a/gui/twmsg.cpp +++ b/gui/twmsg.cpp @@ -89,13 +89,16 @@ public: resname = name.substr(0, pos); default_value = name.substr(pos + 1); } +#ifndef BUILD_TWRPTAR_MAIN const ResourceManager* res = PageManager::GetResources(); if (res) { if (default_value.empty()) return res->FindString(resname); else return res->FindString(resname, default_value); - } else if (!default_value.empty()) { + } +#endif + if (!default_value.empty()) { return default_value; } return name; @@ -112,10 +115,12 @@ class DataLookup : public StringLookup public: virtual std::string operator()(const std::string& name) const { +#ifndef BUILD_TWRPTAR_MAIN std::string value; if (DataManager::GetValue(name, value) == 0) return value; else +#endif return ""; } }; diff --git a/libtar/extract.c b/libtar/extract.c index 257e140d5..6a63ff738 100644 --- a/libtar/extract.c +++ b/libtar/extract.c @@ -32,6 +32,8 @@ # include "selinux/selinux.h" #endif +const unsigned long long progress_size = (unsigned long long)(T_BLOCKSIZE); + static int tar_set_file_perms(TAR *t, const char *realname) { @@ -245,6 +247,11 @@ tar_extract_regfile(TAR *t, const char *realname, const int *progress_fd) close(fdout); return -1; } + else + { + if (*progress_fd != 0) + write(*progress_fd, &progress_size, sizeof(progress_size)); + } } /* close output file */ @@ -255,12 +262,6 @@ tar_extract_regfile(TAR *t, const char *realname, const int *progress_fd) printf("### done extracting %s\n", filename); #endif - if (*progress_fd != 0) - { - unsigned long long file_size = (unsigned long long)(size); - write(*progress_fd, &file_size, sizeof(file_size)); - } - return 0; } diff --git a/partition.cpp b/partition.cpp index 188a739ea..12d4ad0da 100644 --- a/partition.cpp +++ b/partition.cpp @@ -1,5 +1,5 @@ /* - Copyright 2013 TeamWin + Copyright 2013 to 2016 TeamWin This file is part of TWRP/TeamWin Recovery Project. TWRP is free software: you can redistribute it and/or modify @@ -28,6 +28,7 @@ #include <iostream> #include <sstream> #include <sys/param.h> +#include <fcntl.h> #ifdef TW_INCLUDE_CRYPTO #include "cutils/properties.h" @@ -69,6 +70,7 @@ extern "C" { #include <linux/xattr.h> #endif #include <sparse_format.h> +#include "progresstracking.hpp" using namespace std; @@ -1466,14 +1468,14 @@ bool TWPartition::Resize() { return false; } -bool TWPartition::Backup(string backup_folder, const unsigned long long *overall_size, const unsigned long long *other_backups_size, pid_t &tar_fork_pid) { +bool TWPartition::Backup(const string& backup_folder, pid_t &tar_fork_pid, ProgressTracking *progress) { if (Backup_Method == FILES) { - return Backup_Tar(backup_folder, overall_size, other_backups_size, tar_fork_pid); + return Backup_Tar(backup_folder, progress, tar_fork_pid); } else if (Backup_Method == DD) - return Backup_DD(backup_folder); + return Backup_Image(backup_folder, progress); else if (Backup_Method == FLASH_UTILS) - return Backup_Dump_Image(backup_folder); + return Backup_Dump_Image(backup_folder, progress); LOGERR("Unknown backup method for '%s'\n", Mount_Point.c_str()); return false; } @@ -1526,7 +1528,7 @@ bool TWPartition::Check_MD5(string restore_folder) { return false; } -bool TWPartition::Restore(string restore_folder, const unsigned long long *total_restore_size, unsigned long long *already_restored_size) { +bool TWPartition::Restore(const string& restore_folder, ProgressTracking *progress) { string Restore_File_System; TWFunc::GUI_Operation_Text(TW_RESTORE_TEXT, Display_Name, gui_parse_text("{@restoring_hdr}")); @@ -1535,16 +1537,16 @@ bool TWPartition::Restore(string restore_folder, const unsigned long long *total Restore_File_System = Get_Restore_File_System(restore_folder); if (Is_File_System(Restore_File_System)) - return Restore_Tar(restore_folder, Restore_File_System, total_restore_size, already_restored_size); + return Restore_Tar(restore_folder, Restore_File_System, progress); else if (Is_Image(Restore_File_System)) { - return Restore_Image(restore_folder, total_restore_size, already_restored_size, Restore_File_System); + return Restore_Image(restore_folder, Restore_File_System, progress); } LOGERR("Unknown restore method for '%s'\n", Mount_Point.c_str()); return false; } -string TWPartition::Get_Restore_File_System(string restore_folder) { +string TWPartition::Get_Restore_File_System(const string& restore_folder) { size_t first_period, second_period; string Restore_File_System; @@ -2009,14 +2011,9 @@ bool TWPartition::Wipe_Data_Without_Wiping_Media_Func(const string& parent __unu return false; } -bool TWPartition::Backup_Tar(string backup_folder, const unsigned long long *overall_size, const unsigned long long *other_backups_size, pid_t &tar_fork_pid) { - char back_name[255], split_index[5]; - string Full_FileName, Split_FileName, Tar_Args, Command; - int use_compression, use_encryption = 0, index, backup_count; - struct stat st; - unsigned long long total_bsize = 0, file_size; +bool TWPartition::Backup_Tar(const string& backup_folder, ProgressTracking *progress, pid_t &tar_fork_pid) { + string Full_FileName; twrpTar tar; - vector <string> files; if (!Mount(true)) return false; @@ -2024,25 +2021,24 @@ bool TWPartition::Backup_Tar(string backup_folder, const unsigned long long *ove TWFunc::GUI_Operation_Text(TW_BACKUP_TEXT, Backup_Display_Name, "Backing Up"); gui_msg(Msg("backing_up=Backing up {1}...")(Backup_Display_Name)); - DataManager::GetValue(TW_USE_COMPRESSION_VAR, use_compression); - tar.use_compression = use_compression; + DataManager::GetValue(TW_USE_COMPRESSION_VAR, tar.use_compression); #ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS - DataManager::GetValue("tw_encrypt_backup", use_encryption); - if (use_encryption && Can_Encrypt_Backup) { - tar.use_encryption = use_encryption; - if (Use_Userdata_Encryption) - tar.userdata_encryption = use_encryption; - string Password; - DataManager::GetValue("tw_backup_password", Password); - tar.setpassword(Password); - } else { - use_encryption = false; + if (Can_Encrypt_Backup) { + DataManager::GetValue("tw_encrypt_backup", tar.use_encryption); + if (tar.use_encryption) { + if (Use_Userdata_Encryption) + tar.userdata_encryption = tar.use_encryption; + string Password; + DataManager::GetValue("tw_backup_password", Password); + tar.setpassword(Password); + } else { + tar.use_encryption = 0; + } } #endif - sprintf(back_name, "%s.%s.win", Backup_Name.c_str(), Current_File_System.c_str()); - Backup_FileName = back_name; + Backup_FileName = Backup_Name + "." + Current_File_System + ".win"; Full_FileName = backup_folder + "/" + Backup_FileName; tar.has_data_media = Has_Data_Media; Full_FileName = backup_folder + "/" + Backup_FileName; @@ -2051,39 +2047,23 @@ bool TWPartition::Backup_Tar(string backup_folder, const unsigned long long *ove tar.setsize(Backup_Size); tar.partition_name = Backup_Name; tar.backup_folder = backup_folder; - if (tar.createTarFork(overall_size, other_backups_size, tar_fork_pid) != 0) + if (tar.createTarFork(progress, tar_fork_pid) != 0) return false; return true; } -bool TWPartition::Backup_DD(string backup_folder) { - char back_name[255], block_size[32], dd_count[32]; - string Full_FileName, Command, DD_BS, DD_COUNT; - int use_compression; - unsigned long long DD_Block_Size, DD_Count; - - DD_Block_Size = 16 * 1024 * 1024; - while (Backup_Size % DD_Block_Size != 0) DD_Block_Size >>= 1; - - DD_Count = Backup_Size / DD_Block_Size; - - sprintf(dd_count, "%llu", DD_Count); - DD_COUNT = dd_count; - - sprintf(block_size, "%llu", DD_Block_Size); - DD_BS = block_size; +bool TWPartition::Backup_Image(const string& backup_folder, ProgressTracking *progress) { + string Full_FileName; TWFunc::GUI_Operation_Text(TW_BACKUP_TEXT, Display_Name, gui_parse_text("{@backing}")); gui_msg(Msg("backing_up=Backing up {1}...")(Backup_Display_Name)); - sprintf(back_name, "%s.%s.win", Backup_Name.c_str(), Current_File_System.c_str()); - Backup_FileName = back_name; - + Backup_FileName = Backup_Name + "." + Current_File_System + ".win"; Full_FileName = backup_folder + "/" + Backup_FileName; - Command = "dd if=" + Actual_Block_Device + " of='" + Full_FileName + "'" + " bs=" + DD_BS + " count=" + DD_COUNT; - LOGINFO("Backup command: '%s'\n", Command.c_str()); - TWFunc::Exec_Cmd(Command); + if (!Raw_Read_Write(Actual_Block_Device, Full_FileName, Backup_Size, progress)) + 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)); @@ -2092,17 +2072,77 @@ bool TWPartition::Backup_DD(string backup_folder) { return true; } -bool TWPartition::Backup_Dump_Image(string backup_folder) { - char back_name[255]; +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 ret = false; + void* buffer = NULL; + unsigned long long backedup_size = 0; + + RW_Block_Size = 1048576LLU; // 1MB + Remain = input_size; + + src_fd = open(input_file.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))); + return false; + } + dest_fd = open(output_file.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))); + goto exit; + } + bs = (int)(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); + while (Remain > 0) { + if (Remain < RW_Block_Size) + bs = (int)(Remain); + if (read(src_fd, buffer, bs) != bs) { + LOGINFO("Error reading source fd (%s)\n", strerror(errno)); + goto exit; + } + if (write(dest_fd, buffer, bs) != bs) { + LOGINFO("Error writing destination fd (%s)\n", strerror(errno)); + goto exit; + } + backedup_size += (unsigned long long)(bs); + Remain -= (unsigned long long)(bs); + if (progress) + progress->UpdateSize(backedup_size); + if (PartitionManager.Check_Backup_Cancel() != 0) + goto exit; + } + if (progress) + progress->UpdateDisplayDetails(true); + fsync(dest_fd); + ret = true; +exit: + if (src_fd >= 0) + close(src_fd); + if (dest_fd >= 0) + close(dest_fd); + if (buffer) + free(buffer); + return ret; +} + +bool TWPartition::Backup_Dump_Image(const string& backup_folder, ProgressTracking *progress) { string Full_FileName, Command; - int use_compression; TWFunc::GUI_Operation_Text(TW_BACKUP_TEXT, Display_Name, gui_parse_text("{@backing}")); gui_msg(Msg("backing_up=Backing up {1}...")(Backup_Display_Name)); - sprintf(back_name, "%s.%s.win", Backup_Name.c_str(), Current_File_System.c_str()); - Backup_FileName = back_name; + if (progress) + progress->SetPartitionSize(Backup_Size); + Backup_FileName = Backup_Name + "." + Current_File_System + ".win"; Full_FileName = backup_folder + "/" + Backup_FileName; Command = "dump_image " + MTD_Name + " '" + Full_FileName + "'"; @@ -2114,10 +2154,12 @@ bool TWPartition::Backup_Dump_Image(string backup_folder) { 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); return true; } -unsigned long long TWPartition::Get_Restore_Size(string restore_folder) { +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) { @@ -2150,10 +2192,8 @@ unsigned long long TWPartition::Get_Restore_Size(string restore_folder) { return Restore_Size; } -bool TWPartition::Restore_Tar(string restore_folder, string Restore_File_System, const unsigned long long *total_restore_size, unsigned long long *already_restored_size) { - string Full_FileName, Command; - int index = 0; - char split_index[5]; +bool TWPartition::Restore_Tar(const string& restore_folder, const string& Restore_File_System, ProgressTracking *progress) { + string Full_FileName; bool ret = false; if (Has_Android_Secure) { @@ -2188,7 +2228,8 @@ bool TWPartition::Restore_Tar(string restore_folder, string Restore_File_System, if (!Password.empty()) tar.setpassword(Password); #endif - if (tar.extractTarFork(total_restore_size, already_restored_size) != 0) + progress->SetPartitionSize(Get_Restore_Size(restore_folder)); + if (tar.extractTarFork(progress) != 0) ret = false; else ret = true; @@ -2218,28 +2259,21 @@ bool TWPartition::Restore_Tar(string restore_folder, string Restore_File_System, return ret; } -bool TWPartition::Restore_Image(string restore_folder, const unsigned long long *total_restore_size, unsigned long long *already_restored_size, string Restore_File_System) { +bool TWPartition::Restore_Image(const string& restore_folder, const string& Restore_File_System, ProgressTracking *progress) { string Full_FileName; - double display_percent, progress_percent; - char size_progress[1024]; 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 (Restore_File_System == "emmc") { - if (!Flash_Image_DD(Full_FileName)) + 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)) return false; } else if (Restore_File_System == "mtd" || Restore_File_System == "bml") { - if (!Flash_Image_FI(Full_FileName)) + if (!Flash_Image_FI(Full_FileName, progress)) return false; } - display_percent = (double)(Restore_Size + *already_restored_size) / (double)(*total_restore_size) * 100; - sprintf(size_progress, "%lluMB of %lluMB, %i%%", (Restore_Size + *already_restored_size) / 1048576, *total_restore_size / 1048576, (int)(display_percent)); - DataManager::SetValue("tw_size_progress", size_progress); - progress_percent = (display_percent / 100); - DataManager::SetProgress((float)(progress_percent)); - *already_restored_size += Restore_Size; return true; } @@ -2380,7 +2414,7 @@ uint64_t TWPartition::Get_Max_FileSize() { return maxFileSize - 1; } -bool TWPartition::Flash_Image(string Filename) { +bool TWPartition::Flash_Image(const string& Filename) { string Restore_File_System; LOGINFO("Image filename is: %s\n", Filename.c_str()); @@ -2403,21 +2437,23 @@ bool TWPartition::Flash_Image(string Filename) { gui_err("img_size_err=Size of image is larger than target device"); return false; } - if (Backup_Method == DD) - return Flash_Image_DD(Filename); - else if (Backup_Method == FLASH_UTILS) - return Flash_Image_FI(Filename); + if (Backup_Method == DD) { + if (Is_Sparse_Image(Filename)) { + return Flash_Sparse_Image(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); + } } LOGERR("Unknown flash method for '%s'\n", Mount_Point.c_str()); return false; } -bool TWPartition::Flash_Image_DD(string Filename) { - string Command; - - gui_msg(Msg("flashing=Flashing {1}...")(Display_Name)); - +bool TWPartition::Is_Sparse_Image(const string& Filename) { uint32_t magic = 0; int fd = open(Filename.c_str(), O_RDONLY); if (fd < 0) { @@ -2430,20 +2466,31 @@ bool TWPartition::Flash_Image_DD(string Filename) { return false; } close(fd); - if (magic == SPARSE_HEADER_MAGIC) { - Command = "simg2img '" + Filename + "' " + Actual_Block_Device; - } else { - Command = "dd bs=8388608 if='" + Filename + "' of=" + Actual_Block_Device; - } + if (magic == SPARSE_HEADER_MAGIC) + return true; + return false; +} + +bool TWPartition::Flash_Sparse_Image(const string& Filename) { + string Command; + + gui_msg(Msg("flashing=Flashing {1}...")(Display_Name)); + + Command = "simg2img '" + Filename + "' '" + Actual_Block_Device + "'"; LOGINFO("Flash command: '%s'\n", Command.c_str()); TWFunc::Exec_Cmd(Command); return true; } -bool TWPartition::Flash_Image_FI(string Filename) { +bool TWPartition::Flash_Image_FI(const string& Filename, ProgressTracking *progress) { string Command; + unsigned long long file_size; gui_msg(Msg("flashing=Flashing {1}...")(Display_Name)); + if (progress) { + file_size = (unsigned long long)(TWFunc::Get_File_Size(Filename)); + progress->SetPartitionSize(file_size); + } // Sometimes flash image doesn't like to flash due to the first 2KB matching, so we erase first to ensure that it flashes Command = "erase_image " + MTD_Name; LOGINFO("Erase command: '%s'\n", Command.c_str()); @@ -2451,6 +2498,8 @@ bool TWPartition::Flash_Image_FI(string Filename) { Command = "flash_image " + MTD_Name + " '" + Filename + "'"; LOGINFO("Flash command: '%s'\n", Command.c_str()); TWFunc::Exec_Cmd(Command); + if (progress) + progress->UpdateSize(file_size); return true; } diff --git a/partitionmanager.cpp b/partitionmanager.cpp index 1c7af5e6c..0034feac7 100644 --- a/partitionmanager.cpp +++ b/partitionmanager.cpp @@ -1,5 +1,5 @@ /* - Copyright 2014 TeamWin + Copyright 2014 to 2016 TeamWin This file is part of TWRP/TeamWin Recovery Project. TWRP is free software: you can redistribute it and/or modify @@ -43,6 +43,7 @@ #include "set_metadata.h" #include "tw_atomic.hpp" #include "gui/gui.hpp" +#include "progresstracking.hpp" #ifdef TW_HAS_MTP #include "mtp/mtp_MtpServer.hpp" @@ -527,11 +528,9 @@ bool TWPartitionManager::Make_MD5(bool generate_md5, string Backup_Folder, strin return true; } -bool TWPartitionManager::Backup_Partition(TWPartition* Part, string Backup_Folder, bool generate_md5, unsigned long long* img_bytes_remaining, unsigned long long* file_bytes_remaining, unsigned long *img_time, unsigned long *file_time, unsigned long long *img_bytes, unsigned long long *file_bytes) { +bool TWPartitionManager::Backup_Partition(TWPartition* Part, const string& Backup_Folder, bool generate_md5, unsigned long *img_time, unsigned long *file_time, ProgressTracking *progress) { time_t start, stop; int use_compression; - float pos; - unsigned long long total_size, current_size; string backup_log = Backup_Folder + "recovery.log"; @@ -540,26 +539,17 @@ bool TWPartitionManager::Backup_Partition(TWPartition* Part, string Backup_Folde DataManager::GetValue(TW_USE_COMPRESSION_VAR, use_compression); - total_size = *file_bytes + *img_bytes; - current_size = *file_bytes + *img_bytes - *file_bytes_remaining - *img_bytes_remaining; - // Set the position - pos = ((float)(current_size) / (float)(total_size)); - DataManager::SetProgress(pos); - TWFunc::SetPerformanceMode(true); time(&start); - if (Part->Backup(Backup_Folder, &total_size, ¤t_size, tar_fork_pid)) { + if (Part->Backup(Backup_Folder, tar_fork_pid, progress)) { bool md5Success = false; - current_size += Part->Backup_Size; - pos = (float)((float)(current_size) / (float)(total_size)); - DataManager::SetProgress(pos); if (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, &total_size, ¤t_size, tar_fork_pid)) { + if (!(*subpart)->Backup(Backup_Folder, tar_fork_pid, progress)) { TWFunc::SetPerformanceMode(false); Clean_Backup_Folder(Backup_Folder); TWFunc::copy_file("/tmp/recovery.log", backup_log, 0644); @@ -572,14 +562,6 @@ bool TWPartitionManager::Backup_Partition(TWPartition* Part, string Backup_Folde TWFunc::SetPerformanceMode(false); return false; } - if (Part->Backup_Method == 1) { - *file_bytes_remaining -= (*subpart)->Backup_Size; - } else { - *img_bytes_remaining -= (*subpart)->Backup_Size; - } - current_size += Part->Backup_Size; - pos = (float)(current_size / total_size); - DataManager::SetProgress(pos); } } } @@ -587,10 +569,8 @@ bool TWPartitionManager::Backup_Partition(TWPartition* Part, string Backup_Folde int backup_time = (int) difftime(stop, start); LOGINFO("Partition Backup time: %d\n", backup_time); if (Part->Backup_Method == 1) { - *file_bytes_remaining -= Part->Backup_Size; *file_time += backup_time; } else { - *img_bytes_remaining -= Part->Backup_Size; *img_time += backup_time; } @@ -636,6 +616,10 @@ void TWPartitionManager::Clean_Backup_Folder(string Backup_Folder) { closedir(d); } +int TWPartitionManager::Check_Backup_Cancel() { + return stop_backup.get_value(); +} + int TWPartitionManager::Cancel_Backup() { string Backup_Folder, Backup_Name, Full_Backup_Path; @@ -738,6 +722,7 @@ int TWPartitionManager::Run_Backup(void) { return false; } total_bytes = file_bytes + img_bytes; + ProgressTracking progress(total_bytes); 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()); @@ -777,7 +762,7 @@ int TWPartitionManager::Run_Backup(void) { 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_bytes_remaining, &file_bytes_remaining, &img_time, &file_time, &img_bytes, &file_bytes)) + if (!Backup_Partition(backup_part, Full_Backup_Path, do_md5, &img_time, &file_time, &progress)) return false; } else { gui_msg(Msg(msg::kError, "unable_to_locate_partition=Unable to locate '{1}' partition for backup calculations.")(backup_path)); @@ -794,8 +779,10 @@ int TWPartitionManager::Run_Backup(void) { int img_bps = (int)img_bytes / (int)img_time; unsigned long long file_bps = file_bytes / (int)file_time; - gui_msg(Msg("avg_backup_fs=Average backup rate for file systems: {1} MB/sec")(file_bps / (1024 * 1024))); - gui_msg(Msg("avg_backup_img=Average backup rate for imaged drives: {1} MB/sec")(img_bps / (1024 * 1024))); + if (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) + 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); @@ -832,12 +819,12 @@ int TWPartitionManager::Run_Backup(void) { return true; } -bool TWPartitionManager::Restore_Partition(TWPartition* Part, string Restore_Name, int partition_count, const unsigned long long *total_restore_size, unsigned long long *already_restored_size) { +bool TWPartitionManager::Restore_Partition(TWPartition* Part, const string& Restore_Name, ProgressTracking *progress) { time_t Start, Stop; TWFunc::SetPerformanceMode(true); time(&Start); - //DataManager::ShowProgress(1.0 / (float)partition_count, 150); - if (!Part->Restore(Restore_Name, total_restore_size, already_restored_size)) { + + if (!Part->Restore(Restore_Name, progress)) { TWFunc::SetPerformanceMode(false); return false; } @@ -846,7 +833,7 @@ bool TWPartitionManager::Restore_Partition(TWPartition* Part, string Restore_Nam for (subpart = Partitions.begin(); subpart != Partitions.end(); subpart++) { if ((*subpart)->Is_SubPartition && (*subpart)->SubPartition_Of == Part->Mount_Point) { - if (!(*subpart)->Restore(Restore_Name, total_restore_size, already_restored_size)) { + if (!(*subpart)->Restore(Restore_Name, progress)) { TWFunc::SetPerformanceMode(false); return false; } @@ -859,7 +846,7 @@ bool TWPartitionManager::Restore_Partition(TWPartition* Part, string Restore_Nam return true; } -int TWPartitionManager::Run_Restore(string Restore_Name) { +int TWPartitionManager::Run_Restore(const string& Restore_Name) { int check_md5, check, partition_count = 0; TWPartition* restore_part = NULL; time_t rStart, rStop; @@ -925,6 +912,7 @@ int TWPartitionManager::Run_Restore(string Restore_Name) { 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)); DataManager::SetProgress(0.0); + ProgressTracking progress(total_restore_size); start_pos = 0; if (!Restore_List.empty()) { @@ -934,7 +922,7 @@ int TWPartitionManager::Run_Restore(string Restore_Name) { restore_part = Find_Partition_By_Path(restore_path); if (restore_part != NULL) { partition_count++; - if (!Restore_Partition(restore_part, Restore_Name, partition_count, &total_restore_size, &already_restored_size)) + if (!Restore_Partition(restore_part, Restore_Name, &progress)) return false; } else { gui_msg(Msg(msg::kError, "restore_unable_locate=Unable to locate '{1}' partition for restoring.")(restore_path)); diff --git a/partitions.hpp b/partitions.hpp index 1d43e0478..035acf05e 100644 --- a/partitions.hpp +++ b/partitions.hpp @@ -1,5 +1,5 @@ /* - Copyright 2014 TeamWin + Copyright 2014 to 2016 TeamWin This file is part of TWRP/TeamWin Recovery Project. TWRP is free software: you can redistribute it and/or modify @@ -23,6 +23,7 @@ #include <string> #include "twrpDU.hpp" #include "tw_atomic.hpp" +#include "progresstracking.hpp" #define MAX_FSTAB_LINE_LENGTH 2048 @@ -64,17 +65,17 @@ 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(string backup_folder, const unsigned long long *overall_size, const unsigned long long *other_backups_size, pid_t &tar_fork_pid); // Backs up the partition to the folder specified + bool Backup(const string& backup_folder, pid_t &tar_fork_pid, ProgressTracking *progress); // Backs up the partition to the folder specified bool Check_MD5(string restore_folder); // Checks MD5 of a backup - bool Restore(string restore_folder, const unsigned long long *total_restore_size, unsigned long long *already_restored_size); // Restores the partition using the backup folder provided - unsigned long long Get_Restore_Size(string restore_folder); // Returns the overall restore size of the 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 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(string Filename); // Flashes an image to the partition + bool Flash_Image(const string& Filename); // Flashes an image to the partition void Change_Mount_Read_Only(bool new_value); // Changes Mount_Read_Only to new_value int Check_Lifetime_Writes(); int Decrypt_Adopted(); @@ -118,20 +119,22 @@ 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(string backup_folder, const unsigned long long *overall_size, const unsigned long long *other_backups_size, pid_t &tar_fork_pid); // Backs up using tar for file systems - bool Backup_DD(string backup_folder); // Backs up using dd for emmc memory types - bool Backup_Dump_Image(string backup_folder); // Backs up using dump_image for MTD memory types - string Get_Restore_File_System(string restore_folder); // Returns the file system that was in place at the time of the backup - bool Restore_Tar(string restore_folder, string Restore_File_System, const unsigned long long *total_restore_size, unsigned long long *already_restored_size); // Restore using tar for file systems - bool Restore_Image(string restore_folder, const unsigned long long *total_restore_size, unsigned long long *already_restored_size, string Restore_File_System); // Restore using dd for images + 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 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 bool Find_MTD_Block_Device(string MTD_Name); // Finds the mtd block device based on the name from the fstab void Recreate_AndSec_Folder(void); // Recreates the .android_secure folder void Mount_Storage_Retry(void); // Tries multiple times with a half second delay to mount a device in case storage is slow to mount - bool Flash_Image_DD(string Filename); // Flashes an image to the partition using dd - bool Flash_Image_FI(string Filename); // Flashes an image to the partition using flash_image for mtd nand + bool Is_Sparse_Image(const string& Filename); // Determines if a file is in sparse image format + bool Flash_Sparse_Image(const string& Filename); // Flashes a sparse image using simg2img + bool Flash_Image_FI(const string& Filename, ProgressTracking *progress); // Flashes an image to the partition using flash_image for mtd nand private: bool Can_Be_Mounted; // Indicates that the partition can be mounted @@ -208,7 +211,7 @@ public: 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_Restore(string Restore_Name); // Restores a backup + int Run_Restore(const string& Restore_Name); // Restores a backup 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 @@ -229,6 +232,7 @@ public: void UnMount_Main_Partitions(void); // Unmounts system and data if not data/media and boot if boot is mountable int Partition_SDCard(void); // Repartitions the sdcard TWPartition *Get_Default_Storage_Partition(); // Returns a pointer to a default storage partition + int Check_Backup_Cancel(); // Returns the value of stop_backup int Cancel_Backup(); // Signals partition backup to cancel void Clean_Backup_Folder(string Backup_Folder); // Clean Backup Folder on Error int Fix_Contexts(); @@ -255,9 +259,9 @@ 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, string Backup_Folder, bool generate_md5, unsigned long long* img_bytes_remaining, unsigned long long* file_bytes_remaining, unsigned long *img_time, unsigned long *file_time, unsigned long long *img_bytes, unsigned long long *file_bytes); - bool Restore_Partition(TWPartition* Part, string Restore_Name, int partition_count, const unsigned long long *total_restore_size, unsigned long long *already_restored_size); - void Output_Partition(TWPartition* Part); + 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); + 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 TWPartition* Find_Next_Storage(string Path, bool Exclude_Data_Media); diff --git a/progresstracking.cpp b/progresstracking.cpp new file mode 100644 index 000000000..b43e13057 --- /dev/null +++ b/progresstracking.cpp @@ -0,0 +1,108 @@ +/* + Copyright 2016 bigbiff/Dees_Troy TeamWin + This file is part of TWRP/TeamWin Recovery Project. + + 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/>. +*/ + +// Progress tracking class for tracking backup progess and updating the progress bar as appropriate + + +#include "progresstracking.hpp" +#include "twcommon.h" +#ifndef BUILD_TWRPTAR_MAIN +#include "gui/gui.hpp" +#include "data.hpp" +#endif +#include "twrp-functions.hpp" +#include <time.h> + +const int32_t update_interval_ms = 200; // Update interval in ms + +ProgressTracking::ProgressTracking(const unsigned long long backup_size) { + total_backup_size = backup_size; + partition_size = 0; + file_count = 0; + current_size = 0; + current_count = 0; + previous_partitions_size = 0; + display_file_count = false; + clock_gettime(CLOCK_MONOTONIC, &last_update); +} + +void ProgressTracking::SetPartitionSize(const unsigned long long part_size) { + previous_partitions_size += partition_size; + partition_size = part_size; + UpdateDisplayDetails(true); +} + +void ProgressTracking::SetSizeCount(const unsigned long long part_size, unsigned long long f_count) { + previous_partitions_size += partition_size; + partition_size = part_size; + file_count = f_count; + display_file_count = (file_count != 0); + UpdateDisplayDetails(true); +} + +void ProgressTracking::UpdateSize(const unsigned long long size) { + current_size = size; + UpdateDisplayDetails(false); +} + +void ProgressTracking::UpdateSizeCount(const unsigned long long size, const unsigned long long count) { + current_size = size; + current_count = count; + UpdateDisplayDetails(false); +} + +void ProgressTracking::DisplayFileCount(const bool display) { + display_file_count = display; + UpdateDisplayDetails(true); +} + +void ProgressTracking::UpdateDisplayDetails(const bool force) { +#ifndef BUILD_TWRPTAR_MAIN + if (!force) { + // Do something to check the time frame and only update periodically to reduce the total number of GUI updates + timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + + int32_t diff = TWFunc::timespec_diff_ms(last_update, now); + if (diff < update_interval_ms) + return; + } + clock_gettime(CLOCK_MONOTONIC, &last_update); + double display_percent, progress_percent; + string size_prog = gui_lookup("size_progress", "%lluMB of %lluMB, %i%%"); + char size_progress[1024]; + + if (total_backup_size != 0) // prevent division by 0 + display_percent = (double)(current_size + previous_partitions_size) / (double)(total_backup_size) * 100; + sprintf(size_progress, size_prog.c_str(), (current_size + previous_partitions_size) / 1048576, total_backup_size / 1048576, (int)(display_percent)); + DataManager::SetValue("tw_size_progress", size_progress); + progress_percent = (display_percent / 100); + DataManager::SetProgress((float)(progress_percent)); + + if (!display_file_count || file_count == 0) { + DataManager::SetValue("tw_file_progress", ""); + } else { + string file_prog = gui_lookup("file_progress", "%llu of %llu files, %i%%"); + char file_progress[1024]; + + display_percent = (double)(current_count) / (double)(file_count) * 100; + sprintf(file_progress, file_prog.c_str(), current_count, file_count, (int)(display_percent)); + DataManager::SetValue("tw_file_progress", file_progress); + } +#endif +} diff --git a/progresstracking.hpp b/progresstracking.hpp new file mode 100644 index 000000000..15cf91c28 --- /dev/null +++ b/progresstracking.hpp @@ -0,0 +1,54 @@ +/* + Copyright 2016 bigbiff/Dees_Troy TeamWin + This file is part of TWRP/TeamWin Recovery Project. + + 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 __PROGRESSTRACKING_HPP +#define __PROGRESSTRACKING_HPP + +#include <time.h> + +// Progress tracking class for tracking backup progess and updating the progress bar as appropriate +class ProgressTracking +{ +public: + ProgressTracking(const unsigned long long backup_size); + + void SetPartitionSize(const unsigned long long part_size); + void SetSizeCount(const unsigned long long part_size, unsigned long long f_count); + + void UpdateSize(const unsigned long long size); + void UpdateSizeCount(const unsigned long long size, const unsigned long long count); + + void DisplayFileCount(const bool display); + void UpdateDisplayDetails(const bool force); + +private: + unsigned long long total_backup_size; // Overall size (for the progress bar) + + unsigned long long partition_size; // Size of the current partition + unsigned long long file_count; // Count of files for the current partition (tar backup only, not restore) + + unsigned long long current_size; // Size of the current partition's already backed up data + unsigned long long current_count; // Count of files that have already been backed up for the current partition + + unsigned long long previous_partitions_size; // Total data already backed up from previous partitions (for the progress bar) + + bool display_file_count; // Inidicates if we will display the file count text + timespec last_update; // Tracks last update of the displayed progress (frequent updates tax the CPU and slow us down) +}; + +#endif //__PROGRESSTRACKING_HPP diff --git a/tarWrite.c b/tarWrite.c index 98fa14cad..98461452a 100644 --- a/tarWrite.c +++ b/tarWrite.c @@ -28,6 +28,8 @@ unsigned char *write_buffer; unsigned buffer_size = 4096; unsigned buffer_loc = 0; int buffer_status = 0; +int prog_pipe = -1; +const unsigned long long progress_size = (unsigned long long)(T_BLOCKSIZE); void reinit_libtar_buffer(void) { flush = 0; @@ -36,18 +38,20 @@ void reinit_libtar_buffer(void) { buffer_status = 1; } -void init_libtar_buffer(unsigned new_buff_size) { +void init_libtar_buffer(unsigned new_buff_size, int pipe_fd) { if (new_buff_size != 0) buffer_size = new_buff_size; reinit_libtar_buffer(); write_buffer = (unsigned char*) malloc(sizeof(char *) * buffer_size); + prog_pipe = pipe_fd; } void free_libtar_buffer(void) { if (buffer_status > 0) free(write_buffer); buffer_status = 0; + prog_pipe = -1; } ssize_t write_libtar_buffer(int fd, const void *buffer, size_t size) { @@ -79,6 +83,8 @@ ssize_t write_libtar_buffer(int fd, const void *buffer, size_t size) { buffer_loc = 0; return -1; } else { + unsigned long long fs = (unsigned long long)(buffer_loc); + write(prog_pipe, &fs, sizeof(fs)); buffer_loc = 0; return size; } @@ -94,3 +100,14 @@ void flush_libtar_buffer(int fd) { if (buffer_status) buffer_status = 2; } + +void init_libtar_no_buffer(int pipe_fd) { + buffer_size = T_BLOCKSIZE; + prog_pipe = pipe_fd; + buffer_status = 0; +} + +ssize_t write_libtar_no_buffer(int fd, const void *buffer, size_t size) { + write(prog_pipe, &progress_size, sizeof(progress_size)); + return write(fd, buffer, size); +} diff --git a/tarWrite.h b/tarWrite.h index 498ca0aa2..a63a0f035 100644 --- a/tarWrite.h +++ b/tarWrite.h @@ -20,9 +20,12 @@ #define _TARWRITE_HEADER void reinit_libtar_buffer(); -void init_libtar_buffer(unsigned new_buff_size); +void init_libtar_buffer(unsigned new_buff_size, int pipe_fd); void free_libtar_buffer(); writefunc_t write_libtar_buffer(int fd, const void *buffer, size_t size); void flush_libtar_buffer(int fd); -#endif // _TARWRITE_HEADER
\ No newline at end of file +void init_libtar_no_buffer(int pipe_fd); +writefunc_t write_libtar_no_buffer(int fd, const void *buffer, size_t size); + +#endif // _TARWRITE_HEADER diff --git a/twrp-functions.cpp b/twrp-functions.cpp index eb1f4c2f7..8d85ccf04 100644 --- a/twrp-functions.cpp +++ b/twrp-functions.cpp @@ -38,6 +38,7 @@ #include <algorithm> #include "twrp-functions.hpp" #include "twcommon.h" +#include "gui/gui.hpp" #ifndef BUILD_TWRPTAR_MAIN #include "data.hpp" #include "partitions.hpp" @@ -45,7 +46,6 @@ #include "bootloader.h" #include "cutils/properties.h" #include "cutils/android_reboot.h" -#include "gui/gui.hpp" #include <sys/reboot.h> #endif // ndef BUILD_TWRPTAR_MAIN #ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS @@ -272,7 +272,7 @@ int TWFunc::Try_Decrypting_File(string fn, string password) { #endif } -unsigned long TWFunc::Get_File_Size(string Path) { +unsigned long TWFunc::Get_File_Size(const string& Path) { struct stat st; if (stat(Path.c_str(), &st) != 0) @@ -329,6 +329,25 @@ vector<string> TWFunc::split_string(const string &in, char del, bool skip_empty) return res; } +timespec TWFunc::timespec_diff(timespec& start, timespec& end) +{ + timespec temp; + if ((end.tv_nsec-start.tv_nsec)<0) { + temp.tv_sec = end.tv_sec-start.tv_sec-1; + temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec; + } else { + temp.tv_sec = end.tv_sec-start.tv_sec; + temp.tv_nsec = end.tv_nsec-start.tv_nsec; + } + return temp; +} + +int32_t TWFunc::timespec_diff_ms(timespec& start, timespec& end) +{ + return ((end.tv_sec * 1000) + end.tv_nsec/1000000) - + ((start.tv_sec * 1000) + start.tv_nsec/1000000); +} + #ifndef BUILD_TWRPTAR_MAIN // Returns "/path" from a full /path/to/file.name @@ -703,25 +722,6 @@ int TWFunc::write_file(string fn, string& line) { return -1; } -timespec TWFunc::timespec_diff(timespec& start, timespec& end) -{ - timespec temp; - if ((end.tv_nsec-start.tv_nsec)<0) { - temp.tv_sec = end.tv_sec-start.tv_sec-1; - temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec; - } else { - temp.tv_sec = end.tv_sec-start.tv_sec; - temp.tv_nsec = end.tv_nsec-start.tv_nsec; - } - return temp; -} - -int32_t TWFunc::timespec_diff_ms(timespec& start, timespec& end) -{ - return ((end.tv_sec * 1000) + end.tv_nsec/1000000) - - ((start.tv_sec * 1000) + start.tv_nsec/1000000); -} - bool TWFunc::Install_SuperSU(void) { if (!PartitionManager.Mount_By_Path("/system", true)) return false; diff --git a/twrp-functions.hpp b/twrp-functions.hpp index d72c9161b..6c33c5eaf 100644 --- a/twrp-functions.hpp +++ b/twrp-functions.hpp @@ -48,9 +48,11 @@ public: 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 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(string Path); // Returns the size of a file + 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 static vector<string> split_string(const string &in, char del, bool skip_empty); + static timespec timespec_diff(timespec& start, timespec& end); // Return a diff for 2 times + static int32_t timespec_diff_ms(timespec& start, timespec& end); // Returns diff in ms #ifndef BUILD_TWRPTAR_MAIN static void install_htc_dumlock(void); // Installs HTC Dumlock @@ -66,8 +68,6 @@ public: static int removeDir(const string path, bool removeParent); //recursively remove a directory static int copy_file(string src, string dst, int mode); //copy file from src to dst with mode permissions static unsigned int Get_D_Type_From_Stat(string Path); // Returns a dirent dt_type value using stat instead of dirent - static timespec timespec_diff(timespec& start, timespec& end); // Return a diff for 2 times - static int32_t timespec_diff_ms(timespec& start, timespec& end); // Returns diff in ms static int read_file(string fn, vector<string>& results); //read from file static int read_file(string fn, string& results); //read from file static int read_file(string fn, uint64_t& results); //read from file diff --git a/twrpDigest.cpp b/twrpDigest.cpp index fe0e06778..0dd3ea904 100644 --- a/twrpDigest.cpp +++ b/twrpDigest.cpp @@ -1,5 +1,5 @@ /* - Copyright 2012 bigbiff/Dees_Troy TeamWin + Copyright 2012 to 2016 bigbiff/Dees_Troy TeamWin This file is part of TWRP/TeamWin Recovery Project. TWRP is free software: you can redistribute it and/or modify @@ -44,7 +44,7 @@ extern "C" using namespace std; -void twrpDigest::setfn(string fn) { +void twrpDigest::setfn(const string& fn) { md5fn = fn; } diff --git a/twrpDigest.hpp b/twrpDigest.hpp index 5edd4d3d9..2c08ec546 100644 --- a/twrpDigest.hpp +++ b/twrpDigest.hpp @@ -1,5 +1,5 @@ /* - Copyright 2012 bigbiff/Dees_Troy TeamWin + Copyright 2012 to 2016 bigbiff/Dees_Troy TeamWin This file is part of TWRP/TeamWin Recovery Project. TWRP is free software: you can redistribute it and/or modify @@ -25,7 +25,7 @@ using namespace std; class twrpDigest { public: - void setfn(string fn); + void setfn(const string& fn); int computeMD5(void); int verify_md5digest(void); int write_md5digest(void); diff --git a/twrpTar.cpp b/twrpTar.cpp index 76c8920ae..b46f10f60 100644 --- a/twrpTar.cpp +++ b/twrpTar.cpp @@ -1,6 +1,6 @@ /* - Copyright 2013 TeamWin + Copyright 2013 to 2016 bigbiff/Dees_Troy TeamWin This file is part of TWRP/TeamWin Recovery Project. TWRP is free software: you can redistribute it and/or modify @@ -42,10 +42,11 @@ extern "C" { #include "twcommon.h" #include "variables.h" #include "twrp-functions.hpp" +#include "gui/gui.hpp" +#include "progresstracking.hpp" #ifndef BUILD_TWRPTAR_MAIN #include "data.hpp" #include "infomanager.hpp" -#include "gui/gui.hpp" extern "C" { #include "set_metadata.h" } @@ -90,7 +91,7 @@ void twrpTar::Signal_Kill(int signum) { _exit(255); } -int twrpTar::createTarFork(const unsigned long long *overall_size, const unsigned long long *other_backups_size, pid_t &fork_pid) { +int twrpTar::createTarFork(ProgressTracking *progress, pid_t &fork_pid) { int status = 0; pid_t rc_pid, tar_fork_pid; int progress_pipe[2], ret; @@ -389,15 +390,8 @@ int twrpTar::createTarFork(const unsigned long long *overall_size, const unsigne } } else { // Parent side - unsigned long long fs, size_backup, files_backup, total_backup_size; + unsigned long long fs, size_backup = 0, files_backup = 0, file_count = 0; int first_data = 0; - double display_percent, progress_percent; - char file_progress[1024]; - char size_progress[1024]; - files_backup = 0; - size_backup = 0; - string file_prog = gui_lookup("file_progress", "%llu of %llu files, %i%%"); - string size_prog = gui_lookup("size_progress", "%lluMB of %lluMB, %i%%"); fork_pid = tar_fork_pid; @@ -413,27 +407,24 @@ int twrpTar::createTarFork(const unsigned long long *overall_size, const unsigne first_data = 1; } else if (first_data == 1) { // Second incoming data is total size - total_backup_size = fs; first_data = 2; + progress->SetSizeCount(fs, file_count); } else { - files_backup++; - size_backup += fs; - display_percent = (double)(files_backup) / (double)(file_count) * 100; - sprintf(file_progress, file_prog.c_str(), files_backup, file_count, (int)(display_percent)); -#ifndef BUILD_TWRPTAR_MAIN - DataManager::SetValue("tw_file_progress", file_progress); - display_percent = (double)(size_backup + *other_backups_size) / (double)(*overall_size) * 100; - sprintf(size_progress, size_prog.c_str(), (size_backup + *other_backups_size) / 1048576, *overall_size / 1048576, (int)(display_percent)); - DataManager::SetValue("tw_size_progress", size_progress); - progress_percent = (display_percent / 100); - DataManager::SetProgress((float)(progress_percent)); -#endif //ndef BUILD_TWRPTAR_MAIN + if (fs > 0) { + size_backup += fs; + progress->UpdateSize(size_backup); + } else { // fs == 0 increments the file counter + files_backup++; + progress->UpdateSizeCount(size_backup, files_backup); + } } } close(progress_pipe[0]); #ifndef BUILD_TWRPTAR_MAIN DataManager::SetValue("tw_file_progress", ""); DataManager::SetValue("tw_size_progress", ""); + progress->DisplayFileCount(false); + progress->UpdateDisplayDetails(true); InfoManager backup_info(backup_folder + partition_name + ".info"); backup_info.SetValue("backup_size", size_backup); @@ -454,7 +445,7 @@ int twrpTar::createTarFork(const unsigned long long *overall_size, const unsigne return 0; } -int twrpTar::extractTarFork(const unsigned long long *overall_size, unsigned long long *other_backups_size) { +int twrpTar::extractTarFork(ProgressTracking *progress) { int status = 0; pid_t rc_pid, tar_fork_pid; int progress_pipe[2], ret; @@ -597,11 +588,7 @@ int twrpTar::extractTarFork(const unsigned long long *overall_size, unsigned lon } else // parent process { - unsigned long long fs, size_backup; - double display_percent, progress_percent; - char size_progress[1024]; - size_backup = 0; - string size_prog = gui_lookup("size_progress", "%lluMB of %lluMB, %i%%"); + unsigned long long fs, size_backup = 0; // Parent closes output side close(progress_pipe[1]); @@ -609,19 +596,10 @@ int twrpTar::extractTarFork(const unsigned long long *overall_size, unsigned lon // Read progress data from children while (read(progress_pipe[0], &fs, sizeof(fs)) > 0) { size_backup += fs; - display_percent = (double)(size_backup + *other_backups_size) / (double)(*overall_size) * 100; - sprintf(size_progress, size_prog.c_str(), (size_backup + *other_backups_size) / 1048576, *overall_size / 1048576, (int)(display_percent)); - progress_percent = (display_percent / 100); -#ifndef BUILD_TWRPTAR_MAIN - DataManager::SetValue("tw_size_progress", size_progress); - DataManager::SetProgress((float)(progress_percent)); -#endif //ndef BUILD_TWRPTAR_MAIN + progress->UpdateSize(size_backup); } close(progress_pipe[0]); -#ifndef BUILD_TWRPTAR_MAIN - DataManager::SetValue("tw_file_progress", ""); -#endif //ndef BUILD_TWRPTAR_MAIN - *other_backups_size += size_backup; + progress->UpdateDisplayDetails(true); if (TWFunc::Wait_For_Child(tar_fork_pid, &status, "extractTarFork()") != 0) return -1; @@ -786,6 +764,7 @@ int twrpTar::tarList(std::vector<TarListStruct> *TarList, unsigned thread_id) { Archive_Current_Size = 0; } Archive_Current_Size += fs; + fs = 0; // Sending a 0 size to the pipe tells it to increment the file counter write(progress_pipe_fd, &fs, sizeof(fs)); } LOGINFO("addFile '%s' including root: %i\n", buf, include_root_dir); @@ -862,7 +841,6 @@ int twrpTar::addFilesToExistingTar(vector <string> files, string fn) { int twrpTar::createTar() { char* charTarFile = (char*) tarfn.c_str(); char* charRootDir = (char*) tardir.c_str(); - static tartype_t type = { open, close, read, write_tar }; if (use_encryption && use_compression) { // Compressed and encrypted @@ -945,7 +923,9 @@ int twrpTar::createTar() { close(pipes[2]); close(pipes[3]); fd = pipes[1]; - if(tar_fdopen(&t, fd, charRootDir, NULL, 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) { + init_libtar_no_buffer(progress_pipe_fd); + tar_type = { open, close, read, write_tar_no_buffer }; + if(tar_fdopen(&t, 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(fd); LOGINFO("tar_fdopen failed\n"); gui_err("backup_error=Error creating backup."); @@ -997,7 +977,9 @@ int twrpTar::createTar() { // Parent close(pigzfd[0]); // close parent input fd = pigzfd[1]; // copy parent output - if(tar_fdopen(&t, fd, charRootDir, NULL, 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) { + init_libtar_no_buffer(progress_pipe_fd); + tar_type = { open, close, read, write_tar_no_buffer }; + if(tar_fdopen(&t, 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(fd); LOGINFO("tar_fdopen failed\n"); gui_err("backup_error=Error creating backup."); @@ -1045,7 +1027,9 @@ int twrpTar::createTar() { // Parent close(oaesfd[0]); // close parent input fd = oaesfd[1]; // copy parent output - if(tar_fdopen(&t, fd, charRootDir, NULL, 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) { + init_libtar_no_buffer(progress_pipe_fd); + tar_type = { open, close, read, write_tar_no_buffer }; + if(tar_fdopen(&t, 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(fd); LOGINFO("tar_fdopen failed\n"); gui_err("backup_error=Error creating backup."); @@ -1055,8 +1039,9 @@ int twrpTar::createTar() { } } else { // Not compressed or encrypted - init_libtar_buffer(0); - if (tar_open(&t, charTarFile, &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) { + 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; @@ -1476,3 +1461,7 @@ unsigned long long twrpTar::uncompressedSize(string filename, int *archive_type) extern "C" ssize_t write_tar(int fd, const void *buffer, size_t size) { return (ssize_t) write_libtar_buffer(fd, buffer, size); } + +extern "C" ssize_t write_tar_no_buffer(int fd, const void *buffer, size_t size) { + return (ssize_t) write_libtar_no_buffer(fd, buffer, size); +} @@ -20,6 +20,7 @@ #define _TWRPTAR_HEADER ssize_t write_tar(int fd, const void *buffer, size_t size); +ssize_t write_tar_no_buffer(int fd, const void *buffer, size_t size); #endif // _TWRPTAR_HEADER diff --git a/twrpTar.hpp b/twrpTar.hpp index a486c4174..8ef50207f 100644 --- a/twrpTar.hpp +++ b/twrpTar.hpp @@ -1,5 +1,5 @@ /* - Copyright 2012 bigbiff/Dees_Troy TeamWin + Copyright 2012 to 2016 bigbiff/Dees_Troy TeamWin This file is part of TWRP/TeamWin Recovery Project. TWRP is free software: you can redistribute it and/or modify @@ -28,6 +28,7 @@ extern "C" { #include <string> #include <vector> #include "twrpDU.hpp" +#include "progresstracking.hpp" using namespace std; @@ -45,8 +46,8 @@ class twrpTar { public: twrpTar(); virtual ~twrpTar(); - int createTarFork(const unsigned long long *overall_size, const unsigned long long *other_backups_size, pid_t &fork_pid); - int extractTarFork(const unsigned long long *overall_size, unsigned long long *other_backups_size); + int createTarFork(ProgressTracking *progress, pid_t &fork_pid); + int extractTarFork(ProgressTracking *progress); void setfn(string fn); void setdir(string dir); void setsize(unsigned long long backup_size); @@ -87,6 +88,7 @@ private: 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; pid_t pigz_pid; pid_t oaes_pid; diff --git a/twrpTarMain/Android.mk b/twrpTarMain/Android.mk index 5a1a4434f..c88351bd8 100644 --- a/twrpTarMain/Android.mk +++ b/twrpTarMain/Android.mk @@ -8,18 +8,21 @@ LOCAL_SRC_FILES:= \ ../twrp-functions.cpp \ ../twrpTar.cpp \ ../tarWrite.c \ - ../twrpDU.cpp + ../twrpDU.cpp \ + ../progresstracking.cpp \ + ../gui/twmsg.cpp LOCAL_CFLAGS:= -g -c -W -DBUILD_TWRPTAR_MAIN LOCAL_C_INCLUDES += bionic ifeq ($(shell test $(PLATFORM_SDK_VERSION) -lt 23; echo $$?),0) - LOCAL_C_INCLUDES += external/stlport/stlport + LOCAL_C_INCLUDES += external/stlport/stlport bionic/libstdc++/include endif -LOCAL_STATIC_LIBRARIES := libc libtar_static libstdc++ +LOCAL_STATIC_LIBRARIES := libc libtar_static ifeq ($(shell test $(PLATFORM_SDK_VERSION) -lt 23; echo $$?),0) LOCAL_STATIC_LIBRARIES += libstlport_static endif +LOCAL_STATIC_LIBRARIES += libstdc++ ifeq ($(TWHAVE_SELINUX), true) LOCAL_C_INCLUDES += external/libselinux/include @@ -51,7 +54,9 @@ LOCAL_SRC_FILES:= \ ../twrp-functions.cpp \ ../twrpTar.cpp \ ../tarWrite.c \ - ../twrpDU.cpp + ../twrpDU.cpp \ + ../progresstracking.cpp \ + ../gui/twmsg.cpp LOCAL_CFLAGS:= -g -c -W -DBUILD_TWRPTAR_MAIN LOCAL_C_INCLUDES += bionic external/stlport/stlport diff --git a/twrpTarMain/twrpTarMain.cpp b/twrpTarMain/twrpTarMain.cpp index 6cc629d7d..ff35f47ce 100644 --- a/twrpTarMain/twrpTarMain.cpp +++ b/twrpTarMain/twrpTarMain.cpp @@ -20,10 +20,52 @@ #include "../twrp-functions.hpp" #include "../twrpTar.hpp" #include "../twrpDU.hpp" +#include "../progresstracking.hpp" +#include "../gui/gui.hpp" +#include "../gui/twmsg.h" #include <string.h> twrpDU du; +void gui_msg(const char* text) +{ + if (text) { + Message msg = Msg(text); + gui_msg(msg); + } +} + +void gui_warn(const char* text) +{ + if (text) { + Message msg = Msg(msg::kWarning, text); + gui_msg(msg); + } +} + +void gui_err(const char* text) +{ + if (text) { + Message msg = Msg(msg::kError, text); + gui_msg(msg); + } +} + +void gui_highlight(const char* text) +{ + if (text) { + Message msg = Msg(msg::kHighlight, text); + gui_msg(msg); + } +} + +void gui_msg(Message msg) +{ + std::string output = msg; + output += "\n"; + fputs(output.c_str(), stdout); +} + void usage() { printf("twrpTar <action> [options]\n\n"); printf("actions: -c create\n"); @@ -34,7 +76,7 @@ void usage() { printf(" -z compress backup (/sbin/pigz must be present)\n"); #ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS printf(" -e encrypt/decrypt backup followed by password (/sbin/openaes must be present)\n"); - printf(" -u encrypt using userdata encryption (must be used with -e\n"); + printf(" -u encrypt using userdata encryption (must be used with -e)\n"); #endif printf("\n\n"); printf("Example: twrpTar -c -d /cache -t /sdcard/test.tar\n"); @@ -47,7 +89,7 @@ int main(int argc, char **argv) { int i, action = 0; unsigned j; string Directory, Tar_Filename; - unsigned long long temp1 = 0, temp2 = 0; + ProgressTracking progress(1); pid_t tar_fork_pid = 0; #ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS string Password; @@ -144,14 +186,14 @@ int main(int argc, char **argv) { } #endif if (action == 1) { - if (tar.createTarFork(&temp1, &temp2, tar_fork_pid) != 0) { + if (tar.createTarFork(&progress, tar_fork_pid) != 0) { sync(); return -1; } sync(); printf("\n\ntar created successfully.\n"); } else if (action == 2) { - if (tar.extractTarFork(&temp1, &temp2) != 0) { + if (tar.extractTarFork(&progress) != 0) { sync(); return -1; } |