bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 1 | /* |
| 2 | Copyright 2013 to 2017 TeamWin |
| 3 | This file is part of TWRP/TeamWin Recovery Project. |
| 4 | |
| 5 | TWRP is free software: you can redistribute it and/or modify |
| 6 | it under the terms of the GNU General Public License as published by |
| 7 | the Free Software Foundation, either version 3 of the License, or |
| 8 | (at your option) any later version. |
| 9 | |
| 10 | TWRP is distributed in the hope that it will be useful, |
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | GNU General Public License for more details. |
| 14 | |
| 15 | You should have received a copy of the GNU General Public License |
| 16 | along with TWRP. If not, see <http://www.gnu.org/licenses/>. |
| 17 | */ |
| 18 | |
| 19 | #define __STDC_FORMAT_MACROS 1 |
| 20 | #include <string> |
| 21 | #include <sys/wait.h> |
| 22 | #include <sys/stat.h> |
| 23 | #include <pthread.h> |
| 24 | #include <zlib.h> |
| 25 | #include <inttypes.h> |
| 26 | #include "twrpAdbBuFifo.hpp" |
| 27 | #include "twcommon.h" |
| 28 | #include "data.hpp" |
| 29 | #include "variables.h" |
| 30 | #include "partitions.hpp" |
| 31 | #include "twrp-functions.hpp" |
| 32 | #include "gui/gui.hpp" |
| 33 | #include "gui/objects.hpp" |
| 34 | #include "gui/pages.hpp" |
| 35 | #include "adbbu/twadbstream.h" |
| 36 | #include "adbbu/libtwadbbu.hpp" |
| 37 | |
| 38 | twrpAdbBuFifo::twrpAdbBuFifo(void) { |
| 39 | unlink(TW_ADB_FIFO); |
| 40 | } |
| 41 | |
bigbiff bigbiff | adcb4d8 | 2017-09-25 10:51:56 -0400 | [diff] [blame] | 42 | void twrpAdbBuFifo::Check_Adb_Fifo_For_Events(void) { |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 43 | char cmd[512]; |
| 44 | |
| 45 | memset(&cmd, 0, sizeof(cmd)); |
| 46 | |
| 47 | if (read(adb_fifo_fd, &cmd, sizeof(cmd)) > 0) { |
| 48 | LOGINFO("adb backup cmd: %s\n", cmd); |
| 49 | std::string cmdcheck(cmd); |
| 50 | cmdcheck = cmdcheck.substr(0, strlen(ADB_BACKUP_OP)); |
| 51 | std::string Options(cmd); |
| 52 | Options = Options.substr(strlen(ADB_BACKUP_OP) + 1, strlen(cmd)); |
| 53 | if (cmdcheck == ADB_BACKUP_OP) |
bigbiff bigbiff | adcb4d8 | 2017-09-25 10:51:56 -0400 | [diff] [blame] | 54 | Backup_ADB_Command(Options); |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 55 | else { |
bigbiff bigbiff | adcb4d8 | 2017-09-25 10:51:56 -0400 | [diff] [blame] | 56 | Restore_ADB_Backup(); |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 57 | } |
| 58 | } |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 59 | } |
| 60 | |
| 61 | bool twrpAdbBuFifo::start(void) { |
| 62 | LOGINFO("Starting Adb Backup FIFO\n"); |
| 63 | unlink(TW_ADB_FIFO); |
| 64 | if (mkfifo(TW_ADB_FIFO, 06660) != 0) { |
| 65 | LOGINFO("Unable to mkfifo %s\n", TW_ADB_FIFO); |
| 66 | return false; |
| 67 | } |
| 68 | adb_fifo_fd = open(TW_ADB_FIFO, O_RDONLY | O_NONBLOCK); |
| 69 | if (adb_fifo_fd < 0) { |
| 70 | LOGERR("Unable to open TW_ADB_FIFO for reading.\n"); |
| 71 | close(adb_fifo_fd); |
| 72 | return false; |
| 73 | } |
| 74 | while (true) { |
| 75 | Check_Adb_Fifo_For_Events(); |
| 76 | usleep(8000); |
| 77 | } |
| 78 | //Shouldn't get here but cleanup anwyay |
| 79 | close(adb_fifo_fd); |
| 80 | return true; |
| 81 | } |
| 82 | |
| 83 | pthread_t twrpAdbBuFifo::threadAdbBuFifo(void) { |
| 84 | pthread_t thread; |
| 85 | ThreadPtr adbfifo = &twrpAdbBuFifo::start; |
| 86 | PThreadPtr p = *(PThreadPtr*)&adbfifo; |
| 87 | pthread_create(&thread, NULL, p, this); |
| 88 | return thread; |
| 89 | } |
| 90 | |
| 91 | bool twrpAdbBuFifo::Backup_ADB_Command(std::string Options) { |
| 92 | std::vector<std::string> args; |
| 93 | std::string Backup_List; |
| 94 | bool adbbackup = true, ret = false; |
| 95 | std::string rmopt = "--"; |
| 96 | |
| 97 | std::replace(Options.begin(), Options.end(), ':', ' '); |
| 98 | args = TWFunc::Split_String(Options, " "); |
| 99 | |
| 100 | DataManager::SetValue(TW_USE_COMPRESSION_VAR, 0); |
| 101 | DataManager::SetValue(TW_SKIP_DIGEST_GENERATE_VAR, 0); |
| 102 | |
| 103 | if (args[1].compare("--twrp") != 0) { |
| 104 | gui_err("twrp_adbbu_option=--twrp option is required to enable twrp adb backup"); |
bigbiff bigbiff | 38b83c1 | 2017-12-28 19:58:52 -0500 | [diff] [blame] | 105 | if (!twadbbu::Write_TWERROR()) |
| 106 | LOGERR("Unable to write to ADB Backup\n"); |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 107 | sleep(2); |
| 108 | return false; |
| 109 | } |
| 110 | |
| 111 | for (unsigned i = 2; i < args.size(); i++) { |
| 112 | int compress; |
| 113 | |
| 114 | std::string::size_type size = args[i].find(rmopt); |
| 115 | if (size != std::string::npos) |
| 116 | args[i].erase(size, rmopt.length()); |
| 117 | |
| 118 | if (args[i].compare("compress") == 0) { |
| 119 | gui_msg("compression_on=Compression is on"); |
| 120 | DataManager::SetValue(TW_USE_COMPRESSION_VAR, 1); |
| 121 | continue; |
| 122 | } |
| 123 | DataManager::GetValue(TW_USE_COMPRESSION_VAR, compress); |
| 124 | gui_print("%s\n", args[i].c_str()); |
| 125 | std::string path; |
| 126 | path = "/" + args[i]; |
| 127 | TWPartition* part = PartitionManager.Find_Partition_By_Path(path); |
| 128 | if (part) { |
| 129 | Backup_List += path; |
| 130 | Backup_List += ";"; |
| 131 | } |
| 132 | else { |
| 133 | gui_msg(Msg(msg::kError, "partition_not_found=path: {1} not found in partition list")(path)); |
bigbiff bigbiff | 38b83c1 | 2017-12-28 19:58:52 -0500 | [diff] [blame] | 134 | if (!twadbbu::Write_TWERROR()) |
| 135 | LOGERR("Unable to write to TWRP ADB Backup.\n"); |
| 136 | return false; |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 137 | } |
bigbiff bigbiff | 38b83c1 | 2017-12-28 19:58:52 -0500 | [diff] [blame] | 138 | } |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 139 | |
| 140 | if (Backup_List.empty()) { |
| 141 | DataManager::GetValue("tw_backup_list", Backup_List); |
| 142 | if (Backup_List.empty()) { |
| 143 | gui_err("no_partition_selected=No partitions selected for backup."); |
| 144 | return false; |
| 145 | } |
| 146 | } |
| 147 | else |
| 148 | DataManager::SetValue("tw_backup_list", Backup_List); |
| 149 | |
| 150 | DataManager::SetValue("tw_action", "clear"); |
| 151 | DataManager::SetValue("tw_action_text1", gui_lookup("running_recovery_commands", "Running Recovery Commands")); |
| 152 | DataManager::SetValue("tw_action_text2", ""); |
| 153 | gui_changePage("action_page"); |
| 154 | |
| 155 | ret = PartitionManager.Run_Backup(adbbackup); |
| 156 | DataManager::SetValue(TW_BACKUP_NAME, gui_lookup("auto_generate", "(Auto Generate)")); |
| 157 | if (!ret) { |
| 158 | gui_err("backup_fail=Backup failed"); |
| 159 | return false; |
| 160 | } |
| 161 | gui_msg("backup_complete=Backup Complete"); |
| 162 | DataManager::SetValue("ui_progress", 100); |
| 163 | sleep(2); //give time for user to see messages on console |
| 164 | gui_changePage("main"); |
| 165 | return true; |
| 166 | } |
| 167 | |
| 168 | bool twrpAdbBuFifo::Restore_ADB_Backup(void) { |
| 169 | int partition_count = 0; |
| 170 | std::string Restore_Name; |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 171 | struct AdbBackupFileTrailer adbmd5; |
| 172 | struct PartitionSettings part_settings; |
Ethan Yonker | 58f2132 | 2018-08-24 11:17:36 -0500 | [diff] [blame] | 173 | int adb_control_twrp_fd; |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 174 | int adb_control_bu_fd, ret = 0; |
| 175 | char cmd[512]; |
| 176 | |
| 177 | part_settings.total_restore_size = 0; |
| 178 | |
| 179 | PartitionManager.Mount_All_Storage(); |
| 180 | DataManager::SetValue(TW_SKIP_DIGEST_CHECK_VAR, 0); |
| 181 | LOGINFO("opening TW_ADB_BU_CONTROL\n"); |
| 182 | adb_control_bu_fd = open(TW_ADB_BU_CONTROL, O_WRONLY | O_NONBLOCK); |
| 183 | LOGINFO("opening TW_ADB_TWRP_CONTROL\n"); |
| 184 | adb_control_twrp_fd = open(TW_ADB_TWRP_CONTROL, O_RDONLY | O_NONBLOCK); |
| 185 | memset(&adbmd5, 0, sizeof(adbmd5)); |
| 186 | |
| 187 | DataManager::SetValue("tw_action", "clear"); |
| 188 | DataManager::SetValue("tw_action_text1", gui_lookup("running_recovery_commands", "Running Recovery Commands")); |
| 189 | DataManager::SetValue("tw_action_text2", ""); |
| 190 | gui_changePage("action_page"); |
| 191 | |
bigbiff bigbiff | 38b83c1 | 2017-12-28 19:58:52 -0500 | [diff] [blame] | 192 | while (true) { |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 193 | memset(&cmd, 0, sizeof(cmd)); |
| 194 | if (read(adb_control_twrp_fd, cmd, sizeof(cmd)) > 0) { |
| 195 | struct AdbBackupControlType cmdstruct; |
| 196 | |
| 197 | memset(&cmdstruct, 0, sizeof(cmdstruct)); |
| 198 | memcpy(&cmdstruct, cmd, sizeof(cmdstruct)); |
bigbiff bigbiff | adcb4d8 | 2017-09-25 10:51:56 -0400 | [diff] [blame] | 199 | std::string cmdtype = cmdstruct.get_type(); |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 200 | if (cmdtype == TWSTREAMHDR) { |
| 201 | struct AdbBackupStreamHeader twhdr; |
| 202 | memcpy(&twhdr, cmd, sizeof(cmd)); |
| 203 | LOGINFO("ADB Partition count: %" PRIu64 "\n", twhdr.partition_count); |
| 204 | LOGINFO("ADB version: %" PRIu64 "\n", twhdr.version); |
| 205 | if (twhdr.version != ADB_BACKUP_VERSION) { |
| 206 | LOGERR("Incompatible adb backup version!\n"); |
bigbiff bigbiff | 38b83c1 | 2017-12-28 19:58:52 -0500 | [diff] [blame] | 207 | ret = false; |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 208 | break; |
| 209 | } |
| 210 | partition_count = twhdr.partition_count; |
| 211 | } |
| 212 | else if (cmdtype == MD5TRAILER) { |
bigbiff bigbiff | 38b83c1 | 2017-12-28 19:58:52 -0500 | [diff] [blame] | 213 | LOGINFO("Reading ADB Backup MD5TRAILER\n"); |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 214 | memcpy(&adbmd5, cmd, sizeof(cmd)); |
| 215 | } |
| 216 | else if (cmdtype == TWMD5) { |
bigbiff bigbiff | 38b83c1 | 2017-12-28 19:58:52 -0500 | [diff] [blame] | 217 | int check_digest; |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 218 | |
bigbiff bigbiff | 38b83c1 | 2017-12-28 19:58:52 -0500 | [diff] [blame] | 219 | DataManager::GetValue(TW_SKIP_DIGEST_CHECK_VAR, check_digest); |
| 220 | if (check_digest > 0) { |
| 221 | TWFunc::GUI_Operation_Text(TW_VERIFY_DIGEST_TEXT, gui_parse_text("{@verifying_digest}")); |
| 222 | gui_msg("verifying_digest=Verifying Digest"); |
| 223 | struct AdbBackupFileTrailer md5check; |
| 224 | LOGINFO("Verifying md5sums\n"); |
| 225 | |
| 226 | memset(&md5check, 0, sizeof(md5check)); |
| 227 | memcpy(&md5check, cmd, sizeof(cmd)); |
| 228 | if (strcmp(md5check.md5, adbmd5.md5) != 0) { |
| 229 | LOGERR("md5 doesn't match!\n"); |
| 230 | LOGERR("Stored file md5: %s\n", adbmd5.md5); |
| 231 | LOGERR("ADB Backup check md5: %s\n", md5check.md5); |
| 232 | ret = false; |
| 233 | break; |
| 234 | } |
| 235 | else { |
| 236 | LOGINFO("ADB Backup md5 matches\n"); |
| 237 | LOGINFO("Stored file md5: %s\n", adbmd5.md5); |
| 238 | LOGINFO("ADB Backup check md5: %s\n", md5check.md5); |
| 239 | continue; |
| 240 | } |
| 241 | } else { |
| 242 | gui_msg("skip_digest=Skipping Digest check based on user setting."); |
| 243 | continue; |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 244 | } |
bigbiff bigbiff | 38b83c1 | 2017-12-28 19:58:52 -0500 | [diff] [blame] | 245 | |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 246 | } |
| 247 | else if (cmdtype == TWENDADB) { |
| 248 | LOGINFO("received TWENDADB\n"); |
bigbiff bigbiff | 38b83c1 | 2017-12-28 19:58:52 -0500 | [diff] [blame] | 249 | ret = 1; |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 250 | break; |
| 251 | } |
| 252 | else { |
| 253 | struct twfilehdr twimghdr; |
| 254 | memcpy(&twimghdr, cmd, sizeof(cmd)); |
| 255 | std::string cmdstr(twimghdr.type); |
| 256 | Restore_Name = twimghdr.name; |
| 257 | part_settings.total_restore_size = twimghdr.size; |
| 258 | if (cmdtype == TWIMG) { |
| 259 | LOGINFO("ADB Type: %s\n", twimghdr.type); |
| 260 | LOGINFO("ADB Restore_Name: %s\n", Restore_Name.c_str()); |
| 261 | LOGINFO("ADB Restore_size: %" PRIu64 "\n", part_settings.total_restore_size); |
| 262 | string compression = (twimghdr.compressed == 1) ? "compressed" : "uncompressed"; |
| 263 | LOGINFO("ADB compression: %s\n", compression.c_str()); |
| 264 | std::string Backup_FileName; |
| 265 | std::size_t pos = Restore_Name.find_last_of("/"); |
| 266 | std::string path = "/" + Restore_Name.substr(pos, Restore_Name.size()); |
| 267 | pos = path.find_first_of("."); |
| 268 | path = path.substr(0, pos); |
| 269 | if (path.substr(0,1).compare("//")) { |
| 270 | path = path.substr(1, path.size()); |
| 271 | } |
| 272 | |
| 273 | pos = Restore_Name.find_last_of("/"); |
| 274 | Backup_FileName = Restore_Name.substr(pos + 1, Restore_Name.size()); |
| 275 | part_settings.Part = PartitionManager.Find_Partition_By_Path(path); |
| 276 | part_settings.Backup_Folder = path; |
| 277 | PartitionManager.Set_Restore_Files(path); |
| 278 | part_settings.partition_count = partition_count; |
| 279 | part_settings.adbbackup = true; |
| 280 | part_settings.adb_compression = twimghdr.compressed; |
| 281 | part_settings.PM_Method = PM_RESTORE; |
| 282 | ProgressTracking progress(part_settings.total_restore_size); |
| 283 | part_settings.progress = &progress; |
| 284 | if (!PartitionManager.Restore_Partition(&part_settings)) { |
| 285 | LOGERR("ADB Restore failed.\n"); |
bigbiff bigbiff | adcb4d8 | 2017-09-25 10:51:56 -0400 | [diff] [blame] | 286 | ret = false; |
bigbiff bigbiff | 38b83c1 | 2017-12-28 19:58:52 -0500 | [diff] [blame] | 287 | break; |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 288 | } |
| 289 | } |
| 290 | else if (cmdtype == TWFN) { |
| 291 | LOGINFO("ADB Type: %s\n", twimghdr.type); |
| 292 | LOGINFO("ADB Restore_Name: %s\n", Restore_Name.c_str()); |
| 293 | LOGINFO("ADB Restore_size: %" PRIi64 "\n", part_settings.total_restore_size); |
| 294 | string compression = (twimghdr.compressed == 1) ? "compressed" : "uncompressed"; |
| 295 | LOGINFO("ADB compression: %s\n", compression.c_str()); |
| 296 | std::string Backup_FileName; |
| 297 | std::size_t pos = Restore_Name.find_last_of("/"); |
| 298 | std::string path = "/" + Restore_Name.substr(pos, Restore_Name.size()); |
| 299 | pos = path.find_first_of("."); |
| 300 | path = path.substr(0, pos); |
| 301 | if (path.substr(0,1).compare("//")) { |
| 302 | path = path.substr(1, path.size()); |
| 303 | } |
| 304 | |
| 305 | pos = Restore_Name.find_last_of("/"); |
| 306 | Backup_FileName = Restore_Name.substr(pos + 1, Restore_Name.size()); |
| 307 | pos = Restore_Name.find_last_of("/"); |
| 308 | part_settings.Part = PartitionManager.Find_Partition_By_Path(path); |
| 309 | part_settings.Part->Set_Backup_FileName(Backup_FileName); |
| 310 | PartitionManager.Set_Restore_Files(path); |
| 311 | |
| 312 | if (path.compare("/system") == 0) { |
| 313 | if (part_settings.Part->Is_Read_Only()) { |
bigbiff bigbiff | 38b83c1 | 2017-12-28 19:58:52 -0500 | [diff] [blame] | 314 | if (!twadbbu::Write_TWERROR()) |
| 315 | LOGERR("Unable to write to TWRP ADB Backup.\n"); |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 316 | gui_msg(Msg(msg::kError, "restore_read_only=Cannot restore {1} -- mounted read only.")(part_settings.Part->Backup_Display_Name)); |
bigbiff bigbiff | 38b83c1 | 2017-12-28 19:58:52 -0500 | [diff] [blame] | 317 | ret = false; |
| 318 | break; |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 319 | |
| 320 | } |
| 321 | } |
| 322 | part_settings.partition_count = partition_count; |
| 323 | part_settings.adbbackup = true; |
| 324 | part_settings.adb_compression = twimghdr.compressed; |
| 325 | part_settings.total_restore_size += part_settings.Part->Get_Restore_Size(&part_settings); |
| 326 | part_settings.PM_Method = PM_RESTORE; |
| 327 | ProgressTracking progress(part_settings.total_restore_size); |
| 328 | part_settings.progress = &progress; |
| 329 | if (!PartitionManager.Restore_Partition(&part_settings)) { |
| 330 | LOGERR("ADB Restore failed.\n"); |
bigbiff bigbiff | adcb4d8 | 2017-09-25 10:51:56 -0400 | [diff] [blame] | 331 | ret = false; |
bigbiff bigbiff | 38b83c1 | 2017-12-28 19:58:52 -0500 | [diff] [blame] | 332 | break; |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 333 | } |
| 334 | } |
| 335 | } |
| 336 | } |
| 337 | } |
bigbiff bigbiff | adcb4d8 | 2017-09-25 10:51:56 -0400 | [diff] [blame] | 338 | |
| 339 | if (ret != false) |
| 340 | gui_msg("restore_complete=Restore Complete"); |
| 341 | else |
| 342 | gui_err("restore_error=Error during restore process."); |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 343 | |
| 344 | if (!twadbbu::Write_TWENDADB()) |
| 345 | ret = false; |
| 346 | sleep(2); //give time for user to see messages on console |
| 347 | DataManager::SetValue("ui_progress", 100); |
| 348 | gui_changePage("main"); |
bigbiff bigbiff | adcb4d8 | 2017-09-25 10:51:56 -0400 | [diff] [blame] | 349 | close(adb_control_bu_fd); |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 350 | return ret; |
| 351 | } |