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