Update backup and restore code, adb sideload
Fixed a problem with using make_ext4fs by making its lib a dynamic lib. Added ADB sideload zip install feature - no way to cancel it yet. Improve backup and restore code.
This commit is contained in:
@@ -66,14 +66,14 @@ LOCAL_STATIC_LIBRARIES :=
|
||||
LOCAL_SHARED_LIBRARIES :=
|
||||
|
||||
LOCAL_STATIC_LIBRARIES += libmtdutils
|
||||
LOCAL_STATIC_LIBRARIES += libext4_utils libminadbd libminzip libunz
|
||||
LOCAL_STATIC_LIBRARIES += libminadbd libminzip libunz
|
||||
LOCAL_STATIC_LIBRARIES += libminuitwrp libpixelflinger_static libpng libjpegtwrp libgui
|
||||
LOCAL_SHARED_LIBRARIES += libz libc libstlport libcutils libstdc++ libmincrypt
|
||||
LOCAL_SHARED_LIBRARIES += libz libc libstlport libcutils libstdc++ libmincrypt libext4_utils
|
||||
|
||||
ifeq ($(TARGET_USERIMAGES_USE_EXT4), true)
|
||||
LOCAL_CFLAGS += -DUSE_EXT4
|
||||
LOCAL_C_INCLUDES += system/extras/ext4_utils
|
||||
LOCAL_STATIC_LIBRARIES += libext4_utils
|
||||
#LOCAL_STATIC_LIBRARIES += libext4_utils
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_SELINUX), true)
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
#include "adb_install.h"
|
||||
extern "C" {
|
||||
#include "minadbd/adb.h"
|
||||
#include "twinstall.h"
|
||||
int TWinstall_zip(const char* path, int* wipe_cache);
|
||||
}
|
||||
|
||||
static RecoveryUI* ui = NULL;
|
||||
@@ -106,5 +108,5 @@ apply_from_adb(RecoveryUI* ui_, int* wipe_cache, const char* install_file) {
|
||||
}
|
||||
return INSTALL_ERROR;
|
||||
}
|
||||
return install_package(ADB_SIDELOAD_FILENAME, wipe_cache, install_file);
|
||||
return TWinstall_zip(ADB_SIDELOAD_FILENAME, wipe_cache);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
#include "../partitions.hpp"
|
||||
#include "../twrp-functions.hpp"
|
||||
|
||||
#include "../ui.h"
|
||||
#include "../adb_install.h"
|
||||
|
||||
extern "C" {
|
||||
#include "../common.h"
|
||||
#include "../roots.h"
|
||||
@@ -31,6 +34,8 @@ extern "C" {
|
||||
#include "../variables.h"
|
||||
#include "../twinstall.h"
|
||||
|
||||
#include "../minadbd/adb.h"
|
||||
|
||||
int TWinstall_zip(const char* path, int* wipe_cache);
|
||||
void wipe_dalvik_cache(void);
|
||||
int check_backup_name(int show_error);
|
||||
@@ -55,6 +60,8 @@ int gui_start();
|
||||
#include "rapidxml.hpp"
|
||||
#include "objects.hpp"
|
||||
|
||||
extern RecoveryUI* ui;
|
||||
|
||||
void curtainClose(void);
|
||||
|
||||
GUIAction::GUIAction(xml_node<>* node)
|
||||
@@ -733,6 +740,7 @@ int GUIAction::doAction(Action action, int isThreaded /* = 0 */)
|
||||
if (function == "nandroid")
|
||||
{
|
||||
operation_start("Nandroid");
|
||||
int ret = 0;
|
||||
|
||||
if (simulate) {
|
||||
DataManager::SetValue("tw_partition", "Simulation");
|
||||
@@ -741,21 +749,27 @@ int GUIAction::doAction(Action action, int isThreaded /* = 0 */)
|
||||
if (arg == "backup") {
|
||||
string Backup_Name;
|
||||
DataManager::GetValue(TW_BACKUP_NAME, Backup_Name);
|
||||
if (Backup_Name == "(Current Date)" || Backup_Name == "0" || Backup_Name == "(" || check_backup_name(1))
|
||||
PartitionManager.Run_Backup(Backup_Name);
|
||||
else
|
||||
if (Backup_Name == "(Current Date)" || Backup_Name == "0" || Backup_Name == "(" || check_backup_name(1) == 0)
|
||||
ret = PartitionManager.Run_Backup();
|
||||
else {
|
||||
operation_end(1, simulate);
|
||||
return -1;
|
||||
}
|
||||
DataManager::SetValue(TW_BACKUP_NAME, "(Current Date)");
|
||||
} else if (arg == "restore") {
|
||||
string Restore_Name;
|
||||
DataManager::GetValue("tw_restore", Restore_Name);
|
||||
PartitionManager.Run_Restore(Restore_Name);
|
||||
ret = PartitionManager.Run_Restore(Restore_Name);
|
||||
} else {
|
||||
operation_end(1, simulate);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
operation_end(0, simulate);
|
||||
if (ret == false)
|
||||
ret = 1; // 1 for failure
|
||||
else
|
||||
ret = 0; // 0 for success
|
||||
operation_end(ret, simulate);
|
||||
return 0;
|
||||
}
|
||||
if (function == "fixpermissions")
|
||||
@@ -1048,6 +1062,25 @@ LOGE("TODO: Implement ORS support\n");
|
||||
operation_end(op_status, simulate);
|
||||
return 0;
|
||||
}
|
||||
if (function == "adbsideload")
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
operation_start("Sideload");
|
||||
if (simulate) {
|
||||
simulate_progress_bar();
|
||||
} else {
|
||||
int wipe_cache = 0;
|
||||
ui_print("Starting ADB sideload feature...\n");
|
||||
__system("touch /tmp/update.zip");
|
||||
ret = apply_from_adb(ui, &wipe_cache, "/tmp/last_install");
|
||||
LOGI("Result was: %i\n", ret);
|
||||
if (ret != 0)
|
||||
ret = 1;
|
||||
}
|
||||
operation_end(ret, simulate);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -2540,6 +2540,21 @@
|
||||
<action function="page">terminalfolder</action>
|
||||
</object>
|
||||
|
||||
<object type="button">
|
||||
<placement x="%col1_x%" y="%row4_y%" />
|
||||
<font resource="font" color="%button_text_color%" />
|
||||
<text>ADB Sideload</text>
|
||||
<image resource="main_button" />
|
||||
<actions>
|
||||
<action function="set">tw_action=adbsideload</action>
|
||||
<action function="set">tw_action_text1=ADB Sideload</action>
|
||||
<action function="set">tw_action_text2=Usage: adb sideload filename.zip</action>
|
||||
<action function="set">tw_complete_text1=ADB Sideload Complete</action>
|
||||
<action function="set">tw_slider_text=Swipe to Wipe</action>
|
||||
<action function="page">action_page</action>
|
||||
</actions>
|
||||
</object>
|
||||
|
||||
<object type="button">
|
||||
<condition var1="tw_show_dumlock" var2="1" />
|
||||
<placement x="%col2_x%" y="%row4_y%" />
|
||||
|
||||
266
partition.cpp
266
partition.cpp
@@ -37,11 +37,11 @@
|
||||
#include "common.h"
|
||||
#include "partitions.hpp"
|
||||
#include "data.hpp"
|
||||
#include "twrp-functions.hpp"
|
||||
extern "C" {
|
||||
#include "mtdutils/mtdutils.h"
|
||||
#include "mtdutils/mounts.h"
|
||||
#include "extra-functions.h"
|
||||
int __system(const char *command);
|
||||
#include "makelist.h"
|
||||
}
|
||||
|
||||
TWPartition::TWPartition(void) {
|
||||
@@ -333,7 +333,7 @@ bool TWPartition::Is_Image(string File_System) {
|
||||
}
|
||||
|
||||
bool TWPartition::Make_Dir(string Path, bool Display_Error) {
|
||||
if (!Path_Exists(Path)) {
|
||||
if (!TWFunc::Path_Exists(Path)) {
|
||||
if (mkdir(Path.c_str(), 0777) == -1) {
|
||||
if (Display_Error)
|
||||
LOGE("Can not create '%s' folder.\n", Path.c_str());
|
||||
@@ -479,7 +479,7 @@ bool TWPartition::Get_Size_Via_df(bool Display_Error) {
|
||||
|
||||
min_len = Actual_Block_Device.size() + 2;
|
||||
sprintf(command, "df %s > /tmp/dfoutput.txt", Mount_Point.c_str());
|
||||
__system(command);
|
||||
system(command);
|
||||
fp = fopen("/tmp/dfoutput.txt", "rt");
|
||||
if (fp == NULL) {
|
||||
LOGI("Unable to open /tmp/dfoutput.txt.\n");
|
||||
@@ -518,46 +518,6 @@ bool TWPartition::Get_Size_Via_df(bool Display_Error) {
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned long long TWPartition::Get_Folder_Size(string Path, bool Display_Error) {
|
||||
DIR* d;
|
||||
struct dirent* de;
|
||||
struct stat st;
|
||||
char path2[1024], filename[1024];
|
||||
unsigned long long dusize = 0;
|
||||
|
||||
// Make a copy of path in case the data in the pointer gets overwritten later
|
||||
strcpy(path2, Path.c_str());
|
||||
|
||||
d = opendir(path2);
|
||||
if (d == NULL)
|
||||
{
|
||||
LOGE("error opening '%s'\n", path2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ((de = readdir(d)) != NULL)
|
||||
{
|
||||
if (de->d_type == DT_DIR && strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..") != 0)
|
||||
{
|
||||
strcpy(filename, path2);
|
||||
strcat(filename, "/");
|
||||
strcat(filename, de->d_name);
|
||||
dusize += Get_Folder_Size(filename, Display_Error);
|
||||
}
|
||||
else if (de->d_type == DT_REG)
|
||||
{
|
||||
strcpy(filename, path2);
|
||||
strcat(filename, "/");
|
||||
strcat(filename, de->d_name);
|
||||
stat(filename, &st);
|
||||
dusize += (unsigned long long)(st.st_size);
|
||||
}
|
||||
}
|
||||
closedir(d);
|
||||
|
||||
return dusize;
|
||||
}
|
||||
|
||||
bool TWPartition::Find_Partition_Size(void) {
|
||||
FILE* fp;
|
||||
char line[512];
|
||||
@@ -590,16 +550,6 @@ bool TWPartition::Find_Partition_Size(void) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TWPartition::Path_Exists(string Path) {
|
||||
// Check to see if the Path exists
|
||||
struct statfs st;
|
||||
|
||||
if (statfs(Path.c_str(), &st) != 0)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
void TWPartition::Flip_Block_Device(void) {
|
||||
string temp;
|
||||
|
||||
@@ -655,7 +605,7 @@ bool TWPartition::Mount(bool Display_Error) {
|
||||
string Command;
|
||||
|
||||
Command = "mount " + Symlink_Path + " " + Symlink_Mount_Point;
|
||||
__system(Command.c_str());
|
||||
system(Command.c_str());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -727,7 +677,38 @@ bool TWPartition::Backup(string backup_folder) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TWPartition::Check_MD5(string restore_folder) {
|
||||
string Full_Filename;
|
||||
char split_filename[512];
|
||||
int index = 0;
|
||||
|
||||
Full_Filename = restore_folder + "/" + Backup_FileName;
|
||||
LOGI("Full_Filename: '%s'\n", Full_Filename.c_str());
|
||||
if (!TWFunc::Path_Exists(Full_Filename)) {
|
||||
// This is a split archive, we presume
|
||||
sprintf(split_filename, "%s%03i", Full_Filename.c_str(), index);
|
||||
while (index < 1000 && TWFunc::Path_Exists(split_filename)) {
|
||||
if (TWFunc::Check_MD5(split_filename) == 0) {
|
||||
LOGE("MD5 failed to match on '%s'.\n", split_filename);
|
||||
return false;
|
||||
}
|
||||
index++;
|
||||
sprintf(split_filename, "%s%03i", Full_Filename.c_str(), index);
|
||||
LOGI("Full_Filename: '%s'\n", Full_Filename.c_str());
|
||||
}
|
||||
} else {
|
||||
// Single file archive
|
||||
if (TWFunc::Check_MD5(Full_Filename) == 0) {
|
||||
LOGE("MD5 failed to match on '%s'.\n", split_filename);
|
||||
return false;
|
||||
} else
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TWPartition::Restore(string restore_folder) {
|
||||
ui_print("Restoring %s...\n", Display_Name.c_str());
|
||||
if (Backup_Method == FILES)
|
||||
return Restore_Tar(restore_folder);
|
||||
else if (Backup_Method == DD)
|
||||
@@ -797,7 +778,7 @@ void TWPartition::Check_FS_Type() {
|
||||
Find_Actual_Block_Device();
|
||||
blkCommand = "blkid " + Actual_Block_Device + " > /tmp/blkidoutput.txt";
|
||||
|
||||
__system(blkCommand.c_str());
|
||||
system(blkCommand.c_str());
|
||||
fp = fopen("/tmp/blkidoutput.txt", "rt");
|
||||
while (fgets(blkOutput, sizeof(blkOutput), fp) != NULL)
|
||||
{
|
||||
@@ -847,7 +828,7 @@ void TWPartition::Check_FS_Type() {
|
||||
Current_File_System = arg;
|
||||
}
|
||||
}
|
||||
__pclose(fp);
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -855,14 +836,14 @@ bool TWPartition::Wipe_EXT23() {
|
||||
if (!UnMount(true))
|
||||
return false;
|
||||
|
||||
if (Path_Exists("/sbin/mke2fs")) {
|
||||
if (TWFunc::Path_Exists("/sbin/mke2fs")) {
|
||||
char command[512];
|
||||
|
||||
ui_print("Formatting %s using mke2fs...\n", Display_Name.c_str());
|
||||
Find_Actual_Block_Device();
|
||||
sprintf(command, "mke2fs -t %s -m 0 %s", Current_File_System.c_str(), Actual_Block_Device.c_str());
|
||||
LOGI("mke2fs command: %s\n", command);
|
||||
if (__system(command) == 0) {
|
||||
if (system(command) == 0) {
|
||||
ui_print("Done.\n");
|
||||
return true;
|
||||
} else {
|
||||
@@ -879,7 +860,7 @@ bool TWPartition::Wipe_EXT4() {
|
||||
if (!UnMount(true))
|
||||
return false;
|
||||
|
||||
if (Path_Exists("/sbin/make_ext4fs")) {
|
||||
if (TWFunc::Path_Exists("/sbin/make_ext4fs")) {
|
||||
string Command;
|
||||
|
||||
ui_print("Formatting %s using make_ext4fs...\n", Display_Name.c_str());
|
||||
@@ -894,7 +875,7 @@ bool TWPartition::Wipe_EXT4() {
|
||||
}
|
||||
Command += " " + Actual_Block_Device;
|
||||
LOGI("make_ext4fs command: %s\n", Command.c_str());
|
||||
if (__system(Command.c_str()) == 0) {
|
||||
if (system(Command.c_str()) == 0) {
|
||||
ui_print("Done.\n");
|
||||
return true;
|
||||
} else {
|
||||
@@ -913,14 +894,14 @@ bool TWPartition::Wipe_FAT() {
|
||||
if (Backup_Name == "and-sec") // Don't format if it's android secure
|
||||
return Wipe_RMRF();
|
||||
|
||||
if (Path_Exists("/sbin/mkdosfs")) {
|
||||
if (TWFunc::Path_Exists("/sbin/mkdosfs")) {
|
||||
if (!UnMount(true))
|
||||
return false;
|
||||
|
||||
ui_print("Formatting %s using mkdosfs...\n", Display_Name.c_str());
|
||||
Find_Actual_Block_Device();
|
||||
sprintf(command,"mkdosfs %s", Actual_Block_Device.c_str()); // use mkdosfs to format it
|
||||
if (__system(command) == 0) {
|
||||
if (system(command) == 0) {
|
||||
ui_print("Done.\n");
|
||||
return true;
|
||||
} else {
|
||||
@@ -981,7 +962,7 @@ bool TWPartition::Wipe_RMRF() {
|
||||
}
|
||||
|
||||
LOGI("rm -rf command is: '%s'\n", cmd);
|
||||
__system(cmd);
|
||||
system(cmd);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -993,8 +974,8 @@ bool TWPartition::Wipe_Data_Without_Wiping_Media() {
|
||||
return false;
|
||||
|
||||
ui_print("Wiping data without wiping /data/media ...\n");
|
||||
__system("rm -f /data/*");
|
||||
__system("rm -f /data/.*");
|
||||
system("rm -f /data/*");
|
||||
system("rm -f /data/.*");
|
||||
|
||||
DIR* d;
|
||||
d = opendir("/data");
|
||||
@@ -1005,7 +986,7 @@ bool TWPartition::Wipe_Data_Without_Wiping_Media() {
|
||||
if (strcmp(de->d_name, "media") == 0) continue;
|
||||
|
||||
sprintf(cmd, "rm -fr /data/%s", de->d_name);
|
||||
__system(cmd);
|
||||
system(cmd);
|
||||
}
|
||||
closedir(d);
|
||||
}
|
||||
@@ -1014,34 +995,142 @@ bool TWPartition::Wipe_Data_Without_Wiping_Media() {
|
||||
}
|
||||
|
||||
bool TWPartition::Backup_Tar(string backup_folder) {
|
||||
LOGI("STUB TWPartition::Backup_Tar, backup_folder: '%s'\n", backup_folder.c_str());
|
||||
return 1;
|
||||
char back_name[255];
|
||||
string Full_FileName, Tar_Args, Command;
|
||||
int use_compression;
|
||||
|
||||
if (!Mount(true))
|
||||
return false;
|
||||
|
||||
ui_print("Backing up %s...\n", Display_Name.c_str());
|
||||
|
||||
DataManager::GetValue(TW_USE_COMPRESSION_VAR, use_compression);
|
||||
if (use_compression)
|
||||
Tar_Args = "-cz";
|
||||
else
|
||||
Tar_Args = "-c";
|
||||
|
||||
sprintf(back_name, "%s.%s.win", Backup_Name.c_str(), Current_File_System.c_str());
|
||||
Backup_FileName = back_name;
|
||||
|
||||
Full_FileName = backup_folder + "/" + Backup_FileName;
|
||||
if (Backup_Size > MAX_ARCHIVE_SIZE) {
|
||||
// This backup needs to be split into multiple archives
|
||||
LOGE("Multiple archive splitting is not implemented yet!\n");
|
||||
return false;
|
||||
} else {
|
||||
if (Has_Data_Media)
|
||||
Command = "cd " + Mount_Point + " && tar " + Tar_Args + " ./ --exclude='media*' -f '" + Full_FileName + "'";
|
||||
else
|
||||
Command = "cd " + Mount_Point + " && tar " + Tar_Args + " -f '" + Full_FileName + "' ./*";
|
||||
LOGI("Backup command: '%s'\n", Command.c_str());
|
||||
system(Command.c_str());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TWPartition::Backup_DD(string backup_folder) {
|
||||
LOGI("STUB TWPartition::Backup_DD, backup_folder: '%s'\n", backup_folder.c_str());
|
||||
return 1;
|
||||
char back_name[255];
|
||||
string Full_FileName, Command;
|
||||
int use_compression;
|
||||
|
||||
ui_print("Backing up %s...\n", Display_Name.c_str());
|
||||
|
||||
sprintf(back_name, "%s.%s.win", Backup_Name.c_str(), Current_File_System.c_str());
|
||||
Backup_FileName = back_name;
|
||||
|
||||
Full_FileName = backup_folder + "/" + Backup_FileName;
|
||||
|
||||
Command = "dd if=" + Actual_Block_Device + " of='" + Full_FileName + "'";
|
||||
LOGI("Backup command: '%s'\n", Command.c_str());
|
||||
system(Command.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TWPartition::Backup_Dump_Image(string backup_folder) {
|
||||
LOGI("STUB TWPartition::Backup_Dump_Image, backup_folder: '%s'\n", backup_folder.c_str());
|
||||
return 1;
|
||||
char back_name[255];
|
||||
string Full_FileName, Command;
|
||||
int use_compression;
|
||||
|
||||
ui_print("Backing up %s...\n", Display_Name.c_str());
|
||||
|
||||
sprintf(back_name, "%s.%s.win", Backup_Name.c_str(), Current_File_System.c_str());
|
||||
Backup_FileName = back_name;
|
||||
|
||||
Full_FileName = backup_folder + "/" + Backup_FileName;
|
||||
|
||||
Command = "dump_image " + MTD_Name + " '" + Full_FileName + "'";
|
||||
LOGI("Backup command: '%s'\n", Command.c_str());
|
||||
system(Command.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TWPartition::Restore_Tar(string restore_folder) {
|
||||
LOGI("STUB TWPartition::Restore_Tar, backup_folder: '%s'\n", restore_folder.c_str());
|
||||
return 1;
|
||||
size_t first_period, second_period;
|
||||
string Restore_File_System, Full_FileName, Command;
|
||||
|
||||
LOGI("Restore filename is: %s\n", Backup_FileName.c_str());
|
||||
|
||||
// Parse backup filename to extract the file system before wiping
|
||||
first_period = Backup_FileName.find(".");
|
||||
if (first_period == string::npos) {
|
||||
LOGE("Unable to find file system (first period).\n");
|
||||
return false;
|
||||
}
|
||||
Restore_File_System = Backup_FileName.substr(first_period + 1, Backup_FileName.size() - first_period - 1);
|
||||
second_period = Restore_File_System.find(".");
|
||||
if (second_period == string::npos) {
|
||||
LOGE("Unable to find file system (second period).\n");
|
||||
return false;
|
||||
}
|
||||
Restore_File_System.resize(second_period);
|
||||
LOGI("Restore file system is: '%s'.\n", Restore_File_System.c_str());
|
||||
Current_File_System = Restore_File_System;
|
||||
ui_print("Wiping %s...\n", Display_Name.c_str());
|
||||
if (!Wipe())
|
||||
return false;
|
||||
|
||||
if (!Mount(true))
|
||||
return false;
|
||||
|
||||
Full_FileName = restore_folder + "/" + Backup_FileName;
|
||||
ui_print("Restoring %s...\n", Display_Name.c_str());
|
||||
if (!TWFunc::Path_Exists(Full_FileName)) {
|
||||
// This backup is multiple archives
|
||||
LOGE("Multiple archive not implemented yet.\n");
|
||||
return false;
|
||||
} else {
|
||||
Command = "cd " + Mount_Point + " && tar -xf '" + Full_FileName + "'";
|
||||
LOGI("Restore command: '%s'\n", Command.c_str());
|
||||
system(Command.c_str());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TWPartition::Restore_DD(string restore_folder) {
|
||||
LOGI("STUB TWPartition::Restore_DD, backup_folder: '%s'\n", restore_folder.c_str());
|
||||
return 1;
|
||||
string Full_FileName, Command;
|
||||
|
||||
ui_print("Restoring %s...\n", Display_Name.c_str());
|
||||
Full_FileName = restore_folder + "/" + Backup_FileName;
|
||||
Command = "dd bs=4096 if='" + Full_FileName + "' of=" + Actual_Block_Device;
|
||||
LOGI("Restore command: '%s'\n", Command.c_str());
|
||||
system(Command.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TWPartition::Restore_Flash_Image(string restore_folder) {
|
||||
LOGI("STUB TWPartition::Restore_Flash_Image, backup_folder: '%s'\n", restore_folder.c_str());
|
||||
// might erase image first just to ensure that it flashes
|
||||
return 1;
|
||||
string Full_FileName, Command;
|
||||
|
||||
ui_print("Restoring %s...\n", Display_Name.c_str());
|
||||
Full_FileName = restore_folder + "/" + Backup_FileName;
|
||||
// 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;
|
||||
LOGI("Erase command: '%s'\n", Command.c_str());
|
||||
system(Command.c_str());
|
||||
Command = "flash_image " + MTD_Name + " '" + Full_FileName + "'";
|
||||
LOGI("Restore command: '%s'\n", Command.c_str());
|
||||
system(Command.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TWPartition::Update_Size(bool Display_Error) {
|
||||
@@ -1064,7 +1153,8 @@ bool TWPartition::Update_Size(bool Display_Error) {
|
||||
if (Has_Data_Media) {
|
||||
if (Mount(Display_Error)) {
|
||||
unsigned long long data_media_used, actual_data;
|
||||
data_media_used = Get_Folder_Size("/data/media", Display_Error);
|
||||
Used = TWFunc::Get_Folder_Size("/data", Display_Error);
|
||||
data_media_used = TWFunc::Get_Folder_Size("/data/media", Display_Error);
|
||||
actual_data = Used - data_media_used;
|
||||
Backup_Size = actual_data;
|
||||
int bak = (int)(Backup_Size / 1048576LLU);
|
||||
@@ -1082,12 +1172,12 @@ bool TWPartition::Update_Size(bool Display_Error) {
|
||||
void TWPartition::Find_Actual_Block_Device(void) {
|
||||
if (Is_Decrypted) {
|
||||
Actual_Block_Device = Decrypted_Block_Device;
|
||||
if (Path_Exists(Primary_Block_Device))
|
||||
if (TWFunc::Path_Exists(Primary_Block_Device))
|
||||
Is_Present = true;
|
||||
} else if (Path_Exists(Primary_Block_Device)) {
|
||||
} else if (TWFunc::Path_Exists(Primary_Block_Device)) {
|
||||
Is_Present = true;
|
||||
Actual_Block_Device = Primary_Block_Device;
|
||||
} else if (!Alternate_Block_Device.empty() && Path_Exists(Alternate_Block_Device)) {
|
||||
} else if (!Alternate_Block_Device.empty() && TWFunc::Path_Exists(Alternate_Block_Device)) {
|
||||
Flip_Block_Device();
|
||||
Actual_Block_Device = Primary_Block_Device;
|
||||
Is_Present = true;
|
||||
@@ -1102,10 +1192,10 @@ void TWPartition::Recreate_Media_Folder(void) {
|
||||
LOGE("Unable to recreate /data/media folder.\n");
|
||||
} else {
|
||||
LOGI("Recreating /data/media folder.\n");
|
||||
__system("cd /data && mkdir media && chmod 755 media");
|
||||
system("cd /data && mkdir media && chmod 755 media");
|
||||
Command = "umount " + Symlink_Mount_Point;
|
||||
__system(Command.c_str());
|
||||
system(Command.c_str());
|
||||
Command = "mount " + Symlink_Path + " " + Symlink_Mount_Point;
|
||||
__system(Command.c_str());
|
||||
system(Command.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,6 +117,9 @@ int TWPartitionManager::Mount_By_Path(string Path, bool Display_Error) {
|
||||
bool found = false;
|
||||
string Local_Path = TWFunc::Get_Root_Path(Path);
|
||||
|
||||
if (Local_Path == "/tmp")
|
||||
return true;
|
||||
|
||||
// Iterate through all partitions
|
||||
for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
|
||||
if ((*iter)->Mount_Point == Local_Path || (!(*iter)->Symlink_Mount_Point.empty() && (*iter)->Symlink_Mount_Point == Local_Path)) {
|
||||
@@ -326,17 +329,443 @@ TWPartition* TWPartitionManager::Find_Partition_By_Name(string Name) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int TWPartitionManager::Run_Backup(string Backup_Name) {
|
||||
LOGI("STUB TWPartitionManager::Run_Backup, Backup_Name: '%s'\n", Backup_Name.c_str());
|
||||
return 1;
|
||||
bool TWPartitionManager::Make_MD5(bool generate_md5, string Backup_Folder, string Backup_Filename)
|
||||
{
|
||||
char command[512];
|
||||
string Full_File = Backup_Folder + Backup_Filename;
|
||||
|
||||
if (!generate_md5) {
|
||||
LOGI("MD5 disabled\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
ui_print(" * Generating md5...\n");
|
||||
|
||||
if (TWFunc::Path_Exists(Full_File)) {
|
||||
sprintf(command, "cd '%s' && md5sum %s > %s.md5",Backup_Folder.c_str(), Backup_Filename.c_str(), Backup_Filename.c_str());
|
||||
LOGI("MD5 command is: '%s'\n", command);
|
||||
if (system(command) == 0) {
|
||||
ui_print("....MD5 Created.\n");
|
||||
return true;
|
||||
} else {
|
||||
ui_print("....MD5 Error.\n");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
char filename[512];
|
||||
int index = 0;
|
||||
|
||||
sprintf(filename, "%s%03i", Full_File.c_str(), index);
|
||||
while (TWFunc::Path_Exists(filename)) {
|
||||
sprintf(command, "cd '%s' && md5sum %s%03i > %s%03i.md5",Backup_Folder.c_str(), Backup_Filename.c_str(), index, Backup_Filename.c_str(), index);
|
||||
LOGI("MD5 command is: '%s'\n", command);
|
||||
if (system(command) == 0) {
|
||||
ui_print("....MD5 Created.\n");
|
||||
} else {
|
||||
ui_print("....MD5 Error.\n");
|
||||
return false;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
if (index == 0) {
|
||||
LOGE("Backup file: '%s' not found!\n", filename);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
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) {
|
||||
time_t start, stop;
|
||||
|
||||
if (Part == NULL)
|
||||
return true;
|
||||
|
||||
time(&start);
|
||||
|
||||
if (Part->Backup(Backup_Folder)) {
|
||||
time(&stop);
|
||||
if (Part->Backup_Method == 1) {
|
||||
*file_bytes_remaining -= Part->Backup_Size;
|
||||
*file_time += (int) difftime(stop, start);
|
||||
} else {
|
||||
*img_bytes_remaining -= Part->Backup_Size;
|
||||
*img_time += (int) difftime(stop, start);
|
||||
}
|
||||
return Make_MD5(generate_md5, Backup_Folder, Part->Backup_FileName);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int TWPartitionManager::Run_Backup(void) {
|
||||
int check, do_md5, partition_count = 0;
|
||||
string Backup_Folder, Backup_Name, Full_Backup_Path;
|
||||
unsigned long long total_bytes = 0, file_bytes = 0, img_bytes = 0, free_space = 0, img_bytes_remaining, file_bytes_remaining;
|
||||
unsigned long img_time = 0, file_time = 0;
|
||||
TWPartition* backup_sys = NULL;
|
||||
TWPartition* backup_data = NULL;
|
||||
TWPartition* backup_cache = NULL;
|
||||
TWPartition* backup_recovery = NULL;
|
||||
TWPartition* backup_boot = NULL;
|
||||
TWPartition* backup_andsec = NULL;
|
||||
TWPartition* backup_sdext = NULL;
|
||||
TWPartition* backup_sp1 = NULL;
|
||||
TWPartition* backup_sp2 = NULL;
|
||||
TWPartition* backup_sp3 = NULL;
|
||||
TWPartition* storage = NULL;
|
||||
struct tm *t;
|
||||
time_t start, stop, seconds, total_start, total_stop;
|
||||
seconds = time(0);
|
||||
t = localtime(&seconds);
|
||||
|
||||
time(&total_start);
|
||||
|
||||
Update_System_Details();
|
||||
|
||||
if (!Mount_Current_Storage(true))
|
||||
return false;
|
||||
|
||||
DataManager::GetValue(TW_SKIP_MD5_GENERATE_VAR, do_md5);
|
||||
if (do_md5 != 0) {
|
||||
LOGI("MD5 creation enabled.\n");
|
||||
do_md5 = true;
|
||||
}
|
||||
DataManager::GetValue(TW_BACKUPS_FOLDER_VAR, Backup_Folder);
|
||||
DataManager::GetValue(TW_BACKUP_NAME, Backup_Name);
|
||||
if (Backup_Name == "(Current Date)" || Backup_Name == "0") {
|
||||
char timestamp[255];
|
||||
sprintf(timestamp,"%04d-%02d-%02d--%02d-%02d-%02d",t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
|
||||
Backup_Name = timestamp;
|
||||
}
|
||||
LOGI("Backup Name is: '%s'\n", Backup_Name.c_str());
|
||||
Full_Backup_Path = Backup_Folder + "/" + Backup_Name + "/";
|
||||
LOGI("Full_Backup_Path is: '%s'\n", Full_Backup_Path.c_str());
|
||||
|
||||
ui_print("\n[BACKUP STARTED]\n");
|
||||
ui_print(" * Backup Folder: %s\n", Full_Backup_Path.c_str());
|
||||
if (!TWFunc::Recursive_Mkdir(Full_Backup_Path)) {
|
||||
LOGE("Failed to make backup folder.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
LOGI("Calculating backup details...\n");
|
||||
DataManager::GetValue(TW_BACKUP_SYSTEM_VAR, check);
|
||||
if (check) {
|
||||
backup_sys = Find_Partition_By_Path("/system");
|
||||
if (backup_sys != NULL) {
|
||||
partition_count++;
|
||||
if (backup_sys->Backup_Method == 1)
|
||||
file_bytes += backup_sys->Backup_Size;
|
||||
else
|
||||
img_bytes += backup_sys->Backup_Size;
|
||||
} else {
|
||||
LOGE("Unable to locate system partition.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
DataManager::GetValue(TW_BACKUP_DATA_VAR, check);
|
||||
if (check) {
|
||||
backup_data = Find_Partition_By_Path("/data");
|
||||
if (backup_data != NULL) {
|
||||
partition_count++;
|
||||
if (backup_data->Backup_Method == 1)
|
||||
file_bytes += backup_data->Backup_Size;
|
||||
else
|
||||
img_bytes += backup_data->Backup_Size;
|
||||
} else {
|
||||
LOGE("Unable to locate data partition.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
DataManager::GetValue(TW_BACKUP_CACHE_VAR, check);
|
||||
if (check) {
|
||||
backup_cache = Find_Partition_By_Path("/cache");
|
||||
if (backup_cache != NULL) {
|
||||
partition_count++;
|
||||
if (backup_cache->Backup_Method == 1)
|
||||
file_bytes += backup_cache->Backup_Size;
|
||||
else
|
||||
img_bytes += backup_cache->Backup_Size;
|
||||
} else {
|
||||
LOGE("Unable to locate cache partition.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
DataManager::GetValue(TW_BACKUP_RECOVERY_VAR, check);
|
||||
if (check) {
|
||||
backup_recovery = Find_Partition_By_Path("/recovery");
|
||||
if (backup_recovery != NULL) {
|
||||
partition_count++;
|
||||
if (backup_recovery->Backup_Method == 1)
|
||||
file_bytes += backup_recovery->Backup_Size;
|
||||
else
|
||||
img_bytes += backup_recovery->Backup_Size;
|
||||
} else {
|
||||
LOGE("Unable to locate recovery partition.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
DataManager::GetValue(TW_BACKUP_BOOT_VAR, check);
|
||||
if (check) {
|
||||
backup_boot = Find_Partition_By_Path("/boot");
|
||||
if (backup_boot != NULL) {
|
||||
partition_count++;
|
||||
if (backup_boot->Backup_Method == 1)
|
||||
file_bytes += backup_boot->Backup_Size;
|
||||
else
|
||||
img_bytes += backup_boot->Backup_Size;
|
||||
} else {
|
||||
LOGE("Unable to locate boot partition.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
DataManager::GetValue(TW_BACKUP_ANDSEC_VAR, check);
|
||||
if (check) {
|
||||
backup_andsec = Find_Partition_By_Path("/and-sec");
|
||||
if (backup_andsec != NULL) {
|
||||
partition_count++;
|
||||
if (backup_andsec->Backup_Method == 1)
|
||||
file_bytes += backup_andsec->Backup_Size;
|
||||
else
|
||||
img_bytes += backup_andsec->Backup_Size;
|
||||
} else {
|
||||
LOGE("Unable to locate android secure partition.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
DataManager::GetValue(TW_BACKUP_SDEXT_VAR, check);
|
||||
if (check) {
|
||||
backup_sdext = Find_Partition_By_Path("/sd-ext");
|
||||
if (backup_sdext != NULL) {
|
||||
partition_count++;
|
||||
if (backup_sdext->Backup_Method == 1)
|
||||
file_bytes += backup_sdext->Backup_Size;
|
||||
else
|
||||
img_bytes += backup_sdext->Backup_Size;
|
||||
} else {
|
||||
LOGE("Unable to locate sd-ext partition.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#ifdef SP1_NAME
|
||||
DataManager::GetValue(TW_BACKUP_SP1_VAR, check);
|
||||
if (check) {
|
||||
backup_sp1 = Find_Partition_By_Path(SP1_NAME);
|
||||
if (backup_sp1 != NULL) {
|
||||
partition_count++;
|
||||
if (backup_sp1->Backup_Method == 1)
|
||||
file_bytes += backup_sp1->Backup_Size;
|
||||
else
|
||||
img_bytes += backup_sp1->Backup_Size;
|
||||
} else {
|
||||
LOGE("Unable to locate %s partition.\n", SP1_NAME);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef SP2_NAME
|
||||
DataManager::GetValue(TW_BACKUP_SP2_VAR, check);
|
||||
if (check) {
|
||||
backup_sp2 = Find_Partition_By_Path(SP2_NAME);
|
||||
if (backup_sp2 != NULL) {
|
||||
partition_count++;
|
||||
if (backup_sp2->Backup_Method == 1)
|
||||
file_bytes += backup_sp2->Backup_Size;
|
||||
else
|
||||
img_bytes += backup_sp2->Backup_Size;
|
||||
} else {
|
||||
LOGE("Unable to locate %s partition.\n", SP2_NAME);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef SP3_NAME
|
||||
DataManager::GetValue(TW_BACKUP_SP3_VAR, check);
|
||||
if (check) {
|
||||
backup_sp3 = Find_Partition_By_Path(SP3_NAME);
|
||||
if (backup_sp3 != NULL) {
|
||||
partition_count++;
|
||||
if (backup_sp3->Backup_Method == 1)
|
||||
file_bytes += backup_sp3->Backup_Size;
|
||||
else
|
||||
img_bytes += backup_sp3->Backup_Size;
|
||||
} else {
|
||||
LOGE("Unable to locate %s partition.\n", SP3_NAME);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (partition_count == 0) {
|
||||
ui_print("No partitions selected for backup.\n");
|
||||
return false;
|
||||
}
|
||||
total_bytes = file_bytes + img_bytes;
|
||||
ui_print(" * Total number of partitions to back up: %d\n", partition_count);
|
||||
ui_print(" * Total size of all data: %lluMB\n", total_bytes / 1024 / 1024);
|
||||
storage = Find_Partition_By_Path(DataManager::GetCurrentStoragePath());
|
||||
if (storage != NULL) {
|
||||
free_space = storage->Free;
|
||||
ui_print(" * Available space: %lluMB\n", free_space / 1024 / 1024);
|
||||
} else {
|
||||
LOGE("Unable to locate storage device.\n");
|
||||
return false;
|
||||
}
|
||||
if (free_space + (32 * 1024 * 1024) < total_bytes) {
|
||||
// We require an extra 32MB just in case
|
||||
LOGE("Not enough free space on storage.\n");
|
||||
return false;
|
||||
}
|
||||
img_bytes_remaining = img_bytes;
|
||||
file_bytes_remaining = file_bytes;
|
||||
|
||||
if (!Backup_Partition(backup_sys, Full_Backup_Path, do_md5, &img_bytes_remaining, &file_bytes_remaining, &img_time, &file_time))
|
||||
return false;
|
||||
if (!Backup_Partition(backup_data, Full_Backup_Path, do_md5, &img_bytes_remaining, &file_bytes_remaining, &img_time, &file_time))
|
||||
return false;
|
||||
if (!Backup_Partition(backup_cache, Full_Backup_Path, do_md5, &img_bytes_remaining, &file_bytes_remaining, &img_time, &file_time))
|
||||
return false;
|
||||
if (!Backup_Partition(backup_recovery, Full_Backup_Path, do_md5, &img_bytes_remaining, &file_bytes_remaining, &img_time, &file_time))
|
||||
return false;
|
||||
if (!Backup_Partition(backup_boot, Full_Backup_Path, do_md5, &img_bytes_remaining, &file_bytes_remaining, &img_time, &file_time))
|
||||
return false;
|
||||
if (!Backup_Partition(backup_andsec, Full_Backup_Path, do_md5, &img_bytes_remaining, &file_bytes_remaining, &img_time, &file_time))
|
||||
return false;
|
||||
if (!Backup_Partition(backup_sdext, Full_Backup_Path, do_md5, &img_bytes_remaining, &file_bytes_remaining, &img_time, &file_time))
|
||||
return false;
|
||||
if (!Backup_Partition(backup_sp1, Full_Backup_Path, do_md5, &img_bytes_remaining, &file_bytes_remaining, &img_time, &file_time))
|
||||
return false;
|
||||
if (!Backup_Partition(backup_sp2, Full_Backup_Path, do_md5, &img_bytes_remaining, &file_bytes_remaining, &img_time, &file_time))
|
||||
return false;
|
||||
if (!Backup_Partition(backup_sp3, Full_Backup_Path, do_md5, &img_bytes_remaining, &file_bytes_remaining, &img_time, &file_time))
|
||||
return false;
|
||||
|
||||
// Average BPS
|
||||
if (img_time == 0)
|
||||
img_time = 1;
|
||||
if (file_time == 0)
|
||||
file_time = 1;
|
||||
unsigned long int img_bps = img_bytes / img_time;
|
||||
unsigned long int file_bps = file_bytes / file_time;
|
||||
|
||||
ui_print("Average backup rate for file systems: %lu MB/sec\n", (file_bps / (1024 * 1024)));
|
||||
ui_print("Average backup rate for imaged drives: %lu MB/sec\n", (img_bps / (1024 * 1024)));
|
||||
|
||||
time(&total_stop);
|
||||
int total_time = (int) difftime(total_stop, total_start);
|
||||
unsigned long long actual_backup_size = TWFunc::Get_Folder_Size(Full_Backup_Path, true);
|
||||
actual_backup_size /= (1024LLU * 1024LLU);
|
||||
|
||||
ui_print("[%llu MB TOTAL BACKED UP]\n", actual_backup_size);
|
||||
Update_System_Details();
|
||||
ui_print("[BACKUP COMPLETED IN %d SECONDS]\n\n", total_time); // the end
|
||||
return true;
|
||||
}
|
||||
|
||||
int TWPartitionManager::Run_Restore(string Restore_Name) {
|
||||
int check;
|
||||
int check, restore_sys, restore_data, restore_cache, restore_boot, restore_andsec, restore_sdext, restore_sp1, restore_sp2, restore_sp3;
|
||||
TWPartition* Part;
|
||||
LOGE("TO DO: Check MD5 of all partitions before restoring ANY partitions.\n");
|
||||
DataManager::GetValue(TW_RESTORE_SYSTEM_VAR, check);
|
||||
|
||||
DataManager::GetValue(TW_SKIP_MD5_CHECK_VAR, check);
|
||||
DataManager::GetValue(TW_RESTORE_SYSTEM_VAR, restore_sys);
|
||||
DataManager::GetValue(TW_RESTORE_DATA_VAR, restore_data);
|
||||
DataManager::GetValue(TW_RESTORE_CACHE_VAR, restore_cache);
|
||||
DataManager::GetValue(TW_RESTORE_BOOT_VAR, restore_boot);
|
||||
DataManager::GetValue(TW_RESTORE_ANDSEC_VAR, restore_andsec);
|
||||
DataManager::GetValue(TW_RESTORE_SDEXT_VAR, restore_sdext);
|
||||
DataManager::GetValue(TW_RESTORE_SP1_VAR, restore_sp1);
|
||||
DataManager::GetValue(TW_RESTORE_SP2_VAR, restore_sp2);
|
||||
DataManager::GetValue(TW_RESTORE_SP3_VAR, restore_sp3);
|
||||
|
||||
if (check > 0) {
|
||||
// Check MD5 files first before restoring to ensure that all of them match before starting a restore
|
||||
if (restore_sys > 0) {
|
||||
Part = Find_Partition_By_Path("/system");
|
||||
if (Part) {
|
||||
if (!Part->Check_MD5(Restore_Name))
|
||||
return false;
|
||||
} else
|
||||
LOGE("Restore: Unable to locate system partition.\n");
|
||||
}
|
||||
|
||||
if (restore_data > 0) {
|
||||
Part = Find_Partition_By_Path("/data");
|
||||
if (Part) {
|
||||
if (!Part->Check_MD5(Restore_Name))
|
||||
return false;
|
||||
} else
|
||||
LOGE("Restore: Unable to locate data partition.\n");
|
||||
}
|
||||
|
||||
if (restore_cache > 0) {
|
||||
Part = Find_Partition_By_Path("/cache");
|
||||
if (Part) {
|
||||
if (!Part->Check_MD5(Restore_Name))
|
||||
return false;
|
||||
} else
|
||||
LOGE("Restore: Unable to locate cache partition.\n");
|
||||
}
|
||||
|
||||
if (restore_boot > 0) {
|
||||
Part = Find_Partition_By_Path("/boot");
|
||||
if (Part) {
|
||||
if (!Part->Check_MD5(Restore_Name))
|
||||
return false;
|
||||
} else
|
||||
LOGE("Restore: Unable to locate boot partition.\n");
|
||||
}
|
||||
|
||||
if (restore_andsec > 0) {
|
||||
Part = Find_Partition_By_Path("/.android_secure");
|
||||
if (Part) {
|
||||
if (!Part->Check_MD5(Restore_Name))
|
||||
return false;
|
||||
} else
|
||||
LOGE("Restore: Unable to locate android_secure partition.\n");
|
||||
}
|
||||
|
||||
if (restore_sdext > 0) {
|
||||
Part = Find_Partition_By_Path("/sd-ext");
|
||||
if (Part) {
|
||||
if (!Part->Check_MD5(Restore_Name))
|
||||
return false;
|
||||
} else
|
||||
LOGE("Restore: Unable to locate sd-ext partition.\n");
|
||||
}
|
||||
#ifdef SP1_NAME
|
||||
if (restore_sp1 > 0) {
|
||||
Part = Find_Partition_By_Path(TWFunc::Get_Root_Path(SP1_NAME));
|
||||
if (Part) {
|
||||
if (!Part->Check_MD5(Restore_Name))
|
||||
return false;
|
||||
} else
|
||||
LOGE("Restore: Unable to locate %s partition.\n", SP1_NAME);
|
||||
}
|
||||
#endif
|
||||
#ifdef SP2_NAME
|
||||
if (restore_sp2 > 0) {
|
||||
Part = Find_Partition_By_Path(TWFunc::Get_Root_Path(SP2_NAME));
|
||||
if (Part) {
|
||||
if (!Part->Check_MD5(Restore_Name))
|
||||
return false;
|
||||
} else
|
||||
LOGE("Restore: Unable to locate %s partition.\n", SP2_NAME);
|
||||
}
|
||||
#endif
|
||||
#ifdef SP3_NAME
|
||||
if (restore_sp3 > 0) {
|
||||
Part = Find_Partition_By_Path(TWFunc::Get_Root_Path(SP3_NAME));
|
||||
if (Part) {
|
||||
if (!Part->Check_MD5(Restore_Name))
|
||||
return false;
|
||||
} else
|
||||
LOGE("Restore: Unable to locate %s partition.\n", SP3_NAME);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (restore_sys > 0) {
|
||||
Part = Find_Partition_By_Path("/system");
|
||||
if (Part) {
|
||||
if (!Part->Restore(Restore_Name))
|
||||
@@ -344,8 +773,8 @@ LOGE("TO DO: Check MD5 of all partitions before restoring ANY partitions.\n");
|
||||
} else
|
||||
LOGE("Restore: Unable to locate system partition.\n");
|
||||
}
|
||||
DataManager::GetValue(TW_RESTORE_DATA_VAR, check);
|
||||
if (check > 0) {
|
||||
|
||||
if (restore_data > 0) {
|
||||
Part = Find_Partition_By_Path("/data");
|
||||
if (Part) {
|
||||
if (!Part->Restore(Restore_Name))
|
||||
@@ -353,8 +782,8 @@ LOGE("TO DO: Check MD5 of all partitions before restoring ANY partitions.\n");
|
||||
} else
|
||||
LOGE("Restore: Unable to locate data partition.\n");
|
||||
}
|
||||
DataManager::GetValue(TW_RESTORE_CACHE_VAR, check);
|
||||
if (check > 0) {
|
||||
|
||||
if (restore_cache > 0) {
|
||||
Part = Find_Partition_By_Path("/cache");
|
||||
if (Part) {
|
||||
if (!Part->Restore(Restore_Name))
|
||||
@@ -362,8 +791,8 @@ LOGE("TO DO: Check MD5 of all partitions before restoring ANY partitions.\n");
|
||||
} else
|
||||
LOGE("Restore: Unable to locate cache partition.\n");
|
||||
}
|
||||
DataManager::GetValue(TW_RESTORE_BOOT_VAR, check);
|
||||
if (check > 0) {
|
||||
|
||||
if (restore_boot > 0) {
|
||||
Part = Find_Partition_By_Path("/boot");
|
||||
if (Part) {
|
||||
if (!Part->Restore(Restore_Name))
|
||||
@@ -371,8 +800,8 @@ LOGE("TO DO: Check MD5 of all partitions before restoring ANY partitions.\n");
|
||||
} else
|
||||
LOGE("Restore: Unable to locate boot partition.\n");
|
||||
}
|
||||
DataManager::GetValue(TW_RESTORE_ANDSEC_VAR, check);
|
||||
if (check > 0) {
|
||||
|
||||
if (restore_andsec > 0) {
|
||||
Part = Find_Partition_By_Path("/.android_secure");
|
||||
if (Part) {
|
||||
if (!Part->Restore(Restore_Name))
|
||||
@@ -380,8 +809,8 @@ LOGE("TO DO: Check MD5 of all partitions before restoring ANY partitions.\n");
|
||||
} else
|
||||
LOGE("Restore: Unable to locate android_secure partition.\n");
|
||||
}
|
||||
DataManager::GetValue(TW_RESTORE_SDEXT_VAR, check);
|
||||
if (check > 0) {
|
||||
|
||||
if (restore_sdext > 0) {
|
||||
Part = Find_Partition_By_Path("/sd-ext");
|
||||
if (Part) {
|
||||
if (!Part->Restore(Restore_Name))
|
||||
@@ -390,8 +819,7 @@ LOGE("TO DO: Check MD5 of all partitions before restoring ANY partitions.\n");
|
||||
LOGE("Restore: Unable to locate sd-ext partition.\n");
|
||||
}
|
||||
#ifdef SP1_NAME
|
||||
DataManager::GetValue(TW_RESTORE_SP1_VAR, check);
|
||||
if (check > 0) {
|
||||
if (restore_sp1 > 0) {
|
||||
Part = Find_Partition_By_Path(TWFunc::Get_Root_Path(SP1_NAME));
|
||||
if (Part) {
|
||||
if (!Part->Restore(Restore_Name))
|
||||
@@ -401,8 +829,7 @@ LOGE("TO DO: Check MD5 of all partitions before restoring ANY partitions.\n");
|
||||
}
|
||||
#endif
|
||||
#ifdef SP2_NAME
|
||||
DataManager::GetValue(TW_RESTORE_SP2_VAR, check);
|
||||
if (check > 0) {
|
||||
if (restore_sp2 > 0) {
|
||||
Part = Find_Partition_By_Path(TWFunc::Get_Root_Path(SP2_NAME));
|
||||
if (Part) {
|
||||
if (!Part->Restore(Restore_Name))
|
||||
@@ -412,8 +839,7 @@ LOGE("TO DO: Check MD5 of all partitions before restoring ANY partitions.\n");
|
||||
}
|
||||
#endif
|
||||
#ifdef SP3_NAME
|
||||
DataManager::GetValue(TW_RESTORE_SP3_VAR, check);
|
||||
if (check > 0) {
|
||||
if (restore_sp3 > 0) {
|
||||
Part = Find_Partition_By_Path(TWFunc::Get_Root_Path(SP3_NAME));
|
||||
if (Part) {
|
||||
if (!Part->Restore(Restore_Name))
|
||||
@@ -422,6 +848,7 @@ LOGE("TO DO: Check MD5 of all partitions before restoring ANY partitions.\n");
|
||||
LOGE("Restore: Unable to locate %s partition.\n", SP3_NAME);
|
||||
}
|
||||
#endif
|
||||
Update_System_Details();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ public:
|
||||
virtual bool UnMount(bool Display_Error); // Unmounts the partition if it is mounted
|
||||
virtual bool Wipe(); // Wipes the partition
|
||||
virtual bool Backup(string backup_folder); // Backs up the partition to the folder specified
|
||||
virtual bool Check_MD5(string restore_folder); // Checks MD5 of a backup
|
||||
virtual bool Restore(string restore_folder); // Restores the partition using the backup folder provided
|
||||
virtual string Backup_Method_By_Name(); // Returns a string of the backup method for human readable output
|
||||
virtual bool Decrypt(string Password); // Decrypts the partition, return 0 for failure and -1 for success
|
||||
@@ -106,7 +107,6 @@ private:
|
||||
bool Is_Image(string File_System); // Checks to see if the file system given is considered an image
|
||||
void Setup_File_System(bool Display_Error); // Sets defaults for a file system partition
|
||||
void Setup_Image(bool Display_Error); // Sets defaults for an image partition
|
||||
bool Path_Exists(string Path); // Checks to see if the Path exists in the file system
|
||||
void Find_Real_Block_Device(string& Block_Device, bool Display_Error); // Checks the block device given and follows symlinks until it gets to the real block device
|
||||
bool Find_Partition_Size(); // Finds the partition size from /proc/partitions
|
||||
unsigned long long Get_Size_Via_du(string Path, bool Display_Error); // Uses du to get sizes
|
||||
@@ -125,7 +125,6 @@ private:
|
||||
bool Restore_Flash_Image(string restore_folder); // Restore using flash_image for MTD memory types
|
||||
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
|
||||
unsigned long long Get_Folder_Size(string Path, bool Display_Error); // Gets the size of the files in a folder and all of its subfolders
|
||||
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
|
||||
|
||||
@@ -155,7 +154,7 @@ public:
|
||||
TWPartition* Find_Partition_By_Path(string Path); // Returns a pointer to a partition based on path
|
||||
TWPartition* Find_Partition_By_Block(string Block); // Returns a pointer to a partition based on block device
|
||||
TWPartition* Find_Partition_By_Name(string Block); // Returns a pointer to a partition based on name
|
||||
virtual int Run_Backup(string Backup_Name); // Initiates a backup in the current storage
|
||||
virtual int Run_Backup(); // Initiates a backup in the current storage
|
||||
virtual int Run_Restore(string Restore_Name); // Restores a backup
|
||||
virtual void Set_Restore_Files(string Restore_Name); // Used to gather a list of available backup partitions for the user to select for a restore
|
||||
virtual int Wipe_By_Path(string Path); // Wipes a partition based on path
|
||||
@@ -172,6 +171,10 @@ public:
|
||||
virtual int Decrypt_Device(string Password); // Attempt to decrypt any encrypted partitions
|
||||
virtual int Fix_Permissions(); // Fixes permissions in /system and /data
|
||||
|
||||
private:
|
||||
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);
|
||||
|
||||
private:
|
||||
std::vector<TWPartition*> Partitions; // Vector list of all partitions
|
||||
};
|
||||
|
||||
@@ -39,6 +39,7 @@ RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libbmlutils.so
|
||||
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libflashutils.so
|
||||
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libstlport.so
|
||||
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libmincrypt.so
|
||||
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libext4_utils.so
|
||||
ifeq ($(TW_INCLUDE_BLOBPACK), true)
|
||||
RELINK_SOURCE_FILES += $(TARGET_RECOVERY_ROOT_OUT)/sbin/blobpack
|
||||
endif
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <vector>
|
||||
#include <dirent.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "twrp-functions.hpp"
|
||||
#include "partitions.hpp"
|
||||
@@ -162,3 +163,73 @@ void TWFunc::htc_dumlock_reflash_recovery_to_boot(void) {
|
||||
__system("htcdumlock recovery noreboot");
|
||||
ui_print("Recovery is flashed to boot.\n");
|
||||
}
|
||||
|
||||
int TWFunc::Recursive_Mkdir(string Path) {
|
||||
string pathCpy = Path;
|
||||
string wholePath;
|
||||
size_t pos = pathCpy.find("/", 2);
|
||||
|
||||
while (pos != string::npos)
|
||||
{
|
||||
wholePath = pathCpy.substr(0, pos);
|
||||
if (mkdir(wholePath.c_str(), 0777) && errno != EEXIST) {
|
||||
LOGE("Unable to create folder: %s (errno=%d)\n", wholePath.c_str(), errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
pos = pathCpy.find("/", pos + 1);
|
||||
}
|
||||
if (mkdir(wholePath.c_str(), 0777) && errno != EEXIST)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned long long TWFunc::Get_Folder_Size(string Path, bool Display_Error) {
|
||||
DIR* d;
|
||||
struct dirent* de;
|
||||
struct stat st;
|
||||
char path2[1024], filename[1024];
|
||||
unsigned long long dusize = 0;
|
||||
|
||||
// Make a copy of path in case the data in the pointer gets overwritten later
|
||||
strcpy(path2, Path.c_str());
|
||||
|
||||
d = opendir(path2);
|
||||
if (d == NULL)
|
||||
{
|
||||
LOGE("error opening '%s'\n", path2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ((de = readdir(d)) != NULL)
|
||||
{
|
||||
if (de->d_type == DT_DIR && strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..") != 0)
|
||||
{
|
||||
strcpy(filename, path2);
|
||||
strcat(filename, "/");
|
||||
strcat(filename, de->d_name);
|
||||
dusize += Get_Folder_Size(filename, Display_Error);
|
||||
}
|
||||
else if (de->d_type == DT_REG)
|
||||
{
|
||||
strcpy(filename, path2);
|
||||
strcat(filename, "/");
|
||||
strcat(filename, de->d_name);
|
||||
stat(filename, &st);
|
||||
dusize += (unsigned long long)(st.st_size);
|
||||
}
|
||||
}
|
||||
closedir(d);
|
||||
|
||||
return dusize;
|
||||
}
|
||||
|
||||
bool TWFunc::Path_Exists(string Path) {
|
||||
// Check to see if the Path exists
|
||||
struct statfs st;
|
||||
|
||||
if (statfs(Path.c_str(), &st) != 0)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
@@ -10,13 +10,16 @@ class TWFunc
|
||||
{
|
||||
public:
|
||||
static int Check_MD5(string File);
|
||||
static string Get_Root_Path(string Path); // Trims any trailing folders or filenames from the path, also adds a leading / if not present
|
||||
static string Get_Path(string Path); // Trims everything after the last / in the string
|
||||
static string Get_Filename(string Path); // Trims the path off of a filename
|
||||
static string Get_Root_Path(string Path); // Trims any trailing folders or filenames from the path, also adds a leading / if not present
|
||||
static string Get_Path(string Path); // Trims everything after the last / in the string
|
||||
static string Get_Filename(string Path); // Trims the path off of a filename
|
||||
|
||||
static void install_htc_dumlock(void); // Installs HTC Dumlock
|
||||
static void htc_dumlock_restore_original_boot(void); // Restores the backup of boot from HTC Dumlock
|
||||
static void htc_dumlock_reflash_recovery_to_boot(void); // Reflashes the current recovery to boot
|
||||
static void install_htc_dumlock(void); // Installs HTC Dumlock
|
||||
static void htc_dumlock_restore_original_boot(void); // Restores the backup of boot from HTC Dumlock
|
||||
static void htc_dumlock_reflash_recovery_to_boot(void); // Reflashes the current recovery to boot
|
||||
static int Recursive_Mkdir(string Path); // Recursively makes the entire path
|
||||
static unsigned long long Get_Folder_Size(string Path, bool Display_Error); // Gets the size of a folder and all of its subfolders using dirent and stat
|
||||
static bool Path_Exists(string Path); // Returns true if the path exists
|
||||
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user