blob: e22574b27662f9a26148a5f2eb4833181dbe6781 [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>
21#include <string.h>
22#include <fcntl.h>
23#include <errno.h>
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <sys/select.h>
27#include <sys/time.h>
28#include <zlib.h>
29#include <ctype.h>
30#include <semaphore.h>
31#include <string>
32#include <fstream>
33#include <sstream>
34#include <algorithm>
35
36#include "twadbstream.h"
37#include "twrpback.hpp"
38#include "../variables.h"
39#include "../twcommon.h"
40#include "../twrpDigest.hpp"
41
42twrpback::twrpback(void) {
43 read_fd = 0;
44 write_fd = 0;
45 adb_control_twrp_fd = 0;
46 adb_control_bu_fd = 0;
47 adb_read_fd = 0;
48 adb_write_fd = 0;
49 adb_write_fd = 0;
50 ors_fd = 0;
51 firstPart = true;
52 adbloginit();
53}
54
55twrpback::~twrpback(void) {
56 adblogfile.close();
57}
58
59void twrpback::adbloginit(void) {
60 adblogfile.open("/tmp/adb.log", std::fstream::app);
61}
62
63void twrpback::adblogwrite(std::string writemsg) {
64 adblogfile << writemsg << std::flush;
65}
66
67void twrpback::close_backup_fds() {
68 if (ors_fd > 0)
69 close(ors_fd);
70 if (write_fd > 0)
71 close(write_fd);
72 if (adb_read_fd > 0)
73 close(adb_read_fd);
74 if (adb_control_bu_fd > 0)
75 close(adb_control_bu_fd);
76 if (adbd_fp != NULL)
77 fclose(adbd_fp);
78 if (access(TW_ADB_BACKUP, F_OK) == 0)
79 unlink(TW_ADB_BACKUP);
80}
81
82void twrpback::close_restore_fds() {
83 if (ors_fd > 0)
84 close(ors_fd);
85 if (write_fd > 0)
86 close(write_fd);
87 if (adb_control_bu_fd > 0)
88 close(adb_control_bu_fd);
89 if (adb_control_twrp_fd > 0)
90 close(adb_control_twrp_fd);
91 if (adbd_fp != NULL)
92 fclose(adbd_fp);
93 if (access(TW_ADB_RESTORE, F_OK) == 0)
94 unlink(TW_ADB_RESTORE);
95}
96
97int twrpback::backup(std::string command) {
98 twrpDigest adb_md5;
99 bool breakloop = false;
100 int bytes = 0, errctr = 0;
101 char result[MAX_ADB_READ];
102 uint64_t totalbytes = 0, dataChunkBytes = 0;
103 int64_t count = -1; // Count of how many blocks set
104 uint64_t md5fnsize = 0;
105 struct AdbBackupControlType endadb;
106
107 ADBSTRUCT_STATIC_ASSERT(sizeof(endadb) == MAX_ADB_READ);
108
109 bool writedata = true;
110 bool compressed = false;
111 bool firstDataPacket = true;
112
113 adbd_fp = fdopen(adbd_fd, "w");
114 if (adbd_fp == NULL) {
115 adblogwrite("Unable to open adb_fp\n");
116 return -1;
117 }
118
119 if (mkfifo(TW_ADB_BACKUP, 0666) < 0) {
120 adblogwrite("Unable to create TW_ADB_BACKUP fifo\n");
121 return -1;
122 }
123
124 adblogwrite("opening ORS_INPUT_FILE\n");
125 write_fd = open(ORS_INPUT_FILE, O_WRONLY);
126 while (write_fd < 0) {
127 write_fd = open(ORS_INPUT_FILE, O_WRONLY);
128 usleep(10000);
129 errctr++;
130 if (errctr > ADB_BU_MAX_ERROR) {
131 adblogwrite("Unable to open ORS_INPUT_FILE\n");
132 close_backup_fds();
133 return -1;
134 }
135 }
136
137 sprintf(operation, "adbbackup %s", command.c_str());
138 if (write(write_fd, operation, sizeof(operation)) != sizeof(operation)) {
139 adblogwrite("Unable to write to ORS_INPUT_FILE\n");
140 close_backup_fds();
141 return -1;
142 }
143
144 adblogwrite("opening ORS_OUTPUT_FILE\n");
145 ors_fd = open(ORS_OUTPUT_FILE, O_RDONLY);
146 if (ors_fd < 0) {
147 adblogwrite("Unable to open ORS_OUTPUT_FILE\n");
148 close_backup_fds();
149 return -1;
150 }
151
152 memset(&result, 0, sizeof(result));
153 memset(&cmd, 0, sizeof(cmd));
154
155 adblogwrite("opening TW_ADB_BU_CONTROL\n");
156 adb_control_bu_fd = open(TW_ADB_BU_CONTROL, O_RDONLY | O_NONBLOCK);
157 if (adb_control_bu_fd < 0) {
158 adblogwrite("Unable to open TW_ADB_BU_CONTROL for reading.\n");
159 close_backup_fds();
160 return -1;
161 }
162
163 adblogwrite("opening TW_ADB_BACKUP\n");
164 adb_read_fd = open(TW_ADB_BACKUP, O_RDONLY | O_NONBLOCK);
165 if (adb_read_fd < 0) {
166 adblogwrite("Unable to open TW_ADB_BACKUP for reading.\n");
167 close_backup_fds();
168 return -1;
169 }
170
171 //loop until TWENDADB sent
172 while (!breakloop) {
173 if (read(adb_control_bu_fd, &cmd, sizeof(cmd)) > 0) {
174 struct AdbBackupControlType structcmd;
175
176 memcpy(&structcmd, cmd, sizeof(cmd));
177 std::string cmdstr(structcmd.type);
178 std::string cmdtype = cmdstr.substr(0, sizeof(structcmd.type) - 1);
179
180 //we received an error, exit and unlink
181 if (cmdtype == TWERROR) {
182 writedata = false;
183 adblogwrite("Error received. Quitting...\n");
184 close_backup_fds();
185 return -1;
186 }
187 //we received the end of adb backup stream so we should break the loop
188 else if (cmdtype == TWENDADB) {
189 writedata = false;
190 adblogwrite("Recieved TWENDADB\n");
191 memcpy(&endadb, cmd, sizeof(cmd));
192 stringstream str;
193 str << totalbytes;
194 adblogwrite(str.str() + " total bytes written\n");
195 breakloop = true;
196 }
197 //we recieved the TWSTREAMHDR structure metadata to write to adb
198 else if (cmdtype == TWSTREAMHDR) {
199 writedata = false;
200 adblogwrite("Writing TWSTREAMHDR\n");
201 if (fwrite(cmd, 1, sizeof(cmd), adbd_fp) != sizeof(cmd)) {
202 stringstream str;
203 str << strerror(errno);
204 adblogwrite("Error writing TWSTREAMHDR to adbd" + str.str() + "\n");
205 close_backup_fds();
206 return -1;
207 }
208 fflush(adbd_fp);
209 }
210 //we will be writing an image from TWRP
211 else if (cmdtype == TWIMG) {
212 struct twfilehdr twimghdr;
213
214 adblogwrite("Writing TWIMG\n");
215 adb_md5.initMD5();
216
217 memset(&twimghdr, 0, sizeof(twimghdr));
218 memcpy(&twimghdr, cmd, sizeof(cmd));
219 md5fnsize = twimghdr.size;
220
221 if (fwrite(cmd, 1, sizeof(cmd), adbd_fp) != sizeof(cmd)) {
222 adblogwrite("Error writing TWIMG to adbd\n");
223 close_backup_fds();
224 return -1;
225 }
226 fflush(adbd_fp);
227 writedata = true;
228 }
229 //we will be writing a tar from TWRP
230 else if (cmdtype == TWFN) {
231 struct twfilehdr twfilehdr;
232
233 adblogwrite("Writing TWFN\n");
234 adb_md5.initMD5();
235
236 ADBSTRUCT_STATIC_ASSERT(sizeof(twfilehdr) == MAX_ADB_READ);
237
238 memset(&twfilehdr, 0, sizeof(twfilehdr));
239 memcpy(&twfilehdr, cmd, sizeof(cmd));
240 md5fnsize = twfilehdr.size;
241
242 compressed = twfilehdr.compressed == 1 ? true: false;
243
244 if (fwrite(cmd, 1, sizeof(cmd), adbd_fp) != sizeof(cmd)) {
245 adblogwrite("Error writing TWFN to adbd\n");
246 close_backup_fds();
247 return -1;
248 }
249 fflush(adbd_fp);
250 writedata = true;
251 }
252 /*
253 We received the command that we are done with the file stream.
254 We will flush the remaining data stream.
255 Update md5 and write final results to adb stream.
256 If we need padding because the total bytes are not a multiple
257 of 512, we pad the end with 0s to we reach 512.
258 We also write the final md5 to the adb stream.
259 */
260 else if (cmdtype == TWEOF) {
261 adblogwrite("received TWEOF\n");
262 count = totalbytes / MAX_ADB_READ + 1;
263 count = count * MAX_ADB_READ;
264
265 while ((bytes = read(adb_read_fd, &result, sizeof(result))) == MAX_ADB_READ) {
266 totalbytes += bytes;
267 char *writeresult = new char [bytes];
268 memcpy(writeresult, result, bytes);
269 if (adb_md5.updateMD5stream((unsigned char *) writeresult, bytes) == -1)
270 adblogwrite("failed to update md5 stream\n");
271 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 }
290 if (adb_md5.updateMD5stream((unsigned char *) padding, sizeof(padding)) == -1)
291 adblogwrite("failed to update md5 stream\n");
292 fflush(adbd_fp);
293 totalbytes = 0;
294 }
295
296 AdbBackupFileTrailer md5trailer;
297
298 memset(&md5trailer, 0, sizeof(md5trailer));
299 adb_md5.finalizeMD5stream();
300
301 std::string md5string = adb_md5.createMD5string();
302
303 strncpy(md5trailer.start_of_trailer, TWRP, sizeof(md5trailer.start_of_trailer));
304 strncpy(md5trailer.type, MD5TRAILER, sizeof(md5trailer.type));
305 strncpy(md5trailer.md5, md5string.c_str(), sizeof(md5trailer.md5));
306
307 md5trailer.crc = crc32(0L, Z_NULL, 0);
308 md5trailer.crc = crc32(md5trailer.crc, (const unsigned char*) &md5trailer, sizeof(md5trailer));
309
310 md5trailer.ident = crc32(0L, Z_NULL, 0);
311 md5trailer.ident = crc32(md5trailer.ident, (const unsigned char*) &md5trailer, sizeof(md5trailer));
312 md5trailer.ident = crc32(md5trailer.ident, (const unsigned char*) &md5fnsize, sizeof(md5fnsize));
313
314 if (fwrite(&md5trailer, 1, sizeof(md5trailer), adbd_fp) != sizeof(md5trailer)) {
315 adblogwrite("Error writing md5trailer to adbd\n");
316 close_backup_fds();
317 return -1;
318 }
319 fflush(adbd_fp);
320 writedata = false;
321 firstDataPacket = true;
322 }
323 memset(&cmd, 0, sizeof(cmd));
324 }
325 //If we are to write data because of a new file stream, lets write all the data.
326 //This will allow us to not write data after a command structure has been written
327 //to the adb stream.
328 //If the stream is compressed, we need to always write the data.
329 if (writedata || compressed) {
330 while ((bytes = read(adb_read_fd, &result, sizeof(result))) == MAX_ADB_READ) {
331 if (firstDataPacket) {
332 struct AdbBackupControlType data_block;
333
334 memset(&data_block, 0, sizeof(data_block));
335 strncpy(data_block.start_of_header, TWRP, sizeof(data_block.start_of_header));
336 strncpy(data_block.type, TWDATA, sizeof(data_block.type));
337 data_block.crc = crc32(0L, Z_NULL, 0);
338 data_block.crc = crc32(data_block.crc, (const unsigned char*) &data_block, sizeof(data_block));
339 if (fwrite(&data_block, 1, sizeof(data_block), adbd_fp) != sizeof(data_block)) {
340 adblogwrite("Error writing data_block to adbd\n");
341 close_backup_fds();
342 return -1;
343 }
344 fflush(adbd_fp);
345 firstDataPacket = false;
346 }
347 char *writeresult = new char [bytes];
348 memcpy(writeresult, result, bytes);
349
350 if (adb_md5.updateMD5stream((unsigned char *) writeresult, bytes) == -1)
351 adblogwrite("failed to update md5 stream\n");
352
353 totalbytes += bytes;
354 dataChunkBytes += bytes;
355
356 if (fwrite(writeresult, 1, bytes, adbd_fp) != bytes) {
357 adblogwrite("Error writing backup data to adbd\n");
358 close_backup_fds();
359 return -1;
360 }
361 fflush(adbd_fp);
362
363 delete [] writeresult;
364 memset(&result, 0, sizeof(result));
365 if (dataChunkBytes == DATA_MAX_CHUNK_SIZE - sizeof(result)) {
366 struct AdbBackupControlType data_block;
367
368 memset(&data_block, 0, sizeof(data_block));
369 strncpy(data_block.start_of_header, TWRP, sizeof(data_block.start_of_header));
370 strncpy(data_block.type, TWDATA, sizeof(data_block.type));
371 data_block.crc = crc32(0L, Z_NULL, 0);
372 data_block.crc = crc32(data_block.crc, (const unsigned char*) &data_block, sizeof(data_block));
373 if (fwrite(&data_block, 1, sizeof(data_block), adbd_fp) != sizeof(data_block)) {
374 adblogwrite("Error writing data_block to adbd\n");
375 close_backup_fds();
376 return -1;
377 }
378 fflush(adbd_fp);
379 dataChunkBytes = 0;
380 }
381
382 }
383 compressed = false;
384 }
385 }
386
387 //Write the final end adb structure to the adb stream
388 if (fwrite(&endadb, 1, sizeof(endadb), adbd_fp) != sizeof(endadb)) {
389 adblogwrite("Error writing endadb to adbd\n");
390 close_backup_fds();
391 return -1;
392 }
393 fflush(adbd_fp);
394 close_backup_fds();
395 return 0;
396}
397
398int twrpback::restore(void) {
399 twrpDigest adb_md5;
400 char cmd[MAX_ADB_READ];
401 char result[MAX_ADB_READ];
402 struct AdbBackupControlType structcmd;
403 int adb_control_twrp_fd, errctr = 0;
404 uint64_t totalbytes = 0, dataChunkBytes = 0;
405 uint64_t md5fnsize = 0;
406 bool writedata, read_from_adb;
407 bool breakloop, eofsent, md5trsent;
408
409 breakloop = false;
410 read_from_adb = true;
411
412 signal(SIGPIPE, SIG_IGN);
413
414 adbd_fp = fdopen(adbd_fd, "r");
415 if (adbd_fp == NULL) {
416 adblogwrite("Unable to open adb_fp\n");
417 close_restore_fds();
418 return -1;
419 }
420
421 if(mkfifo(TW_ADB_RESTORE, 0666)) {
422 adblogwrite("Unable to create TW_ADB_RESTORE fifo\n");
423 close_restore_fds();
424 return -1;
425 }
426
427 adblogwrite("opening ORS_INPUT_FILE\n");
428 write_fd = open(ORS_INPUT_FILE, O_WRONLY);
429
430 while (write_fd < 0) {
431 write_fd = open(ORS_INPUT_FILE, O_WRONLY);
432 errctr++;
433 if (errctr > ADB_BU_MAX_ERROR) {
434 adblogwrite("Unable to open ORS_INPUT_FILE\n");
435 close_restore_fds();
436 return -1;
437 }
438 }
439
440 sprintf(operation, "adbrestore");
441 if (write(write_fd, operation, sizeof(operation)) != sizeof(operation)) {
442 adblogwrite("Unable to write to ORS_INPUT_FILE\n");
443 close_restore_fds();
444 return -1;
445 }
446
447 ors_fd = open(ORS_OUTPUT_FILE, O_RDONLY);
448 if (ors_fd < 0) {
449 stringstream str;
450 str << strerror(errno);
451 adblogwrite("Unable to write to ORS_OUTPUT_FILE: " + str.str() + "\n");
452 close_restore_fds();
453 return -1;
454 }
455
456 memset(&result, 0, sizeof(result));
457 memset(&cmd, 0, sizeof(cmd));
458
459 adblogwrite("opening TW_ADB_BU_CONTROL\n");
460 adb_control_bu_fd = open(TW_ADB_BU_CONTROL, O_RDONLY | O_NONBLOCK);
461 if (adb_control_bu_fd < 0) {
462 stringstream str;
463 str << strerror(errno);
464 adblogwrite("Unable to open TW_ADB_BU_CONTROL for writing. " + str.str() + "\n");
465 close_restore_fds();
466 return -1;
467 }
468
469 adblogwrite("opening TW_ADB_TWRP_CONTROL\n");
470 adb_control_twrp_fd = open(TW_ADB_TWRP_CONTROL, O_WRONLY | O_NONBLOCK);
471 if (adb_control_twrp_fd < 0) {
472 stringstream str;
473 str << strerror(errno);
474 adblogwrite("Unable to open TW_ADB_TWRP_CONTROL for writing. " + str.str() + ". Retrying...\n");
475 while (adb_control_twrp_fd < 0) {
476 adb_control_twrp_fd = open(TW_ADB_TWRP_CONTROL, O_WRONLY | O_NONBLOCK);
477 usleep(10000);
478 errctr++;
479 if (errctr > ADB_BU_MAX_ERROR) {
480 adblogwrite("Unable to open TW_ADB_TWRP_CONTROL\n");
481 close_backup_fds();
482 return -1;
483 }
484 }
485 }
486
487 //Loop until we receive TWENDADB from TWRP
488 while (!breakloop) {
489 memset(&cmd, 0, sizeof(cmd));
490 if (read(adb_control_bu_fd, &cmd, sizeof(cmd)) > 0) {
491 struct AdbBackupControlType structcmd;
492 memcpy(&structcmd, cmd, sizeof(cmd));
493 std::string cmdstr(structcmd.type);
494 std::string cmdtype = cmdstr.substr(0, sizeof(structcmd.type) - 1);
495
496 //If we receive TWEOF from TWRP close adb data fifo
497 if (cmdtype == TWEOF) {
498 adblogwrite("Received TWEOF\n");
499 struct AdbBackupControlType tweof;
500
501 memset(&tweof, 0, sizeof(tweof));
502 memcpy(&tweof, result, sizeof(result));
503 read_from_adb = true;
504 }
505 //Break when TWRP sends TWENDADB
506 else if (cmdtype == TWENDADB) {
507 adblogwrite("Received TWENDADB\n");
508 breakloop = true;
509 close_restore_fds();
510 }
511 //we received an error, exit and unlink
512 else if (cmdtype == TWERROR) {
513 adblogwrite("Error received. Quitting...\n");
514 close_restore_fds();
515 return -1;
516 }
517 }
518
519 //If we should read from the adb stream, write commands and data to TWRP
520 if (read_from_adb) {
521 std::string cmdstr;
522 int readbytes;
523 if ((readbytes = fread(result, 1, sizeof(result), adbd_fp)) == sizeof(result)) {
524 totalbytes += readbytes;
525 memcpy(&structcmd, result, sizeof(result));
526 cmdstr = structcmd.type;
527 std::string cmdtype = cmdstr.substr(0, sizeof(structcmd.type) - 1);
528
529 //Tell TWRP we have read the entire adb stream
530 if (cmdtype == TWENDADB) {
531 struct AdbBackupControlType endadb;
532 uint32_t crc, endadbcrc;
533
534 totalbytes -= sizeof(result);
535 memset(&endadb, 0, sizeof(endadb));
536 memcpy(&endadb, result, sizeof(result));
537 endadbcrc = endadb.crc;
538 memset(&endadb.crc, 0, sizeof(endadb.crc));
539 crc = crc32(0L, Z_NULL, 0);
540 crc = crc32(crc, (const unsigned char*) &endadb, sizeof(endadb));
541
542 if (crc == endadbcrc) {
543 adblogwrite("Sending TWENDADB\n");
544 if (write(adb_control_twrp_fd, &endadb, sizeof(endadb)) < 1) {
545 stringstream str;
546 str << strerror(errno);
547 adblogwrite("Cannot write to ADB_CONTROL_READ_FD: " + str.str() + "\n");
548 close_restore_fds();
549 return -1;
550 }
551 }
552 else {
553 adblogwrite("ADB TWENDADB crc header doesn't match\n");
554 close_restore_fds();
555 return -1;
556 }
557 }
558 //Send TWRP partition metadata
559 else if (cmdtype == TWSTREAMHDR) {
560 struct AdbBackupStreamHeader cnthdr;
561 uint32_t crc, cnthdrcrc;
562
563 ADBSTRUCT_STATIC_ASSERT(sizeof(cnthdr) == MAX_ADB_READ);
564 totalbytes -= sizeof(result);
565
566 memset(&cnthdr, 0, sizeof(cnthdr));
567 memcpy(&cnthdr, result, sizeof(result));
568 cnthdrcrc = cnthdr.crc;
569 memset(&cnthdr.crc, 0, sizeof(cnthdr.crc));
570 crc = crc32(0L, Z_NULL, 0);
571 crc = crc32(crc, (const unsigned char*) &cnthdr, sizeof(cnthdr));
572
573 if (crc == cnthdrcrc) {
574 adblogwrite("Restoring TWSTREAMHDR\n");
575 if (write(adb_control_twrp_fd, result, sizeof(result)) < 0) {
576 stringstream str;
577 str << strerror(errno);
578 adblogwrite("Cannot write to adb_control_twrp_fd: " + str.str() + "\n");
579 close_restore_fds();
580 return -1;
581 }
582 }
583 else {
584 adblogwrite("ADB TWSTREAMHDR crc header doesn't match\n");
585 close_restore_fds();
586 return -1;
587 }
588 }
589 //Tell TWRP we are sending a partition image
590 else if (cmdtype == TWIMG) {
591 struct twfilehdr twimghdr;
592 uint32_t crc, twimghdrcrc;
593
594 totalbytes -= sizeof(result);
595 adb_md5.initMD5();
596 adblogwrite("Restoring TWIMG\n");
597 memset(&twimghdr, 0, sizeof(twimghdr));
598 memcpy(&twimghdr, result, sizeof(result));
599 md5fnsize = twimghdr.size;
600 twimghdrcrc = twimghdr.crc;
601 memset(&twimghdr.crc, 0, sizeof(twimghdr.crc));
602
603 crc = crc32(0L, Z_NULL, 0);
604 crc = crc32(crc, (const unsigned char*) &twimghdr, sizeof(twimghdr));
605 if (crc == twimghdrcrc) {
606 if (write(adb_control_twrp_fd, result, sizeof(result)) < 1) {
607 stringstream str;
608 str << strerror(errno);
609 adblogwrite("Cannot write to adb_control_twrp_fd: " + str.str() + "\n");
610 close_restore_fds();
611 return -1;
612 }
613 }
614 else {
615 adblogwrite("ADB TWIMG crc header doesn't match\n");
616 close_restore_fds();
617 return -1;
618 }
619 adblogwrite("opening TW_ADB_RESTORE\n");
620 adb_write_fd = open(TW_ADB_RESTORE, O_WRONLY);
621 }
622 //Tell TWRP we are sending a tar stream
623 else if (cmdtype == TWFN) {
624 struct twfilehdr twfilehdr;
625 uint32_t crc, twfilehdrcrc;
626
627 totalbytes -= sizeof(result);
628 adb_md5.initMD5();
629 adblogwrite("Restoring TWFN\n");
630 memset(&twfilehdr, 0, sizeof(twfilehdr));
631 memcpy(&twfilehdr, result, sizeof(result));
632 md5fnsize = twfilehdr.size;
633 twfilehdrcrc = twfilehdr.crc;
634 memset(&twfilehdr.crc, 0, sizeof(twfilehdr.crc));
635
636 crc = crc32(0L, Z_NULL, 0);
637 crc = crc32(crc, (const unsigned char*) &twfilehdr, sizeof(twfilehdr));
638
639 if (crc == twfilehdrcrc) {
640 if (write(adb_control_twrp_fd, result, sizeof(result)) < 1) {
641 stringstream str;
642 str << strerror(errno);
643 adblogwrite("Cannot write to adb_control_twrp_fd: " + str.str() + "\n");
644 close_restore_fds();
645 return -1;
646 }
647 }
648 else {
649 adblogwrite("ADB TWFN crc header doesn't match\n");
650 close_restore_fds();
651 return -1;
652 }
653
654 adblogwrite("opening TW_ADB_RESTORE\n");
655 adb_write_fd = open(TW_ADB_RESTORE, O_WRONLY);
656 }
657 //Send the tar or partition image md5 to TWRP
658 else if (cmdtype == TWDATA) {
659 totalbytes -= sizeof(result);
660 while (1) {
661 if ((readbytes = fread(result, 1, sizeof(result), adbd_fp)) != sizeof(result)) {
662 close_restore_fds();
663 return -1;
664 }
665 totalbytes += readbytes;
666 memcpy(&structcmd, result, sizeof(result));
667 cmdstr = structcmd.type;
668
669 if (cmdstr.substr(0, sizeof(MD5TRAILER) - 1) == MD5TRAILER) {
670 struct AdbBackupFileTrailer md5tr;
671 uint32_t crc, md5trcrc, md5ident, md5identmatch;
672
673 ADBSTRUCT_STATIC_ASSERT(sizeof(md5tr) == MAX_ADB_READ);
674 memset(&md5tr, 0, sizeof(md5tr));
675 memcpy(&md5tr, result, sizeof(result));
676 md5ident = md5tr.ident;
677
678 memset(&md5tr.ident, 0, sizeof(md5tr.ident));
679
680 md5identmatch = crc32(0L, Z_NULL, 0);
681 md5identmatch = crc32(md5identmatch, (const unsigned char*) &md5tr, sizeof(md5tr));
682 md5identmatch = crc32(md5identmatch, (const unsigned char*) &md5fnsize, sizeof(md5fnsize));
683
684 if (md5identmatch == md5ident) {
685 totalbytes -= sizeof(result);
686 close(adb_write_fd);
687 adblogwrite("Restoring MD5TRAILER\n");
688 md5trcrc = md5tr.crc;
689 memset(&md5tr.crc, 0, sizeof(md5tr.crc));
690 crc = crc32(0L, Z_NULL, 0);
691 crc = crc32(crc, (const unsigned char*) &md5tr, sizeof(md5tr));
692 if (crc == md5trcrc) {
693 if (write(adb_control_twrp_fd, result, sizeof(result)) < 1) {
694 stringstream str;
695 str << strerror(errno);
696 adblogwrite("Cannot write to adb_control_twrp_fd: " + str.str() + "\n");
697 close_restore_fds();
698 return -1;
699 }
700 }
701 else {
702 adblogwrite("ADB MD5TRAILER crc header doesn't match\n");
703 close_restore_fds();
704 return -1;
705 }
706 adblogwrite("md5 finalize stream\n");
707 adb_md5.finalizeMD5stream();
708
709 AdbBackupFileTrailer md5;
710
711 memset(&md5, 0, sizeof(md5));
712 strncpy(md5.start_of_trailer, TWRP, sizeof(md5.start_of_trailer));
713 strncpy(md5.type, TWMD5, sizeof(md5.type));
714 std::string md5string = adb_md5.createMD5string();
715 strncpy(md5.md5, md5string.c_str(), sizeof(md5.md5));
716
717 adblogwrite("Sending MD5Check\n");
718 if (write(adb_control_twrp_fd, &md5, sizeof(md5)) < 1) {
719 stringstream str;
720 str << strerror(errno);
721 adblogwrite("Cannot write to adb_control_twrp_fd: " + str.str() + "\n");
722 close_restore_fds();
723 return -1;
724 }
725 read_from_adb = false; //don't read from adb until TWRP sends TWEOF
726 break;
727 }
728 }
729 if (adb_md5.updateMD5stream((unsigned char*)result, sizeof(result)) == -1)
730 adblogwrite("failed to update md5 stream\n");
731 dataChunkBytes += readbytes;
732
733 if (write(adb_write_fd, result, sizeof(result)) < 0) {
734 stringstream str;
735 str << strerror(errno);
736 adblogwrite("Cannot write to adb_write_fd\n" + str.str() + ". Retrying.\n");
737 while(write(adb_write_fd, result, sizeof(result)) < 0) {
738 adblogwrite("Cannot write to adb_write_fd\n" + str.str() + ". Retrying.\n");
739 continue;
740 }
741 }
742 if (dataChunkBytes == ((DATA_MAX_CHUNK_SIZE) - sizeof(result))) {
743 dataChunkBytes = 0;
744 break;
745 }
746 memset(&result, 0, sizeof(result));
747 }
748 }
749 }
750 }
751 }
752
753 stringstream str;
754 str << totalbytes;
755 adblogwrite(str.str() + " bytes restored from adbbackup\n");
756 return 0;
757}
758
759int main(int argc, char **argv) {
760 int index;
761 int ret = 0, pos = 0;
762 std::string command;
763 twrpback tw;
764
765 tw.adblogwrite("Starting adb backup and restore\n");
766 if (mkfifo(TW_ADB_BU_CONTROL, 0666) < 0) {
767 stringstream str;
768 str << strerror(errno);
769 tw.adblogwrite("Unable to create TW_ADB_BU_CONTROL fifo: " + str.str() + "\n");
770 unlink(TW_ADB_BU_CONTROL);
771 return -1;
772 }
773 if (mkfifo(TW_ADB_TWRP_CONTROL, 0666) < 0) {
774 stringstream str;
775 str << strerror(errno);
776 tw.adblogwrite("Unable to create TW_ADB_TWRP_CONTROL fifo: " + str.str() + "\n");
777 unlink(TW_ADB_TWRP_CONTROL);
778 unlink(TW_ADB_BU_CONTROL);
779 return -1;
780 }
781
782 command = argv[1];
783 for (index = 2; index < argc; index++) {
784 command = command + " " + argv[index];
785 }
786
787 pos = command.find("backup");
788 if (pos < 0) {
789 pos = command.find("restore");
790 }
791 command.erase(0, pos);
792 command.erase(std::remove(command.begin(), command.end(), '\''), command.end());
793 tw.adblogwrite("command: " + command + "\n");
794
795 if (command.substr(0, sizeof("backup") - 1) == "backup") {
796 tw.adblogwrite("Starting adb backup\n");
797 if (isdigit(*argv[1]))
798 tw.adbd_fd = atoi(argv[1]);
799 else
800 tw.adbd_fd = 1;
801 ret = tw.backup(command);
802 }
803 else if (command.substr(0, sizeof("restore") - 1) == "restore") {
804 tw.adblogwrite("Starting adb restore\n");
805 if (isdigit(*argv[1]))
806 tw.adbd_fd = atoi(argv[1]);
807 else
808 tw.adbd_fd = 0;
809 ret = tw.restore();
810 }
811 if (ret == 0)
812 tw.adblogwrite("Adb backup/restore completed\n");
813 else
814 tw.adblogwrite("Adb backup/restore failed\n");
815
816 if (unlink(TW_ADB_BU_CONTROL) < 0) {
817 stringstream str;
818 str << strerror(errno);
819 tw.adblogwrite("Unable to remove TW_ADB_BU_CONTROL: " + str.str());
820 }
821 unlink(TW_ADB_TWRP_CONTROL);
822 return ret;
823}