summaryrefslogtreecommitdiffstats
path: root/openrecoveryscript.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'openrecoveryscript.cpp')
-rw-r--r--openrecoveryscript.cpp289
1 files changed, 287 insertions, 2 deletions
diff --git a/openrecoveryscript.cpp b/openrecoveryscript.cpp
index 75db902e2..0d2268cd1 100644
--- a/openrecoveryscript.cpp
+++ b/openrecoveryscript.cpp
@@ -1,5 +1,5 @@
/*
- Copyright 2012 bigbiff/Dees_Troy TeamWin
+ Copyright 2016 TeamWin
This file is part of TWRP/TeamWin Recovery Project.
TWRP is free software: you can redistribute it and/or modify
@@ -16,6 +16,7 @@
along with TWRP. If not, see <http://www.gnu.org/licenses/>.
*/
+#define __STDC_FORMAT_MACROS 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -26,21 +27,31 @@
#include <dirent.h>
#include <time.h>
#include <errno.h>
+#include <inttypes.h>
#include <iostream>
#include <fstream>
+#include <sstream>
+#include <string>
+#include <iterator>
+#include <algorithm>
#include <sys/types.h>
#include <sys/wait.h>
+#include <zlib.h>
#include "twrp-functions.hpp"
#include "partitions.hpp"
#include "twcommon.h"
#include "openrecoveryscript.hpp"
+#include "progresstracking.hpp"
#include "variables.h"
#include "adb_install.h"
#include "data.hpp"
#include "adb_install.h"
#include "fuse_sideload.h"
#include "gui/gui.hpp"
+#include "gui/pages.hpp"
+#include "orscmd/orscmd.h"
+#include "adbbu/libtwadbbu.hpp"
extern "C" {
#include "twinstall.h"
#include "gui/gui.h"
@@ -139,6 +150,8 @@ int OpenRecoveryScript::run_script_file(void) {
// Wipe
if (strcmp(value, "cache") == 0 || strcmp(value, "/cache") == 0) {
PartitionManager.Wipe_By_Path("/cache");
+ } else if (strcmp(value, "system") == 0 || strcmp(value, "/system") == 0) {
+ PartitionManager.Wipe_By_Path("/system");
} else if (strcmp(value, "dalvik") == 0 || strcmp(value, "dalvick") == 0 || strcmp(value, "dalvikcache") == 0 || strcmp(value, "dalvickcache") == 0) {
PartitionManager.Wipe_Dalvik_Cache();
} else if (strcmp(value, "data") == 0 || strcmp(value, "/data") == 0 || strcmp(value, "factory") == 0 || strcmp(value, "factoryreset") == 0) {
@@ -280,6 +293,17 @@ int OpenRecoveryScript::run_script_file(void) {
ret_val = 1;
else
gui_msg("done=Done.");
+ } else if (strncmp(command, "adbbackup", 9) == 0) {
+ ret_val = Backup_ADB_Command(value);
+ if (ret_val == 1) {
+ twadbbu::Write_TWERROR();
+ gui_err("adbbackup_error=Error with ADB Backup. Quitting...");
+ }
+ } else if (strcmp(command, "adbrestore") == 0) {
+ LOGINFO("running adb restore\n");
+ ret_val = Restore_ADB_Backup();
+ } else if (strcmp(command, "remountrw") == 0) {
+ ret_val = remountrw();
} else if (strcmp(command, "mount") == 0) {
// Mount
DataManager::SetValue("tw_action_text2", gui_parse_text("{@mounting}"));
@@ -400,6 +424,7 @@ int OpenRecoveryScript::run_script_file(void) {
gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(SCRIPT_FILE_TMP)(strerror(errno)));
return 1;
}
+
if (install_cmd && DataManager::GetIntValue(TW_HAS_INJECTTWRP) == 1 && DataManager::GetIntValue(TW_INJECT_AFTER_ZIP) == 1) {
gui_msg("injecttwrp=Injecting TWRP into boot image...");
TWPartition* Boot = PartitionManager.Find_Partition_By_Path("/boot");
@@ -485,6 +510,72 @@ int OpenRecoveryScript::Install_Command(string Zip) {
return ret_val;
}
+int OpenRecoveryScript::Backup_ADB_Command(std::string Options) {
+ std::vector<std::string> args;
+ std::string Backup_List;
+ bool adbbackup = true, ret = false;
+ std::string rmopt = "--";
+
+ std::replace(Options.begin(), Options.end(), ':', ' ');
+ args = TWFunc::Split_String(Options, " ");
+
+ DataManager::SetValue(TW_USE_COMPRESSION_VAR, 0);
+ DataManager::SetValue(TW_SKIP_MD5_GENERATE_VAR, 0);
+
+ if (args[1].compare("--twrp") != 0) {
+ gui_err("twrp_adbbu_option=--twrp option is required to enable twrp adb backup");
+ sleep(2);
+ return 1;
+ }
+
+ for (unsigned i = 2; i < args.size(); i++) {
+ int compress;
+
+ std::string::size_type size = args[i].find(rmopt);
+ if (size != std::string::npos)
+ args[i].erase(size, rmopt.length());
+
+ if (args[i].compare("compress") == 0) {
+ gui_msg("compression_on=Compression is on");
+ DataManager::SetValue(TW_USE_COMPRESSION_VAR, 1);
+ continue;
+ }
+ DataManager::GetValue(TW_USE_COMPRESSION_VAR, compress);
+ gui_print("%s\n", args[i].c_str());
+ std::string path;
+ path = "/" + args[i];
+ TWPartition* part = PartitionManager.Find_Partition_By_Path(path);
+ if (part) {
+ Backup_List += path;
+ Backup_List += ";";
+ }
+ else {
+ gui_msg(Msg(msg::kError, "partition_not_found=path: {1} not found in partition list")(path));
+ return 1;
+ }
+ }
+
+ if (Backup_List.empty()) {
+ DataManager::GetValue("tw_backup_list", Backup_List);
+ if (Backup_List.empty()) {
+ gui_err("no_partition_selected=No partitions selected for backup.");
+ return 1;
+ }
+ }
+ else
+ DataManager::SetValue("tw_backup_list", Backup_List);
+
+ ret = PartitionManager.Run_Backup(adbbackup);
+ DataManager::SetValue(TW_BACKUP_NAME, gui_lookup("auto_generate", "(Auto Generate)"));
+ if (!ret) {
+ gui_err("backup_fail=Backup failed");
+ return 1;
+ }
+ gui_msg("backup_complete=Backup Complete");
+ sleep(2); //give time for user to see messages on console
+ return 0;
+}
+
string OpenRecoveryScript::Locate_Zip_File(string Zip, string Storage_Root) {
string Path = TWFunc::Get_Path(Zip);
string File = TWFunc::Get_Filename(Zip);
@@ -513,6 +604,7 @@ int OpenRecoveryScript::Backup_Command(string Options) {
char value1[SCRIPT_COMMAND_SIZE];
int line_len, i;
string Backup_List;
+ bool adbbackup = false;
strcpy(value1, Options.c_str());
@@ -558,7 +650,7 @@ int OpenRecoveryScript::Backup_Command(string Options) {
}
}
DataManager::SetValue("tw_backup_list", Backup_List);
- if (!PartitionManager.Run_Backup()) {
+ if (!PartitionManager.Run_Backup(false)) {
gui_err("backup_fail=Backup Failed");
return 1;
}
@@ -651,3 +743,196 @@ void OpenRecoveryScript::Run_CLI_Command(const char* command) {
call_after_cli_command();
LOGINFO("Done reading ORS command from command line\n");
}
+
+int OpenRecoveryScript::Restore_ADB_Backup(void) {
+ bool breakloop = false;
+ int partition_count = 0;
+ std::string Restore_Name;
+ std::size_t pos = 0;
+ struct AdbBackupFileTrailer adbmd5;
+ struct PartitionSettings part_settings;
+ int adb_control_twrp_fd, adb_write_fd, systemro;
+ int adb_control_bu_fd, ret = 0;
+ char cmd[512];
+ int orsfd = open(ORS_OUTPUT_FILE, O_WRONLY);
+
+ part_settings.total_restore_size = 0;
+
+ PartitionManager.Mount_All_Storage();
+ DataManager::SetValue(TW_SKIP_MD5_CHECK_VAR, 0);
+ LOGINFO("opening TW_ADB_BU_CONTROL\n");
+ adb_control_bu_fd = open(TW_ADB_BU_CONTROL, O_WRONLY | O_NONBLOCK);
+ LOGINFO("opening TW_ADB_TWRP_CONTROL\n");
+ adb_control_twrp_fd = open(TW_ADB_TWRP_CONTROL, O_RDONLY | O_NONBLOCK);
+ memset(&adbmd5, 0, sizeof(adbmd5));
+
+ while (!breakloop) {
+ memset(&cmd, 0, sizeof(cmd));
+ if (read(adb_control_twrp_fd, cmd, sizeof(cmd)) > 0) {
+ struct AdbBackupControlType cmdstruct;
+
+ memset(&cmdstruct, 0, sizeof(cmdstruct));
+ memcpy(&cmdstruct, cmd, sizeof(cmdstruct));
+ std::string cmdstr(cmdstruct.type);
+ std::string cmdtype = cmdstr.substr(0, sizeof(cmdstruct.type) - 1);
+ if (cmdstr.substr(0, sizeof(cmdstruct.type) - 1) == TWSTREAMHDR) {
+ struct AdbBackupStreamHeader twhdr;
+ memcpy(&twhdr, cmd, sizeof(cmd));
+ LOGINFO("ADB Partition count: %" PRIu64 "\n", twhdr.partition_count);
+ LOGINFO("ADB version: %" PRIu64 "\n", twhdr.version);
+ if (twhdr.version != ADB_BACKUP_VERSION) {
+ LOGERR("Incompatible adb backup version!\n");
+ breakloop = false;
+ break;
+ }
+ partition_count = twhdr.partition_count;
+ }
+ else if (cmdtype == MD5TRAILER) {
+ LOGINFO("Restoring MD5TRAILER\n");
+ memcpy(&adbmd5, cmd, sizeof(cmd));
+ }
+ else if (cmdtype == TWMD5) {
+ struct AdbBackupFileTrailer md5check;
+ LOGINFO("Restoring TWMD5\n");
+
+ memset(&md5check, 0, sizeof(md5check));
+ memcpy(&md5check, cmd, sizeof(cmd));
+ if (strcmp(md5check.md5, adbmd5.md5) != 0) {
+ LOGERR("md5 doesn't match!\n");
+ LOGERR("file md5: %s\n", adbmd5.md5);
+ LOGERR("check md5: %s\n", md5check.md5);
+ breakloop = true;
+ ret = 1;
+ break;
+ }
+ else {
+ LOGINFO("adbrestore md5 matches\n");
+ LOGINFO("adbmd5.md5: %s\n", adbmd5.md5);
+ LOGINFO("md5check.md5: %s\n", md5check.md5);
+ }
+ }
+ else if (cmdtype == TWENDADB) {
+ LOGINFO("received TWENDADB\n");
+ breakloop = true;
+ break;
+ }
+ else {
+ struct twfilehdr twimghdr;
+ memcpy(&twimghdr, cmd, sizeof(cmd));
+ std::string cmdstr(twimghdr.type);
+ Restore_Name = twimghdr.name;
+ part_settings.total_restore_size = twimghdr.size;
+ if (cmdtype == TWIMG) {
+ LOGINFO("ADB Type: %s\n", twimghdr.type);
+ LOGINFO("ADB Restore_Name: %s\n", Restore_Name.c_str());
+ LOGINFO("ADB Restore_size: %" PRIu64 "\n", part_settings.total_restore_size);
+ string compression = (twimghdr.compressed == 1) ? "compressed" : "uncompressed";
+ LOGINFO("ADB compression: %s\n", compression.c_str());
+ std::string Backup_FileName;
+ std::size_t pos = Restore_Name.find_last_of("/");
+ std::string path = "/" + Restore_Name.substr(pos, Restore_Name.size());
+ pos = path.find_first_of(".");
+ path = path.substr(0, pos);
+ if (path.substr(0,1).compare("//")) {
+ path = path.substr(1, path.size());
+ }
+
+ pos = Restore_Name.find_last_of("/");
+ Backup_FileName = Restore_Name.substr(pos + 1, Restore_Name.size());
+ part_settings.Part = PartitionManager.Find_Partition_By_Path(path);
+ part_settings.Restore_Name = path;
+ part_settings.partition_count = partition_count;
+ part_settings.adbbackup = true;
+ part_settings.adb_compression = twimghdr.compressed;
+ part_settings.Backup_FileName = Backup_FileName;
+ part_settings.PM_Method = PM_RESTORE;
+ ProgressTracking progress(part_settings.total_restore_size);
+ part_settings.progress = &progress;
+ if (!PartitionManager.Restore_Partition(&part_settings)) {
+ LOGERR("ADB Restore failed.\n");
+ return 1;
+ }
+ }
+ else if (cmdtype == TWFN) {
+ LOGINFO("ADB Type: %s\n", twimghdr.type);
+ LOGINFO("ADB Restore_Name: %s\n", Restore_Name.c_str());
+ LOGINFO("ADB Restore_size: %" PRIi64 "\n", part_settings.total_restore_size);
+ string compression = (twimghdr.compressed == 1) ? "compressed" : "uncompressed";
+ LOGINFO("ADB compression: %s\n", compression.c_str());
+ std::string Backup_FileName;
+ std::size_t pos = Restore_Name.find_last_of("/");
+ std::string path = "/" + Restore_Name.substr(pos, Restore_Name.size());
+ pos = path.find_first_of(".");
+ path = path.substr(0, pos);
+ if (path.substr(0,1).compare("//")) {
+ path = path.substr(1, path.size());
+ }
+
+ pos = Restore_Name.find_last_of("/");
+ Backup_FileName = Restore_Name.substr(pos + 1, Restore_Name.size());
+ pos = Restore_Name.find_last_of("/");
+ part_settings.Restore_Name = Restore_Name.substr(0, pos);
+ part_settings.Part = PartitionManager.Find_Partition_By_Path(path);
+
+ if (path.compare("/system") == 0) {
+ if (part_settings.Part->Is_Read_Only()) {
+ struct AdbBackupControlType twerror;
+ strncpy(twerror.start_of_header, TWRP, sizeof(twerror.start_of_header));
+ strncpy(twerror.type, TWERROR, sizeof(twerror.type));
+ memset(twerror.space, 0, sizeof(twerror.space));
+ twerror.crc = crc32(0L, Z_NULL, 0);
+ twerror.crc = crc32(twerror.crc, (const unsigned char*) &twerror, sizeof(twerror));
+ if (write(adb_control_bu_fd, &twerror, sizeof(twerror)) < 0) {
+ LOGERR("Cannot write to ADB_CONTROL_BU_FD: %s\n", strerror(errno));
+ }
+ gui_msg(Msg(msg::kError, "restore_read_only=Cannot restore {1} -- mounted read only.")(part_settings.Part->Backup_Display_Name));
+ return 1;
+
+ }
+ }
+ part_settings.partition_count = partition_count;
+ part_settings.adbbackup = true;
+ part_settings.adb_compression = twimghdr.compressed;
+ part_settings.Backup_FileName = Backup_FileName;
+ part_settings.total_restore_size += part_settings.Part->Get_Restore_Size(&part_settings);
+ part_settings.PM_Method = PM_RESTORE;
+ ProgressTracking progress(part_settings.total_restore_size);
+ part_settings.progress = &progress;
+ if (!PartitionManager.Restore_Partition(&part_settings)) {
+ LOGERR("ADB Restore failed.\n");
+ return 1;
+ }
+ }
+ }
+ }
+ }
+ gui_msg("restore_complete=Restore Complete");
+
+ if (!twadbbu::Write_TWENDADB())
+ ret = 1;
+ sleep(2); //give time for user to see messages on console
+ return ret;
+}
+
+int OpenRecoveryScript::remountrw(void)
+{
+ bool remount_system = PartitionManager.Is_Mounted_By_Path("/system");
+ int op_status;
+ TWPartition* Part;
+
+ if (!PartitionManager.UnMount_By_Path("/system", true)) {
+ op_status = 1; // fail
+ } else {
+ Part = PartitionManager.Find_Partition_By_Path("/system");
+ if (Part) {
+ DataManager::SetValue("tw_mount_system_ro", 0);
+ Part->Change_Mount_Read_Only(false);
+ }
+ if (remount_system) {
+ Part->Mount(true);
+ }
+ op_status = 0; // success
+ }
+
+ return op_status;
+}