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]; |
bigbiff bigbiff | adcb4d8 | 2017-09-25 10:51:56 -0400 | [diff] [blame] | 44 | int ret; |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 45 | |
| 46 | memset(&cmd, 0, sizeof(cmd)); |
| 47 | |
| 48 | if (read(adb_fifo_fd, &cmd, sizeof(cmd)) > 0) { |
| 49 | LOGINFO("adb backup cmd: %s\n", cmd); |
| 50 | std::string cmdcheck(cmd); |
| 51 | cmdcheck = cmdcheck.substr(0, strlen(ADB_BACKUP_OP)); |
| 52 | std::string Options(cmd); |
| 53 | Options = Options.substr(strlen(ADB_BACKUP_OP) + 1, strlen(cmd)); |
| 54 | if (cmdcheck == ADB_BACKUP_OP) |
bigbiff bigbiff | adcb4d8 | 2017-09-25 10:51:56 -0400 | [diff] [blame] | 55 | Backup_ADB_Command(Options); |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 56 | else { |
bigbiff bigbiff | adcb4d8 | 2017-09-25 10:51:56 -0400 | [diff] [blame] | 57 | Restore_ADB_Backup(); |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 58 | } |
| 59 | } |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 60 | } |
| 61 | |
| 62 | bool twrpAdbBuFifo::start(void) { |
| 63 | LOGINFO("Starting Adb Backup FIFO\n"); |
| 64 | unlink(TW_ADB_FIFO); |
| 65 | if (mkfifo(TW_ADB_FIFO, 06660) != 0) { |
| 66 | LOGINFO("Unable to mkfifo %s\n", TW_ADB_FIFO); |
| 67 | return false; |
| 68 | } |
| 69 | adb_fifo_fd = open(TW_ADB_FIFO, O_RDONLY | O_NONBLOCK); |
| 70 | if (adb_fifo_fd < 0) { |
| 71 | LOGERR("Unable to open TW_ADB_FIFO for reading.\n"); |
| 72 | close(adb_fifo_fd); |
| 73 | return false; |
| 74 | } |
| 75 | while (true) { |
| 76 | Check_Adb_Fifo_For_Events(); |
| 77 | usleep(8000); |
| 78 | } |
| 79 | //Shouldn't get here but cleanup anwyay |
| 80 | close(adb_fifo_fd); |
| 81 | return true; |
| 82 | } |
| 83 | |
| 84 | pthread_t twrpAdbBuFifo::threadAdbBuFifo(void) { |
| 85 | pthread_t thread; |
| 86 | ThreadPtr adbfifo = &twrpAdbBuFifo::start; |
| 87 | PThreadPtr p = *(PThreadPtr*)&adbfifo; |
| 88 | pthread_create(&thread, NULL, p, this); |
| 89 | return thread; |
| 90 | } |
| 91 | |
| 92 | bool twrpAdbBuFifo::Backup_ADB_Command(std::string Options) { |
| 93 | std::vector<std::string> args; |
| 94 | std::string Backup_List; |
| 95 | bool adbbackup = true, ret = false; |
| 96 | std::string rmopt = "--"; |
| 97 | |
| 98 | std::replace(Options.begin(), Options.end(), ':', ' '); |
| 99 | args = TWFunc::Split_String(Options, " "); |
| 100 | |
| 101 | DataManager::SetValue(TW_USE_COMPRESSION_VAR, 0); |
| 102 | DataManager::SetValue(TW_SKIP_DIGEST_GENERATE_VAR, 0); |
| 103 | |
| 104 | if (args[1].compare("--twrp") != 0) { |
| 105 | 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] | 106 | if (!twadbbu::Write_TWERROR()) |
| 107 | LOGERR("Unable to write to ADB Backup\n"); |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 108 | sleep(2); |
| 109 | return false; |
| 110 | } |
| 111 | |
| 112 | for (unsigned i = 2; i < args.size(); i++) { |
| 113 | int compress; |
| 114 | |
| 115 | std::string::size_type size = args[i].find(rmopt); |
| 116 | if (size != std::string::npos) |
| 117 | args[i].erase(size, rmopt.length()); |
| 118 | |
| 119 | if (args[i].compare("compress") == 0) { |
| 120 | gui_msg("compression_on=Compression is on"); |
| 121 | DataManager::SetValue(TW_USE_COMPRESSION_VAR, 1); |
| 122 | continue; |
| 123 | } |
| 124 | DataManager::GetValue(TW_USE_COMPRESSION_VAR, compress); |
| 125 | gui_print("%s\n", args[i].c_str()); |
| 126 | std::string path; |
| 127 | path = "/" + args[i]; |
| 128 | TWPartition* part = PartitionManager.Find_Partition_By_Path(path); |
| 129 | if (part) { |
| 130 | Backup_List += path; |
| 131 | Backup_List += ";"; |
| 132 | } |
| 133 | else { |
| 134 | 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] | 135 | if (!twadbbu::Write_TWERROR()) |
| 136 | LOGERR("Unable to write to TWRP ADB Backup.\n"); |
| 137 | return false; |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 138 | } |
bigbiff bigbiff | 38b83c1 | 2017-12-28 19:58:52 -0500 | [diff] [blame] | 139 | } |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 140 | |
| 141 | if (Backup_List.empty()) { |
| 142 | DataManager::GetValue("tw_backup_list", Backup_List); |
| 143 | if (Backup_List.empty()) { |
| 144 | gui_err("no_partition_selected=No partitions selected for backup."); |
| 145 | return false; |
| 146 | } |
| 147 | } |
| 148 | else |
| 149 | DataManager::SetValue("tw_backup_list", Backup_List); |
| 150 | |
| 151 | DataManager::SetValue("tw_action", "clear"); |
| 152 | DataManager::SetValue("tw_action_text1", gui_lookup("running_recovery_commands", "Running Recovery Commands")); |
| 153 | DataManager::SetValue("tw_action_text2", ""); |
| 154 | gui_changePage("action_page"); |
| 155 | |
| 156 | ret = PartitionManager.Run_Backup(adbbackup); |
| 157 | DataManager::SetValue(TW_BACKUP_NAME, gui_lookup("auto_generate", "(Auto Generate)")); |
| 158 | if (!ret) { |
| 159 | gui_err("backup_fail=Backup failed"); |
| 160 | return false; |
| 161 | } |
| 162 | gui_msg("backup_complete=Backup Complete"); |
| 163 | DataManager::SetValue("ui_progress", 100); |
| 164 | sleep(2); //give time for user to see messages on console |
| 165 | gui_changePage("main"); |
| 166 | return true; |
| 167 | } |
| 168 | |
| 169 | bool twrpAdbBuFifo::Restore_ADB_Backup(void) { |
| 170 | int partition_count = 0; |
| 171 | std::string Restore_Name; |
| 172 | std::size_t pos = 0; |
| 173 | struct AdbBackupFileTrailer adbmd5; |
| 174 | struct PartitionSettings part_settings; |
| 175 | int adb_control_twrp_fd, adb_write_fd, systemro; |
| 176 | int adb_control_bu_fd, ret = 0; |
| 177 | char cmd[512]; |
| 178 | |
| 179 | part_settings.total_restore_size = 0; |
| 180 | |
| 181 | PartitionManager.Mount_All_Storage(); |
| 182 | DataManager::SetValue(TW_SKIP_DIGEST_CHECK_VAR, 0); |
| 183 | LOGINFO("opening TW_ADB_BU_CONTROL\n"); |
| 184 | adb_control_bu_fd = open(TW_ADB_BU_CONTROL, O_WRONLY | O_NONBLOCK); |
| 185 | LOGINFO("opening TW_ADB_TWRP_CONTROL\n"); |
| 186 | adb_control_twrp_fd = open(TW_ADB_TWRP_CONTROL, O_RDONLY | O_NONBLOCK); |
| 187 | memset(&adbmd5, 0, sizeof(adbmd5)); |
| 188 | |
| 189 | DataManager::SetValue("tw_action", "clear"); |
| 190 | DataManager::SetValue("tw_action_text1", gui_lookup("running_recovery_commands", "Running Recovery Commands")); |
| 191 | DataManager::SetValue("tw_action_text2", ""); |
| 192 | gui_changePage("action_page"); |
| 193 | |
bigbiff bigbiff | 38b83c1 | 2017-12-28 19:58:52 -0500 | [diff] [blame] | 194 | while (true) { |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 195 | memset(&cmd, 0, sizeof(cmd)); |
| 196 | if (read(adb_control_twrp_fd, cmd, sizeof(cmd)) > 0) { |
| 197 | struct AdbBackupControlType cmdstruct; |
| 198 | |
| 199 | memset(&cmdstruct, 0, sizeof(cmdstruct)); |
| 200 | memcpy(&cmdstruct, cmd, sizeof(cmdstruct)); |
bigbiff bigbiff | adcb4d8 | 2017-09-25 10:51:56 -0400 | [diff] [blame] | 201 | std::string cmdtype = cmdstruct.get_type(); |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 202 | if (cmdtype == TWSTREAMHDR) { |
| 203 | struct AdbBackupStreamHeader twhdr; |
| 204 | memcpy(&twhdr, cmd, sizeof(cmd)); |
| 205 | LOGINFO("ADB Partition count: %" PRIu64 "\n", twhdr.partition_count); |
| 206 | LOGINFO("ADB version: %" PRIu64 "\n", twhdr.version); |
| 207 | if (twhdr.version != ADB_BACKUP_VERSION) { |
| 208 | LOGERR("Incompatible adb backup version!\n"); |
bigbiff bigbiff | 38b83c1 | 2017-12-28 19:58:52 -0500 | [diff] [blame] | 209 | ret = false; |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 210 | break; |
| 211 | } |
| 212 | partition_count = twhdr.partition_count; |
| 213 | } |
| 214 | else if (cmdtype == MD5TRAILER) { |
bigbiff bigbiff | 38b83c1 | 2017-12-28 19:58:52 -0500 | [diff] [blame] | 215 | LOGINFO("Reading ADB Backup MD5TRAILER\n"); |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 216 | memcpy(&adbmd5, cmd, sizeof(cmd)); |
| 217 | } |
| 218 | else if (cmdtype == TWMD5) { |
bigbiff bigbiff | 38b83c1 | 2017-12-28 19:58:52 -0500 | [diff] [blame] | 219 | int check_digest; |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 220 | |
bigbiff bigbiff | 38b83c1 | 2017-12-28 19:58:52 -0500 | [diff] [blame] | 221 | DataManager::GetValue(TW_SKIP_DIGEST_CHECK_VAR, check_digest); |
| 222 | if (check_digest > 0) { |
| 223 | TWFunc::GUI_Operation_Text(TW_VERIFY_DIGEST_TEXT, gui_parse_text("{@verifying_digest}")); |
| 224 | gui_msg("verifying_digest=Verifying Digest"); |
| 225 | struct AdbBackupFileTrailer md5check; |
| 226 | LOGINFO("Verifying md5sums\n"); |
| 227 | |
| 228 | memset(&md5check, 0, sizeof(md5check)); |
| 229 | memcpy(&md5check, cmd, sizeof(cmd)); |
| 230 | if (strcmp(md5check.md5, adbmd5.md5) != 0) { |
| 231 | LOGERR("md5 doesn't match!\n"); |
| 232 | LOGERR("Stored file md5: %s\n", adbmd5.md5); |
| 233 | LOGERR("ADB Backup check md5: %s\n", md5check.md5); |
| 234 | ret = false; |
| 235 | break; |
| 236 | } |
| 237 | else { |
| 238 | LOGINFO("ADB Backup md5 matches\n"); |
| 239 | LOGINFO("Stored file md5: %s\n", adbmd5.md5); |
| 240 | LOGINFO("ADB Backup check md5: %s\n", md5check.md5); |
| 241 | continue; |
| 242 | } |
| 243 | } else { |
| 244 | gui_msg("skip_digest=Skipping Digest check based on user setting."); |
| 245 | continue; |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 246 | } |
bigbiff bigbiff | 38b83c1 | 2017-12-28 19:58:52 -0500 | [diff] [blame] | 247 | |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 248 | } |
| 249 | else if (cmdtype == TWENDADB) { |
| 250 | LOGINFO("received TWENDADB\n"); |
bigbiff bigbiff | 38b83c1 | 2017-12-28 19:58:52 -0500 | [diff] [blame] | 251 | ret = 1; |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 252 | break; |
| 253 | } |
| 254 | else { |
| 255 | struct twfilehdr twimghdr; |
| 256 | memcpy(&twimghdr, cmd, sizeof(cmd)); |
| 257 | std::string cmdstr(twimghdr.type); |
| 258 | Restore_Name = twimghdr.name; |
| 259 | part_settings.total_restore_size = twimghdr.size; |
| 260 | if (cmdtype == TWIMG) { |
| 261 | LOGINFO("ADB Type: %s\n", twimghdr.type); |
| 262 | LOGINFO("ADB Restore_Name: %s\n", Restore_Name.c_str()); |
| 263 | LOGINFO("ADB Restore_size: %" PRIu64 "\n", part_settings.total_restore_size); |
| 264 | string compression = (twimghdr.compressed == 1) ? "compressed" : "uncompressed"; |
| 265 | LOGINFO("ADB compression: %s\n", compression.c_str()); |
| 266 | std::string Backup_FileName; |
| 267 | std::size_t pos = Restore_Name.find_last_of("/"); |
| 268 | std::string path = "/" + Restore_Name.substr(pos, Restore_Name.size()); |
| 269 | pos = path.find_first_of("."); |
| 270 | path = path.substr(0, pos); |
| 271 | if (path.substr(0,1).compare("//")) { |
| 272 | path = path.substr(1, path.size()); |
| 273 | } |
| 274 | |
| 275 | pos = Restore_Name.find_last_of("/"); |
| 276 | Backup_FileName = Restore_Name.substr(pos + 1, Restore_Name.size()); |
| 277 | part_settings.Part = PartitionManager.Find_Partition_By_Path(path); |
| 278 | part_settings.Backup_Folder = path; |
| 279 | PartitionManager.Set_Restore_Files(path); |
| 280 | part_settings.partition_count = partition_count; |
| 281 | part_settings.adbbackup = true; |
| 282 | part_settings.adb_compression = twimghdr.compressed; |
| 283 | part_settings.PM_Method = PM_RESTORE; |
| 284 | ProgressTracking progress(part_settings.total_restore_size); |
| 285 | part_settings.progress = &progress; |
| 286 | if (!PartitionManager.Restore_Partition(&part_settings)) { |
| 287 | LOGERR("ADB Restore failed.\n"); |
bigbiff bigbiff | adcb4d8 | 2017-09-25 10:51:56 -0400 | [diff] [blame] | 288 | ret = false; |
bigbiff bigbiff | 38b83c1 | 2017-12-28 19:58:52 -0500 | [diff] [blame] | 289 | break; |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 290 | } |
| 291 | } |
| 292 | else if (cmdtype == TWFN) { |
| 293 | LOGINFO("ADB Type: %s\n", twimghdr.type); |
| 294 | LOGINFO("ADB Restore_Name: %s\n", Restore_Name.c_str()); |
| 295 | LOGINFO("ADB Restore_size: %" PRIi64 "\n", part_settings.total_restore_size); |
| 296 | string compression = (twimghdr.compressed == 1) ? "compressed" : "uncompressed"; |
| 297 | LOGINFO("ADB compression: %s\n", compression.c_str()); |
| 298 | std::string Backup_FileName; |
| 299 | std::size_t pos = Restore_Name.find_last_of("/"); |
| 300 | std::string path = "/" + Restore_Name.substr(pos, Restore_Name.size()); |
| 301 | pos = path.find_first_of("."); |
| 302 | path = path.substr(0, pos); |
| 303 | if (path.substr(0,1).compare("//")) { |
| 304 | path = path.substr(1, path.size()); |
| 305 | } |
| 306 | |
| 307 | pos = Restore_Name.find_last_of("/"); |
| 308 | Backup_FileName = Restore_Name.substr(pos + 1, Restore_Name.size()); |
| 309 | pos = Restore_Name.find_last_of("/"); |
| 310 | part_settings.Part = PartitionManager.Find_Partition_By_Path(path); |
| 311 | part_settings.Part->Set_Backup_FileName(Backup_FileName); |
| 312 | PartitionManager.Set_Restore_Files(path); |
| 313 | |
| 314 | if (path.compare("/system") == 0) { |
| 315 | if (part_settings.Part->Is_Read_Only()) { |
bigbiff bigbiff | 38b83c1 | 2017-12-28 19:58:52 -0500 | [diff] [blame] | 316 | if (!twadbbu::Write_TWERROR()) |
| 317 | LOGERR("Unable to write to TWRP ADB Backup.\n"); |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 318 | 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] | 319 | ret = false; |
| 320 | break; |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 321 | |
| 322 | } |
| 323 | } |
| 324 | part_settings.partition_count = partition_count; |
| 325 | part_settings.adbbackup = true; |
| 326 | part_settings.adb_compression = twimghdr.compressed; |
| 327 | part_settings.total_restore_size += part_settings.Part->Get_Restore_Size(&part_settings); |
| 328 | part_settings.PM_Method = PM_RESTORE; |
| 329 | ProgressTracking progress(part_settings.total_restore_size); |
| 330 | part_settings.progress = &progress; |
| 331 | if (!PartitionManager.Restore_Partition(&part_settings)) { |
| 332 | LOGERR("ADB Restore failed.\n"); |
bigbiff bigbiff | adcb4d8 | 2017-09-25 10:51:56 -0400 | [diff] [blame] | 333 | ret = false; |
bigbiff bigbiff | 38b83c1 | 2017-12-28 19:58:52 -0500 | [diff] [blame] | 334 | break; |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 335 | } |
| 336 | } |
| 337 | } |
| 338 | } |
| 339 | } |
bigbiff bigbiff | adcb4d8 | 2017-09-25 10:51:56 -0400 | [diff] [blame] | 340 | |
| 341 | if (ret != false) |
| 342 | gui_msg("restore_complete=Restore Complete"); |
| 343 | else |
| 344 | gui_err("restore_error=Error during restore process."); |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 345 | |
| 346 | if (!twadbbu::Write_TWENDADB()) |
| 347 | ret = false; |
| 348 | sleep(2); //give time for user to see messages on console |
| 349 | DataManager::SetValue("ui_progress", 100); |
| 350 | gui_changePage("main"); |
bigbiff bigbiff | adcb4d8 | 2017-09-25 10:51:56 -0400 | [diff] [blame] | 351 | close(adb_control_bu_fd); |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 352 | return ret; |
| 353 | } |