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"); |
| 106 | sleep(2); |
| 107 | return false; |
| 108 | } |
| 109 | |
| 110 | for (unsigned i = 2; i < args.size(); i++) { |
| 111 | int compress; |
| 112 | |
| 113 | std::string::size_type size = args[i].find(rmopt); |
| 114 | if (size != std::string::npos) |
| 115 | args[i].erase(size, rmopt.length()); |
| 116 | |
| 117 | if (args[i].compare("compress") == 0) { |
| 118 | gui_msg("compression_on=Compression is on"); |
| 119 | DataManager::SetValue(TW_USE_COMPRESSION_VAR, 1); |
| 120 | continue; |
| 121 | } |
| 122 | DataManager::GetValue(TW_USE_COMPRESSION_VAR, compress); |
| 123 | gui_print("%s\n", args[i].c_str()); |
| 124 | std::string path; |
| 125 | path = "/" + args[i]; |
| 126 | TWPartition* part = PartitionManager.Find_Partition_By_Path(path); |
| 127 | if (part) { |
| 128 | Backup_List += path; |
| 129 | Backup_List += ";"; |
| 130 | } |
| 131 | else { |
| 132 | gui_msg(Msg(msg::kError, "partition_not_found=path: {1} not found in partition list")(path)); |
| 133 | return false; |
| 134 | } |
| 135 | } |
| 136 | |
| 137 | if (Backup_List.empty()) { |
| 138 | DataManager::GetValue("tw_backup_list", Backup_List); |
| 139 | if (Backup_List.empty()) { |
| 140 | gui_err("no_partition_selected=No partitions selected for backup."); |
| 141 | return false; |
| 142 | } |
| 143 | } |
| 144 | else |
| 145 | DataManager::SetValue("tw_backup_list", Backup_List); |
| 146 | |
| 147 | DataManager::SetValue("tw_action", "clear"); |
| 148 | DataManager::SetValue("tw_action_text1", gui_lookup("running_recovery_commands", "Running Recovery Commands")); |
| 149 | DataManager::SetValue("tw_action_text2", ""); |
| 150 | gui_changePage("action_page"); |
| 151 | |
| 152 | ret = PartitionManager.Run_Backup(adbbackup); |
| 153 | DataManager::SetValue(TW_BACKUP_NAME, gui_lookup("auto_generate", "(Auto Generate)")); |
| 154 | if (!ret) { |
| 155 | gui_err("backup_fail=Backup failed"); |
| 156 | return false; |
| 157 | } |
| 158 | gui_msg("backup_complete=Backup Complete"); |
| 159 | DataManager::SetValue("ui_progress", 100); |
| 160 | sleep(2); //give time for user to see messages on console |
| 161 | gui_changePage("main"); |
| 162 | return true; |
| 163 | } |
| 164 | |
| 165 | bool twrpAdbBuFifo::Restore_ADB_Backup(void) { |
| 166 | int partition_count = 0; |
| 167 | std::string Restore_Name; |
| 168 | std::size_t pos = 0; |
| 169 | struct AdbBackupFileTrailer adbmd5; |
| 170 | struct PartitionSettings part_settings; |
| 171 | int adb_control_twrp_fd, adb_write_fd, systemro; |
| 172 | int adb_control_bu_fd, ret = 0; |
| 173 | char cmd[512]; |
| 174 | |
| 175 | part_settings.total_restore_size = 0; |
| 176 | |
| 177 | PartitionManager.Mount_All_Storage(); |
| 178 | DataManager::SetValue(TW_SKIP_DIGEST_CHECK_VAR, 0); |
| 179 | LOGINFO("opening TW_ADB_BU_CONTROL\n"); |
| 180 | adb_control_bu_fd = open(TW_ADB_BU_CONTROL, O_WRONLY | O_NONBLOCK); |
| 181 | LOGINFO("opening TW_ADB_TWRP_CONTROL\n"); |
| 182 | adb_control_twrp_fd = open(TW_ADB_TWRP_CONTROL, O_RDONLY | O_NONBLOCK); |
| 183 | memset(&adbmd5, 0, sizeof(adbmd5)); |
| 184 | |
| 185 | DataManager::SetValue("tw_action", "clear"); |
| 186 | DataManager::SetValue("tw_action_text1", gui_lookup("running_recovery_commands", "Running Recovery Commands")); |
| 187 | DataManager::SetValue("tw_action_text2", ""); |
| 188 | gui_changePage("action_page"); |
| 189 | |
| 190 | while (1) { |
| 191 | memset(&cmd, 0, sizeof(cmd)); |
| 192 | if (read(adb_control_twrp_fd, cmd, sizeof(cmd)) > 0) { |
| 193 | struct AdbBackupControlType cmdstruct; |
| 194 | |
| 195 | memset(&cmdstruct, 0, sizeof(cmdstruct)); |
| 196 | memcpy(&cmdstruct, cmd, sizeof(cmdstruct)); |
bigbiff bigbiff | adcb4d8 | 2017-09-25 10:51:56 -0400 | [diff] [blame] | 197 | std::string cmdtype = cmdstruct.get_type(); |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 198 | if (cmdtype == TWSTREAMHDR) { |
| 199 | struct AdbBackupStreamHeader twhdr; |
| 200 | memcpy(&twhdr, cmd, sizeof(cmd)); |
| 201 | LOGINFO("ADB Partition count: %" PRIu64 "\n", twhdr.partition_count); |
| 202 | LOGINFO("ADB version: %" PRIu64 "\n", twhdr.version); |
| 203 | if (twhdr.version != ADB_BACKUP_VERSION) { |
| 204 | LOGERR("Incompatible adb backup version!\n"); |
| 205 | break; |
| 206 | } |
| 207 | partition_count = twhdr.partition_count; |
| 208 | } |
| 209 | else if (cmdtype == MD5TRAILER) { |
| 210 | LOGINFO("Restoring MD5TRAILER\n"); |
| 211 | memcpy(&adbmd5, cmd, sizeof(cmd)); |
| 212 | } |
| 213 | else if (cmdtype == TWMD5) { |
| 214 | struct AdbBackupFileTrailer md5check; |
| 215 | LOGINFO("Restoring TWMD5\n"); |
| 216 | |
| 217 | memset(&md5check, 0, sizeof(md5check)); |
| 218 | memcpy(&md5check, cmd, sizeof(cmd)); |
| 219 | if (strcmp(md5check.md5, adbmd5.md5) != 0) { |
| 220 | LOGERR("md5 doesn't match!\n"); |
| 221 | LOGERR("file md5: %s\n", adbmd5.md5); |
| 222 | LOGERR("check md5: %s\n", md5check.md5); |
| 223 | ret = false; |
| 224 | break; |
| 225 | } |
| 226 | else { |
| 227 | LOGINFO("adbrestore md5 matches\n"); |
| 228 | LOGINFO("adbmd5.md5: %s\n", adbmd5.md5); |
| 229 | LOGINFO("md5check.md5: %s\n", md5check.md5); |
bigbiff bigbiff | adcb4d8 | 2017-09-25 10:51:56 -0400 | [diff] [blame] | 230 | ret = true; |
| 231 | break; |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 232 | } |
| 233 | } |
| 234 | else if (cmdtype == TWENDADB) { |
| 235 | LOGINFO("received TWENDADB\n"); |
| 236 | break; |
| 237 | } |
| 238 | else { |
| 239 | struct twfilehdr twimghdr; |
| 240 | memcpy(&twimghdr, cmd, sizeof(cmd)); |
| 241 | std::string cmdstr(twimghdr.type); |
| 242 | Restore_Name = twimghdr.name; |
| 243 | part_settings.total_restore_size = twimghdr.size; |
| 244 | if (cmdtype == TWIMG) { |
| 245 | LOGINFO("ADB Type: %s\n", twimghdr.type); |
| 246 | LOGINFO("ADB Restore_Name: %s\n", Restore_Name.c_str()); |
| 247 | LOGINFO("ADB Restore_size: %" PRIu64 "\n", part_settings.total_restore_size); |
| 248 | string compression = (twimghdr.compressed == 1) ? "compressed" : "uncompressed"; |
| 249 | LOGINFO("ADB compression: %s\n", compression.c_str()); |
| 250 | std::string Backup_FileName; |
| 251 | std::size_t pos = Restore_Name.find_last_of("/"); |
| 252 | std::string path = "/" + Restore_Name.substr(pos, Restore_Name.size()); |
| 253 | pos = path.find_first_of("."); |
| 254 | path = path.substr(0, pos); |
| 255 | if (path.substr(0,1).compare("//")) { |
| 256 | path = path.substr(1, path.size()); |
| 257 | } |
| 258 | |
| 259 | pos = Restore_Name.find_last_of("/"); |
| 260 | Backup_FileName = Restore_Name.substr(pos + 1, Restore_Name.size()); |
| 261 | part_settings.Part = PartitionManager.Find_Partition_By_Path(path); |
| 262 | part_settings.Backup_Folder = path; |
| 263 | PartitionManager.Set_Restore_Files(path); |
| 264 | part_settings.partition_count = partition_count; |
| 265 | part_settings.adbbackup = true; |
| 266 | part_settings.adb_compression = twimghdr.compressed; |
| 267 | part_settings.PM_Method = PM_RESTORE; |
| 268 | ProgressTracking progress(part_settings.total_restore_size); |
| 269 | part_settings.progress = &progress; |
| 270 | if (!PartitionManager.Restore_Partition(&part_settings)) { |
| 271 | LOGERR("ADB Restore failed.\n"); |
bigbiff bigbiff | adcb4d8 | 2017-09-25 10:51:56 -0400 | [diff] [blame] | 272 | ret = false; |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 273 | } |
| 274 | } |
| 275 | else if (cmdtype == TWFN) { |
| 276 | LOGINFO("ADB Type: %s\n", twimghdr.type); |
| 277 | LOGINFO("ADB Restore_Name: %s\n", Restore_Name.c_str()); |
| 278 | LOGINFO("ADB Restore_size: %" PRIi64 "\n", part_settings.total_restore_size); |
| 279 | string compression = (twimghdr.compressed == 1) ? "compressed" : "uncompressed"; |
| 280 | LOGINFO("ADB compression: %s\n", compression.c_str()); |
| 281 | std::string Backup_FileName; |
| 282 | std::size_t pos = Restore_Name.find_last_of("/"); |
| 283 | std::string path = "/" + Restore_Name.substr(pos, Restore_Name.size()); |
| 284 | pos = path.find_first_of("."); |
| 285 | path = path.substr(0, pos); |
| 286 | if (path.substr(0,1).compare("//")) { |
| 287 | path = path.substr(1, path.size()); |
| 288 | } |
| 289 | |
| 290 | pos = Restore_Name.find_last_of("/"); |
| 291 | Backup_FileName = Restore_Name.substr(pos + 1, Restore_Name.size()); |
| 292 | pos = Restore_Name.find_last_of("/"); |
| 293 | part_settings.Part = PartitionManager.Find_Partition_By_Path(path); |
| 294 | part_settings.Part->Set_Backup_FileName(Backup_FileName); |
| 295 | PartitionManager.Set_Restore_Files(path); |
| 296 | |
| 297 | if (path.compare("/system") == 0) { |
| 298 | if (part_settings.Part->Is_Read_Only()) { |
| 299 | struct AdbBackupControlType twerror; |
| 300 | strncpy(twerror.start_of_header, TWRP, sizeof(twerror.start_of_header)); |
| 301 | strncpy(twerror.type, TWERROR, sizeof(twerror.type)); |
| 302 | memset(twerror.space, 0, sizeof(twerror.space)); |
| 303 | twerror.crc = crc32(0L, Z_NULL, 0); |
| 304 | twerror.crc = crc32(twerror.crc, (const unsigned char*) &twerror, sizeof(twerror)); |
| 305 | if (write(adb_control_bu_fd, &twerror, sizeof(twerror)) < 0) { |
| 306 | LOGERR("Cannot write to ADB_CONTROL_BU_FD: %s\n", strerror(errno)); |
| 307 | } |
| 308 | gui_msg(Msg(msg::kError, "restore_read_only=Cannot restore {1} -- mounted read only.")(part_settings.Part->Backup_Display_Name)); |
| 309 | return false; |
| 310 | |
| 311 | } |
| 312 | } |
| 313 | part_settings.partition_count = partition_count; |
| 314 | part_settings.adbbackup = true; |
| 315 | part_settings.adb_compression = twimghdr.compressed; |
| 316 | part_settings.total_restore_size += part_settings.Part->Get_Restore_Size(&part_settings); |
| 317 | part_settings.PM_Method = PM_RESTORE; |
| 318 | ProgressTracking progress(part_settings.total_restore_size); |
| 319 | part_settings.progress = &progress; |
| 320 | if (!PartitionManager.Restore_Partition(&part_settings)) { |
| 321 | LOGERR("ADB Restore failed.\n"); |
bigbiff bigbiff | adcb4d8 | 2017-09-25 10:51:56 -0400 | [diff] [blame] | 322 | ret = false; |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 323 | } |
| 324 | } |
| 325 | } |
| 326 | } |
| 327 | } |
bigbiff bigbiff | adcb4d8 | 2017-09-25 10:51:56 -0400 | [diff] [blame] | 328 | |
| 329 | if (ret != false) |
| 330 | gui_msg("restore_complete=Restore Complete"); |
| 331 | else |
| 332 | gui_err("restore_error=Error during restore process."); |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 333 | |
| 334 | if (!twadbbu::Write_TWENDADB()) |
| 335 | ret = false; |
| 336 | sleep(2); //give time for user to see messages on console |
| 337 | DataManager::SetValue("ui_progress", 100); |
| 338 | gui_changePage("main"); |
bigbiff bigbiff | adcb4d8 | 2017-09-25 10:51:56 -0400 | [diff] [blame] | 339 | close(adb_control_bu_fd); |
| 340 | close(adb_control_twrp_fd); |
bigbiff bigbiff | 19fb79c | 2016-09-05 21:04:51 -0400 | [diff] [blame] | 341 | return ret; |
| 342 | } |