summaryrefslogtreecommitdiffstats
path: root/twrpAdbBuFifo.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--twrpAdbBuFifo.cpp342
1 files changed, 342 insertions, 0 deletions
diff --git a/twrpAdbBuFifo.cpp b/twrpAdbBuFifo.cpp
new file mode 100644
index 000000000..0c7dd1524
--- /dev/null
+++ b/twrpAdbBuFifo.cpp
@@ -0,0 +1,342 @@
+/*
+ Copyright 2013 to 2017 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/>.
+*/
+
+#define __STDC_FORMAT_MACROS 1
+#include <string>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <pthread.h>
+#include <zlib.h>
+#include <inttypes.h>
+#include "twrpAdbBuFifo.hpp"
+#include "twcommon.h"
+#include "data.hpp"
+#include "variables.h"
+#include "partitions.hpp"
+#include "twrp-functions.hpp"
+#include "gui/gui.hpp"
+#include "gui/objects.hpp"
+#include "gui/pages.hpp"
+#include "adbbu/twadbstream.h"
+#include "adbbu/libtwadbbu.hpp"
+
+twrpAdbBuFifo::twrpAdbBuFifo(void) {
+ unlink(TW_ADB_FIFO);
+}
+
+void twrpAdbBuFifo::Check_Adb_Fifo_For_Events(void) {
+ char cmd[512];
+ int ret;
+
+ memset(&cmd, 0, sizeof(cmd));
+
+ if (read(adb_fifo_fd, &cmd, sizeof(cmd)) > 0) {
+ LOGINFO("adb backup cmd: %s\n", cmd);
+ std::string cmdcheck(cmd);
+ cmdcheck = cmdcheck.substr(0, strlen(ADB_BACKUP_OP));
+ std::string Options(cmd);
+ Options = Options.substr(strlen(ADB_BACKUP_OP) + 1, strlen(cmd));
+ if (cmdcheck == ADB_BACKUP_OP)
+ Backup_ADB_Command(Options);
+ else {
+ Restore_ADB_Backup();
+ }
+ }
+}
+
+bool twrpAdbBuFifo::start(void) {
+ LOGINFO("Starting Adb Backup FIFO\n");
+ unlink(TW_ADB_FIFO);
+ if (mkfifo(TW_ADB_FIFO, 06660) != 0) {
+ LOGINFO("Unable to mkfifo %s\n", TW_ADB_FIFO);
+ return false;
+ }
+ adb_fifo_fd = open(TW_ADB_FIFO, O_RDONLY | O_NONBLOCK);
+ if (adb_fifo_fd < 0) {
+ LOGERR("Unable to open TW_ADB_FIFO for reading.\n");
+ close(adb_fifo_fd);
+ return false;
+ }
+ while (true) {
+ Check_Adb_Fifo_For_Events();
+ usleep(8000);
+ }
+ //Shouldn't get here but cleanup anwyay
+ close(adb_fifo_fd);
+ return true;
+}
+
+pthread_t twrpAdbBuFifo::threadAdbBuFifo(void) {
+ pthread_t thread;
+ ThreadPtr adbfifo = &twrpAdbBuFifo::start;
+ PThreadPtr p = *(PThreadPtr*)&adbfifo;
+ pthread_create(&thread, NULL, p, this);
+ return thread;
+}
+
+bool twrpAdbBuFifo::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_DIGEST_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 false;
+ }
+
+ 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 false;
+ }
+ }
+
+ 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 false;
+ }
+ }
+ else
+ DataManager::SetValue("tw_backup_list", Backup_List);
+
+ DataManager::SetValue("tw_action", "clear");
+ DataManager::SetValue("tw_action_text1", gui_lookup("running_recovery_commands", "Running Recovery Commands"));
+ DataManager::SetValue("tw_action_text2", "");
+ gui_changePage("action_page");
+
+ 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 false;
+ }
+ gui_msg("backup_complete=Backup Complete");
+ DataManager::SetValue("ui_progress", 100);
+ sleep(2); //give time for user to see messages on console
+ gui_changePage("main");
+ return true;
+}
+
+bool twrpAdbBuFifo::Restore_ADB_Backup(void) {
+ 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];
+
+ part_settings.total_restore_size = 0;
+
+ PartitionManager.Mount_All_Storage();
+ DataManager::SetValue(TW_SKIP_DIGEST_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));
+
+ DataManager::SetValue("tw_action", "clear");
+ DataManager::SetValue("tw_action_text1", gui_lookup("running_recovery_commands", "Running Recovery Commands"));
+ DataManager::SetValue("tw_action_text2", "");
+ gui_changePage("action_page");
+
+ while (1) {
+ 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 cmdtype = cmdstruct.get_type();
+ if (cmdtype == 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");
+ 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);
+ ret = false;
+ break;
+ }
+ else {
+ LOGINFO("adbrestore md5 matches\n");
+ LOGINFO("adbmd5.md5: %s\n", adbmd5.md5);
+ LOGINFO("md5check.md5: %s\n", md5check.md5);
+ ret = true;
+ break;
+ }
+ }
+ else if (cmdtype == TWENDADB) {
+ LOGINFO("received TWENDADB\n");
+ 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.Backup_Folder = path;
+ PartitionManager.Set_Restore_Files(path);
+ part_settings.partition_count = partition_count;
+ part_settings.adbbackup = true;
+ part_settings.adb_compression = twimghdr.compressed;
+ 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");
+ ret = false;
+ }
+ }
+ 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.Part = PartitionManager.Find_Partition_By_Path(path);
+ part_settings.Part->Set_Backup_FileName(Backup_FileName);
+ PartitionManager.Set_Restore_Files(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 false;
+
+ }
+ }
+ part_settings.partition_count = partition_count;
+ part_settings.adbbackup = true;
+ part_settings.adb_compression = twimghdr.compressed;
+ 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");
+ ret = false;
+ }
+ }
+ }
+ }
+ }
+
+ if (ret != false)
+ gui_msg("restore_complete=Restore Complete");
+ else
+ gui_err("restore_error=Error during restore process.");
+
+ if (!twadbbu::Write_TWENDADB())
+ ret = false;
+ sleep(2); //give time for user to see messages on console
+ DataManager::SetValue("ui_progress", 100);
+ gui_changePage("main");
+ close(adb_control_bu_fd);
+ close(adb_control_twrp_fd);
+ return ret;
+}