summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk1
-rw-r--r--gui/twmsg.cpp7
-rw-r--r--libtar/extract.c13
-rw-r--r--partition.cpp231
-rw-r--r--partitionmanager.cpp56
-rw-r--r--partitions.hpp38
-rw-r--r--progresstracking.cpp108
-rw-r--r--progresstracking.hpp54
-rw-r--r--tarWrite.c19
-rw-r--r--tarWrite.h7
-rw-r--r--twrp-functions.cpp42
-rw-r--r--twrp-functions.hpp6
-rw-r--r--twrpDigest.cpp4
-rw-r--r--twrpDigest.hpp4
-rw-r--r--twrpTar.cpp83
-rw-r--r--twrpTar.h1
-rw-r--r--twrpTar.hpp8
-rw-r--r--twrpTarMain/Android.mk13
-rw-r--r--twrpTarMain/twrpTarMain.cpp50
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, &current_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, &current_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);
+}
diff --git a/twrpTar.h b/twrpTar.h
index a73b917e1..425a831f2 100644
--- a/twrpTar.h
+++ b/twrpTar.h
@@ -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;
}