blob: 8652de2acb42e10f0c1de630da8b0450e241f682 [file] [log] [blame]
bigbiffce8f83c2015-12-12 18:30:21 -05001/*
2 Copyright 2013 to 2016 TeamWin
3 TWRP is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 TWRP is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with TWRP. If not, see <http://www.gnu.org/licenses/>.
15*/
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <unistd.h>
bigbiffce8f83c2015-12-12 18:30:21 -050021#include <fcntl.h>
22#include <errno.h>
23#include <sys/types.h>
24#include <sys/stat.h>
25#include <sys/select.h>
26#include <sys/time.h>
27#include <zlib.h>
28#include <ctype.h>
29#include <semaphore.h>
30#include <string>
31#include <fstream>
32#include <sstream>
33#include <algorithm>
34
35#include "twadbstream.h"
36#include "twrpback.hpp"
bigbiff bigbiff56cf5642016-08-19 17:43:45 -040037#include "../twrpDigest/twrpDigest.hpp"
38#include "../twrpDigest/twrpMD5.hpp"
bigbiffce8f83c2015-12-12 18:30:21 -050039
40twrpback::twrpback(void) {
41 read_fd = 0;
42 write_fd = 0;
43 adb_control_twrp_fd = 0;
44 adb_control_bu_fd = 0;
45 adb_read_fd = 0;
46 adb_write_fd = 0;
47 adb_write_fd = 0;
48 ors_fd = 0;
49 firstPart = true;
50 adbloginit();
51}
52
53twrpback::~twrpback(void) {
54 adblogfile.close();
55}
56
57void twrpback::adbloginit(void) {
58 adblogfile.open("/tmp/adb.log", std::fstream::app);
59}
60
61void twrpback::adblogwrite(std::string writemsg) {
62 adblogfile << writemsg << std::flush;
63}
64
65void twrpback::close_backup_fds() {
66 if (ors_fd > 0)
67 close(ors_fd);
68 if (write_fd > 0)
69 close(write_fd);
70 if (adb_read_fd > 0)
71 close(adb_read_fd);
72 if (adb_control_bu_fd > 0)
73 close(adb_control_bu_fd);
74 if (adbd_fp != NULL)
75 fclose(adbd_fp);
76 if (access(TW_ADB_BACKUP, F_OK) == 0)
77 unlink(TW_ADB_BACKUP);
78}
79
80void twrpback::close_restore_fds() {
81 if (ors_fd > 0)
82 close(ors_fd);
83 if (write_fd > 0)
84 close(write_fd);
85 if (adb_control_bu_fd > 0)
86 close(adb_control_bu_fd);
87 if (adb_control_twrp_fd > 0)
88 close(adb_control_twrp_fd);
89 if (adbd_fp != NULL)
90 fclose(adbd_fp);
91 if (access(TW_ADB_RESTORE, F_OK) == 0)
92 unlink(TW_ADB_RESTORE);
93}
94
95int twrpback::backup(std::string command) {
bigbiff bigbiff56cf5642016-08-19 17:43:45 -040096 twrpMD5 digest;
bigbiffce8f83c2015-12-12 18:30:21 -050097 bool breakloop = false;
98 int bytes = 0, errctr = 0;
99 char result[MAX_ADB_READ];
100 uint64_t totalbytes = 0, dataChunkBytes = 0;
101 int64_t count = -1; // Count of how many blocks set
102 uint64_t md5fnsize = 0;
103 struct AdbBackupControlType endadb;
104
105 ADBSTRUCT_STATIC_ASSERT(sizeof(endadb) == MAX_ADB_READ);
106
107 bool writedata = true;
108 bool compressed = false;
109 bool firstDataPacket = true;
110
111 adbd_fp = fdopen(adbd_fd, "w");
112 if (adbd_fp == NULL) {
113 adblogwrite("Unable to open adb_fp\n");
114 return -1;
115 }
116
117 if (mkfifo(TW_ADB_BACKUP, 0666) < 0) {
118 adblogwrite("Unable to create TW_ADB_BACKUP fifo\n");
119 return -1;
120 }
121
122 adblogwrite("opening ORS_INPUT_FILE\n");
123 write_fd = open(ORS_INPUT_FILE, O_WRONLY);
124 while (write_fd < 0) {
125 write_fd = open(ORS_INPUT_FILE, O_WRONLY);
126 usleep(10000);
127 errctr++;
128 if (errctr > ADB_BU_MAX_ERROR) {
129 adblogwrite("Unable to open ORS_INPUT_FILE\n");
130 close_backup_fds();
131 return -1;
132 }
133 }
134
Ayke van Laethem05c2de42017-06-02 00:19:27 +0200135 memset(operation, 0, sizeof(operation));
136 if (snprintf(operation, sizeof(operation), "adbbackup %s", command.c_str()) >= sizeof(operation)) {
137 adblogwrite("Operation too big to write to ORS_INPUT_FILE\n");
138 close_backup_fds();
139 return -1;
140 }
bigbiffce8f83c2015-12-12 18:30:21 -0500141 if (write(write_fd, operation, sizeof(operation)) != sizeof(operation)) {
142 adblogwrite("Unable to write to ORS_INPUT_FILE\n");
143 close_backup_fds();
144 return -1;
145 }
146
147 adblogwrite("opening ORS_OUTPUT_FILE\n");
148 ors_fd = open(ORS_OUTPUT_FILE, O_RDONLY);
149 if (ors_fd < 0) {
150 adblogwrite("Unable to open ORS_OUTPUT_FILE\n");
151 close_backup_fds();
152 return -1;
153 }
154
155 memset(&result, 0, sizeof(result));
156 memset(&cmd, 0, sizeof(cmd));
157
158 adblogwrite("opening TW_ADB_BU_CONTROL\n");
159 adb_control_bu_fd = open(TW_ADB_BU_CONTROL, O_RDONLY | O_NONBLOCK);
160 if (adb_control_bu_fd < 0) {
161 adblogwrite("Unable to open TW_ADB_BU_CONTROL for reading.\n");
162 close_backup_fds();
163 return -1;
164 }
165
166 adblogwrite("opening TW_ADB_BACKUP\n");
167 adb_read_fd = open(TW_ADB_BACKUP, O_RDONLY | O_NONBLOCK);
168 if (adb_read_fd < 0) {
169 adblogwrite("Unable to open TW_ADB_BACKUP for reading.\n");
170 close_backup_fds();
171 return -1;
172 }
173
174 //loop until TWENDADB sent
175 while (!breakloop) {
176 if (read(adb_control_bu_fd, &cmd, sizeof(cmd)) > 0) {
177 struct AdbBackupControlType structcmd;
178
179 memcpy(&structcmd, cmd, sizeof(cmd));
Ayke van Laethem05c2de42017-06-02 00:19:27 +0200180 std::string cmdtype = structcmd.get_type();
bigbiffce8f83c2015-12-12 18:30:21 -0500181
182 //we received an error, exit and unlink
183 if (cmdtype == TWERROR) {
184 writedata = false;
185 adblogwrite("Error received. Quitting...\n");
186 close_backup_fds();
187 return -1;
188 }
189 //we received the end of adb backup stream so we should break the loop
190 else if (cmdtype == TWENDADB) {
191 writedata = false;
192 adblogwrite("Recieved TWENDADB\n");
193 memcpy(&endadb, cmd, sizeof(cmd));
Matt Mowercc19c6f2017-02-22 11:31:35 -0600194 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500195 str << totalbytes;
196 adblogwrite(str.str() + " total bytes written\n");
197 breakloop = true;
198 }
199 //we recieved the TWSTREAMHDR structure metadata to write to adb
200 else if (cmdtype == TWSTREAMHDR) {
201 writedata = false;
202 adblogwrite("Writing TWSTREAMHDR\n");
203 if (fwrite(cmd, 1, sizeof(cmd), adbd_fp) != sizeof(cmd)) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600204 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500205 str << strerror(errno);
206 adblogwrite("Error writing TWSTREAMHDR to adbd" + str.str() + "\n");
207 close_backup_fds();
208 return -1;
209 }
210 fflush(adbd_fp);
211 }
212 //we will be writing an image from TWRP
213 else if (cmdtype == TWIMG) {
214 struct twfilehdr twimghdr;
215
216 adblogwrite("Writing TWIMG\n");
bigbiff bigbiff56cf5642016-08-19 17:43:45 -0400217 digest.init();
bigbiffce8f83c2015-12-12 18:30:21 -0500218 memset(&twimghdr, 0, sizeof(twimghdr));
219 memcpy(&twimghdr, cmd, sizeof(cmd));
220 md5fnsize = twimghdr.size;
221
222 if (fwrite(cmd, 1, sizeof(cmd), adbd_fp) != sizeof(cmd)) {
223 adblogwrite("Error writing TWIMG to adbd\n");
224 close_backup_fds();
225 return -1;
226 }
227 fflush(adbd_fp);
228 writedata = true;
229 }
230 //we will be writing a tar from TWRP
231 else if (cmdtype == TWFN) {
232 struct twfilehdr twfilehdr;
233
234 adblogwrite("Writing TWFN\n");
bigbiff bigbiff56cf5642016-08-19 17:43:45 -0400235 digest.init();
bigbiffce8f83c2015-12-12 18:30:21 -0500236
237 ADBSTRUCT_STATIC_ASSERT(sizeof(twfilehdr) == MAX_ADB_READ);
238
239 memset(&twfilehdr, 0, sizeof(twfilehdr));
240 memcpy(&twfilehdr, cmd, sizeof(cmd));
241 md5fnsize = twfilehdr.size;
242
243 compressed = twfilehdr.compressed == 1 ? true: false;
244
245 if (fwrite(cmd, 1, sizeof(cmd), adbd_fp) != sizeof(cmd)) {
246 adblogwrite("Error writing TWFN to adbd\n");
247 close_backup_fds();
248 return -1;
249 }
250 fflush(adbd_fp);
251 writedata = true;
252 }
253 /*
254 We received the command that we are done with the file stream.
255 We will flush the remaining data stream.
256 Update md5 and write final results to adb stream.
257 If we need padding because the total bytes are not a multiple
258 of 512, we pad the end with 0s to we reach 512.
259 We also write the final md5 to the adb stream.
260 */
261 else if (cmdtype == TWEOF) {
262 adblogwrite("received TWEOF\n");
263 count = totalbytes / MAX_ADB_READ + 1;
264 count = count * MAX_ADB_READ;
265
266 while ((bytes = read(adb_read_fd, &result, sizeof(result))) == MAX_ADB_READ) {
267 totalbytes += bytes;
268 char *writeresult = new char [bytes];
269 memcpy(writeresult, result, bytes);
bigbiff bigbiff56cf5642016-08-19 17:43:45 -0400270 digest.update((unsigned char *) writeresult, bytes);
bigbiffce8f83c2015-12-12 18:30:21 -0500271 if (fwrite(writeresult, 1, bytes, adbd_fp) != bytes) {
272 adblogwrite("Error writing backup data to adbd\n");
273 close_backup_fds();
274 return -1;
275 }
276 fflush(adbd_fp);
277 delete [] writeresult;
278 memset(&result, 0, sizeof(result));
279 }
280
281 if ((totalbytes % MAX_ADB_READ) != 0) {
282 adblogwrite("writing padding to stream\n");
283 char padding[count - totalbytes];
284 memset(padding, 0, sizeof(padding));
285 if (fwrite(padding, 1, sizeof(padding), adbd_fp) != sizeof(padding)) {
286 adblogwrite("Error writing padding to adbd\n");
287 close_backup_fds();
288 return -1;
289 }
bigbiff bigbiff56cf5642016-08-19 17:43:45 -0400290 digest.update((unsigned char *) padding, sizeof(padding));
bigbiffce8f83c2015-12-12 18:30:21 -0500291 fflush(adbd_fp);
292 totalbytes = 0;
293 }
294
295 AdbBackupFileTrailer md5trailer;
296
297 memset(&md5trailer, 0, sizeof(md5trailer));
bigbiffce8f83c2015-12-12 18:30:21 -0500298
bigbiff bigbiff56cf5642016-08-19 17:43:45 -0400299 std::string md5string = digest.return_digest_string();
bigbiffce8f83c2015-12-12 18:30:21 -0500300
301 strncpy(md5trailer.start_of_trailer, TWRP, sizeof(md5trailer.start_of_trailer));
302 strncpy(md5trailer.type, MD5TRAILER, sizeof(md5trailer.type));
303 strncpy(md5trailer.md5, md5string.c_str(), sizeof(md5trailer.md5));
304
305 md5trailer.crc = crc32(0L, Z_NULL, 0);
306 md5trailer.crc = crc32(md5trailer.crc, (const unsigned char*) &md5trailer, sizeof(md5trailer));
307
308 md5trailer.ident = crc32(0L, Z_NULL, 0);
309 md5trailer.ident = crc32(md5trailer.ident, (const unsigned char*) &md5trailer, sizeof(md5trailer));
310 md5trailer.ident = crc32(md5trailer.ident, (const unsigned char*) &md5fnsize, sizeof(md5fnsize));
311
312 if (fwrite(&md5trailer, 1, sizeof(md5trailer), adbd_fp) != sizeof(md5trailer)) {
313 adblogwrite("Error writing md5trailer to adbd\n");
314 close_backup_fds();
315 return -1;
316 }
317 fflush(adbd_fp);
318 writedata = false;
319 firstDataPacket = true;
320 }
321 memset(&cmd, 0, sizeof(cmd));
322 }
323 //If we are to write data because of a new file stream, lets write all the data.
324 //This will allow us to not write data after a command structure has been written
325 //to the adb stream.
326 //If the stream is compressed, we need to always write the data.
327 if (writedata || compressed) {
bigbiff bigbiff4a2a1912017-06-03 10:55:46 -0400328 while ((bytes = read(adb_read_fd, &result, sizeof(result))) > 0) {
bigbiffce8f83c2015-12-12 18:30:21 -0500329 if (firstDataPacket) {
330 struct AdbBackupControlType data_block;
331
332 memset(&data_block, 0, sizeof(data_block));
333 strncpy(data_block.start_of_header, TWRP, sizeof(data_block.start_of_header));
334 strncpy(data_block.type, TWDATA, sizeof(data_block.type));
335 data_block.crc = crc32(0L, Z_NULL, 0);
336 data_block.crc = crc32(data_block.crc, (const unsigned char*) &data_block, sizeof(data_block));
337 if (fwrite(&data_block, 1, sizeof(data_block), adbd_fp) != sizeof(data_block)) {
338 adblogwrite("Error writing data_block to adbd\n");
339 close_backup_fds();
340 return -1;
341 }
342 fflush(adbd_fp);
343 firstDataPacket = false;
344 }
345 char *writeresult = new char [bytes];
346 memcpy(writeresult, result, bytes);
347
bigbiff bigbiff56cf5642016-08-19 17:43:45 -0400348 digest.update((unsigned char *) writeresult, bytes);
bigbiffce8f83c2015-12-12 18:30:21 -0500349
350 totalbytes += bytes;
351 dataChunkBytes += bytes;
352
353 if (fwrite(writeresult, 1, bytes, adbd_fp) != bytes) {
354 adblogwrite("Error writing backup data to adbd\n");
355 close_backup_fds();
356 return -1;
357 }
358 fflush(adbd_fp);
359
360 delete [] writeresult;
361 memset(&result, 0, sizeof(result));
362 if (dataChunkBytes == DATA_MAX_CHUNK_SIZE - sizeof(result)) {
363 struct AdbBackupControlType data_block;
364
365 memset(&data_block, 0, sizeof(data_block));
366 strncpy(data_block.start_of_header, TWRP, sizeof(data_block.start_of_header));
367 strncpy(data_block.type, TWDATA, sizeof(data_block.type));
368 data_block.crc = crc32(0L, Z_NULL, 0);
369 data_block.crc = crc32(data_block.crc, (const unsigned char*) &data_block, sizeof(data_block));
370 if (fwrite(&data_block, 1, sizeof(data_block), adbd_fp) != sizeof(data_block)) {
371 adblogwrite("Error writing data_block to adbd\n");
372 close_backup_fds();
373 return -1;
374 }
375 fflush(adbd_fp);
376 dataChunkBytes = 0;
377 }
378
379 }
380 compressed = false;
381 }
382 }
383
384 //Write the final end adb structure to the adb stream
385 if (fwrite(&endadb, 1, sizeof(endadb), adbd_fp) != sizeof(endadb)) {
386 adblogwrite("Error writing endadb to adbd\n");
387 close_backup_fds();
388 return -1;
389 }
390 fflush(adbd_fp);
391 close_backup_fds();
392 return 0;
393}
394
395int twrpback::restore(void) {
bigbiff bigbiff56cf5642016-08-19 17:43:45 -0400396 twrpMD5 digest;
397 char cmd[MAX_ADB_READ];
bigbiffce8f83c2015-12-12 18:30:21 -0500398 char result[MAX_ADB_READ];
399 struct AdbBackupControlType structcmd;
400 int adb_control_twrp_fd, errctr = 0;
401 uint64_t totalbytes = 0, dataChunkBytes = 0;
402 uint64_t md5fnsize = 0;
403 bool writedata, read_from_adb;
404 bool breakloop, eofsent, md5trsent;
405
406 breakloop = false;
407 read_from_adb = true;
408
409 signal(SIGPIPE, SIG_IGN);
410
411 adbd_fp = fdopen(adbd_fd, "r");
412 if (adbd_fp == NULL) {
413 adblogwrite("Unable to open adb_fp\n");
414 close_restore_fds();
415 return -1;
416 }
417
418 if(mkfifo(TW_ADB_RESTORE, 0666)) {
419 adblogwrite("Unable to create TW_ADB_RESTORE fifo\n");
420 close_restore_fds();
421 return -1;
422 }
423
424 adblogwrite("opening ORS_INPUT_FILE\n");
425 write_fd = open(ORS_INPUT_FILE, O_WRONLY);
426
427 while (write_fd < 0) {
428 write_fd = open(ORS_INPUT_FILE, O_WRONLY);
429 errctr++;
430 if (errctr > ADB_BU_MAX_ERROR) {
431 adblogwrite("Unable to open ORS_INPUT_FILE\n");
432 close_restore_fds();
433 return -1;
434 }
435 }
436
Ayke van Laethem05c2de42017-06-02 00:19:27 +0200437 memset(operation, 0, sizeof(operation));
bigbiffce8f83c2015-12-12 18:30:21 -0500438 sprintf(operation, "adbrestore");
439 if (write(write_fd, operation, sizeof(operation)) != sizeof(operation)) {
440 adblogwrite("Unable to write to ORS_INPUT_FILE\n");
441 close_restore_fds();
442 return -1;
443 }
444
445 ors_fd = open(ORS_OUTPUT_FILE, O_RDONLY);
446 if (ors_fd < 0) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600447 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500448 str << strerror(errno);
449 adblogwrite("Unable to write to ORS_OUTPUT_FILE: " + str.str() + "\n");
450 close_restore_fds();
451 return -1;
452 }
453
454 memset(&result, 0, sizeof(result));
455 memset(&cmd, 0, sizeof(cmd));
456
457 adblogwrite("opening TW_ADB_BU_CONTROL\n");
458 adb_control_bu_fd = open(TW_ADB_BU_CONTROL, O_RDONLY | O_NONBLOCK);
459 if (adb_control_bu_fd < 0) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600460 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500461 str << strerror(errno);
462 adblogwrite("Unable to open TW_ADB_BU_CONTROL for writing. " + str.str() + "\n");
463 close_restore_fds();
464 return -1;
465 }
466
467 adblogwrite("opening TW_ADB_TWRP_CONTROL\n");
468 adb_control_twrp_fd = open(TW_ADB_TWRP_CONTROL, O_WRONLY | O_NONBLOCK);
469 if (adb_control_twrp_fd < 0) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600470 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500471 str << strerror(errno);
472 adblogwrite("Unable to open TW_ADB_TWRP_CONTROL for writing. " + str.str() + ". Retrying...\n");
473 while (adb_control_twrp_fd < 0) {
474 adb_control_twrp_fd = open(TW_ADB_TWRP_CONTROL, O_WRONLY | O_NONBLOCK);
475 usleep(10000);
476 errctr++;
477 if (errctr > ADB_BU_MAX_ERROR) {
478 adblogwrite("Unable to open TW_ADB_TWRP_CONTROL\n");
479 close_backup_fds();
480 return -1;
481 }
482 }
483 }
484
485 //Loop until we receive TWENDADB from TWRP
486 while (!breakloop) {
487 memset(&cmd, 0, sizeof(cmd));
488 if (read(adb_control_bu_fd, &cmd, sizeof(cmd)) > 0) {
489 struct AdbBackupControlType structcmd;
490 memcpy(&structcmd, cmd, sizeof(cmd));
Ayke van Laethem05c2de42017-06-02 00:19:27 +0200491 std::string cmdtype = structcmd.get_type();
bigbiffce8f83c2015-12-12 18:30:21 -0500492
493 //If we receive TWEOF from TWRP close adb data fifo
494 if (cmdtype == TWEOF) {
495 adblogwrite("Received TWEOF\n");
496 struct AdbBackupControlType tweof;
497
498 memset(&tweof, 0, sizeof(tweof));
499 memcpy(&tweof, result, sizeof(result));
500 read_from_adb = true;
501 }
502 //Break when TWRP sends TWENDADB
503 else if (cmdtype == TWENDADB) {
504 adblogwrite("Received TWENDADB\n");
505 breakloop = true;
506 close_restore_fds();
507 }
508 //we received an error, exit and unlink
509 else if (cmdtype == TWERROR) {
510 adblogwrite("Error received. Quitting...\n");
511 close_restore_fds();
512 return -1;
513 }
514 }
bigbiffce8f83c2015-12-12 18:30:21 -0500515 //If we should read from the adb stream, write commands and data to TWRP
516 if (read_from_adb) {
bigbiffce8f83c2015-12-12 18:30:21 -0500517 int readbytes;
518 if ((readbytes = fread(result, 1, sizeof(result), adbd_fp)) == sizeof(result)) {
519 totalbytes += readbytes;
520 memcpy(&structcmd, result, sizeof(result));
Ayke van Laethem05c2de42017-06-02 00:19:27 +0200521 std::string cmdtype = structcmd.get_type();
bigbiffce8f83c2015-12-12 18:30:21 -0500522
523 //Tell TWRP we have read the entire adb stream
524 if (cmdtype == TWENDADB) {
525 struct AdbBackupControlType endadb;
526 uint32_t crc, endadbcrc;
527
528 totalbytes -= sizeof(result);
529 memset(&endadb, 0, sizeof(endadb));
530 memcpy(&endadb, result, sizeof(result));
531 endadbcrc = endadb.crc;
532 memset(&endadb.crc, 0, sizeof(endadb.crc));
533 crc = crc32(0L, Z_NULL, 0);
534 crc = crc32(crc, (const unsigned char*) &endadb, sizeof(endadb));
535
536 if (crc == endadbcrc) {
537 adblogwrite("Sending TWENDADB\n");
538 if (write(adb_control_twrp_fd, &endadb, sizeof(endadb)) < 1) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600539 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500540 str << strerror(errno);
541 adblogwrite("Cannot write to ADB_CONTROL_READ_FD: " + str.str() + "\n");
542 close_restore_fds();
543 return -1;
544 }
bigbiff bigbiffb5ecaad2017-03-20 18:53:53 -0400545 read_from_adb = false;
bigbiffce8f83c2015-12-12 18:30:21 -0500546 }
547 else {
548 adblogwrite("ADB TWENDADB crc header doesn't match\n");
549 close_restore_fds();
550 return -1;
551 }
552 }
553 //Send TWRP partition metadata
554 else if (cmdtype == TWSTREAMHDR) {
555 struct AdbBackupStreamHeader cnthdr;
556 uint32_t crc, cnthdrcrc;
557
558 ADBSTRUCT_STATIC_ASSERT(sizeof(cnthdr) == MAX_ADB_READ);
559 totalbytes -= sizeof(result);
560
561 memset(&cnthdr, 0, sizeof(cnthdr));
562 memcpy(&cnthdr, result, sizeof(result));
563 cnthdrcrc = cnthdr.crc;
564 memset(&cnthdr.crc, 0, sizeof(cnthdr.crc));
565 crc = crc32(0L, Z_NULL, 0);
566 crc = crc32(crc, (const unsigned char*) &cnthdr, sizeof(cnthdr));
567
568 if (crc == cnthdrcrc) {
569 adblogwrite("Restoring TWSTREAMHDR\n");
570 if (write(adb_control_twrp_fd, result, sizeof(result)) < 0) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600571 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500572 str << strerror(errno);
573 adblogwrite("Cannot write to adb_control_twrp_fd: " + str.str() + "\n");
574 close_restore_fds();
575 return -1;
576 }
577 }
578 else {
579 adblogwrite("ADB TWSTREAMHDR crc header doesn't match\n");
580 close_restore_fds();
581 return -1;
582 }
583 }
584 //Tell TWRP we are sending a partition image
585 else if (cmdtype == TWIMG) {
586 struct twfilehdr twimghdr;
587 uint32_t crc, twimghdrcrc;
588
bigbiff bigbiff56cf5642016-08-19 17:43:45 -0400589 digest.init();
bigbiffce8f83c2015-12-12 18:30:21 -0500590 totalbytes -= sizeof(result);
bigbiffce8f83c2015-12-12 18:30:21 -0500591 adblogwrite("Restoring TWIMG\n");
592 memset(&twimghdr, 0, sizeof(twimghdr));
593 memcpy(&twimghdr, result, sizeof(result));
594 md5fnsize = twimghdr.size;
595 twimghdrcrc = twimghdr.crc;
596 memset(&twimghdr.crc, 0, sizeof(twimghdr.crc));
597
598 crc = crc32(0L, Z_NULL, 0);
599 crc = crc32(crc, (const unsigned char*) &twimghdr, sizeof(twimghdr));
600 if (crc == twimghdrcrc) {
601 if (write(adb_control_twrp_fd, result, sizeof(result)) < 1) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600602 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500603 str << strerror(errno);
604 adblogwrite("Cannot write to adb_control_twrp_fd: " + str.str() + "\n");
605 close_restore_fds();
606 return -1;
607 }
608 }
609 else {
610 adblogwrite("ADB TWIMG crc header doesn't match\n");
611 close_restore_fds();
612 return -1;
613 }
614 adblogwrite("opening TW_ADB_RESTORE\n");
615 adb_write_fd = open(TW_ADB_RESTORE, O_WRONLY);
616 }
617 //Tell TWRP we are sending a tar stream
618 else if (cmdtype == TWFN) {
619 struct twfilehdr twfilehdr;
620 uint32_t crc, twfilehdrcrc;
bigbiff bigbiff56cf5642016-08-19 17:43:45 -0400621 digest.init();
bigbiffce8f83c2015-12-12 18:30:21 -0500622
623 totalbytes -= sizeof(result);
bigbiffce8f83c2015-12-12 18:30:21 -0500624 adblogwrite("Restoring TWFN\n");
625 memset(&twfilehdr, 0, sizeof(twfilehdr));
626 memcpy(&twfilehdr, result, sizeof(result));
627 md5fnsize = twfilehdr.size;
628 twfilehdrcrc = twfilehdr.crc;
629 memset(&twfilehdr.crc, 0, sizeof(twfilehdr.crc));
630
631 crc = crc32(0L, Z_NULL, 0);
632 crc = crc32(crc, (const unsigned char*) &twfilehdr, sizeof(twfilehdr));
633
634 if (crc == twfilehdrcrc) {
635 if (write(adb_control_twrp_fd, result, sizeof(result)) < 1) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600636 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500637 str << strerror(errno);
638 adblogwrite("Cannot write to adb_control_twrp_fd: " + str.str() + "\n");
639 close_restore_fds();
640 return -1;
641 }
642 }
643 else {
644 adblogwrite("ADB TWFN crc header doesn't match\n");
645 close_restore_fds();
646 return -1;
647 }
648
649 adblogwrite("opening TW_ADB_RESTORE\n");
650 adb_write_fd = open(TW_ADB_RESTORE, O_WRONLY);
651 }
652 //Send the tar or partition image md5 to TWRP
653 else if (cmdtype == TWDATA) {
654 totalbytes -= sizeof(result);
655 while (1) {
656 if ((readbytes = fread(result, 1, sizeof(result), adbd_fp)) != sizeof(result)) {
657 close_restore_fds();
658 return -1;
659 }
660 totalbytes += readbytes;
661 memcpy(&structcmd, result, sizeof(result));
Ayke van Laethem05c2de42017-06-02 00:19:27 +0200662 std::string cmdtype = structcmd.get_type();
bigbiffce8f83c2015-12-12 18:30:21 -0500663
Ayke van Laethem05c2de42017-06-02 00:19:27 +0200664 if (cmdtype.substr(0, sizeof(MD5TRAILER) - 1) == MD5TRAILER) {
bigbiffce8f83c2015-12-12 18:30:21 -0500665 struct AdbBackupFileTrailer md5tr;
666 uint32_t crc, md5trcrc, md5ident, md5identmatch;
667
668 ADBSTRUCT_STATIC_ASSERT(sizeof(md5tr) == MAX_ADB_READ);
669 memset(&md5tr, 0, sizeof(md5tr));
670 memcpy(&md5tr, result, sizeof(result));
671 md5ident = md5tr.ident;
672
673 memset(&md5tr.ident, 0, sizeof(md5tr.ident));
674
675 md5identmatch = crc32(0L, Z_NULL, 0);
676 md5identmatch = crc32(md5identmatch, (const unsigned char*) &md5tr, sizeof(md5tr));
677 md5identmatch = crc32(md5identmatch, (const unsigned char*) &md5fnsize, sizeof(md5fnsize));
678
679 if (md5identmatch == md5ident) {
680 totalbytes -= sizeof(result);
681 close(adb_write_fd);
682 adblogwrite("Restoring MD5TRAILER\n");
683 md5trcrc = md5tr.crc;
684 memset(&md5tr.crc, 0, sizeof(md5tr.crc));
685 crc = crc32(0L, Z_NULL, 0);
686 crc = crc32(crc, (const unsigned char*) &md5tr, sizeof(md5tr));
687 if (crc == md5trcrc) {
688 if (write(adb_control_twrp_fd, result, sizeof(result)) < 1) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600689 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500690 str << strerror(errno);
691 adblogwrite("Cannot write to adb_control_twrp_fd: " + str.str() + "\n");
692 close_restore_fds();
693 return -1;
694 }
695 }
696 else {
697 adblogwrite("ADB MD5TRAILER crc header doesn't match\n");
698 close_restore_fds();
699 return -1;
700 }
bigbiffce8f83c2015-12-12 18:30:21 -0500701
702 AdbBackupFileTrailer md5;
703
704 memset(&md5, 0, sizeof(md5));
705 strncpy(md5.start_of_trailer, TWRP, sizeof(md5.start_of_trailer));
706 strncpy(md5.type, TWMD5, sizeof(md5.type));
bigbiff bigbiff56cf5642016-08-19 17:43:45 -0400707 std::string md5string = digest.return_digest_string();
bigbiffce8f83c2015-12-12 18:30:21 -0500708 strncpy(md5.md5, md5string.c_str(), sizeof(md5.md5));
709
710 adblogwrite("Sending MD5Check\n");
711 if (write(adb_control_twrp_fd, &md5, sizeof(md5)) < 1) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600712 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500713 str << strerror(errno);
714 adblogwrite("Cannot write to adb_control_twrp_fd: " + str.str() + "\n");
715 close_restore_fds();
716 return -1;
717 }
718 read_from_adb = false; //don't read from adb until TWRP sends TWEOF
719 break;
720 }
721 }
bigbiff bigbiff56cf5642016-08-19 17:43:45 -0400722 digest.update((unsigned char*)result, sizeof(result));
bigbiffce8f83c2015-12-12 18:30:21 -0500723 dataChunkBytes += readbytes;
724
725 if (write(adb_write_fd, result, sizeof(result)) < 0) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600726 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500727 str << strerror(errno);
728 adblogwrite("Cannot write to adb_write_fd\n" + str.str() + ". Retrying.\n");
729 while(write(adb_write_fd, result, sizeof(result)) < 0) {
730 adblogwrite("Cannot write to adb_write_fd\n" + str.str() + ". Retrying.\n");
731 continue;
732 }
733 }
734 if (dataChunkBytes == ((DATA_MAX_CHUNK_SIZE) - sizeof(result))) {
735 dataChunkBytes = 0;
736 break;
737 }
738 memset(&result, 0, sizeof(result));
739 }
740 }
741 }
742 }
743 }
744
Matt Mowercc19c6f2017-02-22 11:31:35 -0600745 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500746 str << totalbytes;
747 adblogwrite(str.str() + " bytes restored from adbbackup\n");
748 return 0;
749}
750
751int main(int argc, char **argv) {
752 int index;
753 int ret = 0, pos = 0;
754 std::string command;
755 twrpback tw;
756
757 tw.adblogwrite("Starting adb backup and restore\n");
758 if (mkfifo(TW_ADB_BU_CONTROL, 0666) < 0) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600759 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500760 str << strerror(errno);
761 tw.adblogwrite("Unable to create TW_ADB_BU_CONTROL fifo: " + str.str() + "\n");
762 unlink(TW_ADB_BU_CONTROL);
763 return -1;
764 }
765 if (mkfifo(TW_ADB_TWRP_CONTROL, 0666) < 0) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600766 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500767 str << strerror(errno);
768 tw.adblogwrite("Unable to create TW_ADB_TWRP_CONTROL fifo: " + str.str() + "\n");
769 unlink(TW_ADB_TWRP_CONTROL);
770 unlink(TW_ADB_BU_CONTROL);
771 return -1;
772 }
773
Ayke van Laethem05c2de42017-06-02 00:19:27 +0200774 if (argc <= 1) {
775 tw.adblogwrite("No parameters given, exiting...\n");
776 tw.close_restore_fds();
777 return -1;
778 }
779
bigbiffce8f83c2015-12-12 18:30:21 -0500780 command = argv[1];
781 for (index = 2; index < argc; index++) {
782 command = command + " " + argv[index];
783 }
784
785 pos = command.find("backup");
786 if (pos < 0) {
787 pos = command.find("restore");
788 }
789 command.erase(0, pos);
790 command.erase(std::remove(command.begin(), command.end(), '\''), command.end());
791 tw.adblogwrite("command: " + command + "\n");
792
793 if (command.substr(0, sizeof("backup") - 1) == "backup") {
794 tw.adblogwrite("Starting adb backup\n");
795 if (isdigit(*argv[1]))
796 tw.adbd_fd = atoi(argv[1]);
797 else
798 tw.adbd_fd = 1;
799 ret = tw.backup(command);
800 }
801 else if (command.substr(0, sizeof("restore") - 1) == "restore") {
802 tw.adblogwrite("Starting adb restore\n");
803 if (isdigit(*argv[1]))
804 tw.adbd_fd = atoi(argv[1]);
805 else
806 tw.adbd_fd = 0;
807 ret = tw.restore();
808 }
809 if (ret == 0)
810 tw.adblogwrite("Adb backup/restore completed\n");
811 else
812 tw.adblogwrite("Adb backup/restore failed\n");
813
814 if (unlink(TW_ADB_BU_CONTROL) < 0) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600815 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500816 str << strerror(errno);
817 tw.adblogwrite("Unable to remove TW_ADB_BU_CONTROL: " + str.str());
818 }
819 unlink(TW_ADB_TWRP_CONTROL);
820 return ret;
821}