blob: 1c98a1b5c11e9b5c253b7e6a453e7642deb88161 [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
Ayke van Laethem05c2de42017-06-02 00:19:27 +0200136 memset(operation, 0, sizeof(operation));
137 if (snprintf(operation, sizeof(operation), "adbbackup %s", command.c_str()) >= sizeof(operation)) {
138 adblogwrite("Operation too big to write to ORS_INPUT_FILE\n");
139 close_backup_fds();
140 return -1;
141 }
bigbiffce8f83c2015-12-12 18:30:21 -0500142 if (write(write_fd, operation, sizeof(operation)) != sizeof(operation)) {
143 adblogwrite("Unable to write to ORS_INPUT_FILE\n");
144 close_backup_fds();
145 return -1;
146 }
147
148 adblogwrite("opening ORS_OUTPUT_FILE\n");
149 ors_fd = open(ORS_OUTPUT_FILE, O_RDONLY);
150 if (ors_fd < 0) {
151 adblogwrite("Unable to open ORS_OUTPUT_FILE\n");
152 close_backup_fds();
153 return -1;
154 }
155
156 memset(&result, 0, sizeof(result));
157 memset(&cmd, 0, sizeof(cmd));
158
159 adblogwrite("opening TW_ADB_BU_CONTROL\n");
160 adb_control_bu_fd = open(TW_ADB_BU_CONTROL, O_RDONLY | O_NONBLOCK);
161 if (adb_control_bu_fd < 0) {
162 adblogwrite("Unable to open TW_ADB_BU_CONTROL for reading.\n");
163 close_backup_fds();
164 return -1;
165 }
166
167 adblogwrite("opening TW_ADB_BACKUP\n");
168 adb_read_fd = open(TW_ADB_BACKUP, O_RDONLY | O_NONBLOCK);
169 if (adb_read_fd < 0) {
170 adblogwrite("Unable to open TW_ADB_BACKUP for reading.\n");
171 close_backup_fds();
172 return -1;
173 }
174
175 //loop until TWENDADB sent
176 while (!breakloop) {
177 if (read(adb_control_bu_fd, &cmd, sizeof(cmd)) > 0) {
178 struct AdbBackupControlType structcmd;
179
180 memcpy(&structcmd, cmd, sizeof(cmd));
Ayke van Laethem05c2de42017-06-02 00:19:27 +0200181 std::string cmdtype = structcmd.get_type();
bigbiffce8f83c2015-12-12 18:30:21 -0500182
183 //we received an error, exit and unlink
184 if (cmdtype == TWERROR) {
185 writedata = false;
186 adblogwrite("Error received. Quitting...\n");
187 close_backup_fds();
188 return -1;
189 }
190 //we received the end of adb backup stream so we should break the loop
191 else if (cmdtype == TWENDADB) {
192 writedata = false;
193 adblogwrite("Recieved TWENDADB\n");
194 memcpy(&endadb, cmd, sizeof(cmd));
Matt Mowercc19c6f2017-02-22 11:31:35 -0600195 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500196 str << totalbytes;
197 adblogwrite(str.str() + " total bytes written\n");
198 breakloop = true;
199 }
200 //we recieved the TWSTREAMHDR structure metadata to write to adb
201 else if (cmdtype == TWSTREAMHDR) {
202 writedata = false;
203 adblogwrite("Writing TWSTREAMHDR\n");
204 if (fwrite(cmd, 1, sizeof(cmd), adbd_fp) != sizeof(cmd)) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600205 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500206 str << strerror(errno);
207 adblogwrite("Error writing TWSTREAMHDR to adbd" + str.str() + "\n");
208 close_backup_fds();
209 return -1;
210 }
211 fflush(adbd_fp);
212 }
213 //we will be writing an image from TWRP
214 else if (cmdtype == TWIMG) {
215 struct twfilehdr twimghdr;
216
217 adblogwrite("Writing TWIMG\n");
218 adb_md5.initMD5();
219
220 memset(&twimghdr, 0, sizeof(twimghdr));
221 memcpy(&twimghdr, cmd, sizeof(cmd));
222 md5fnsize = twimghdr.size;
223
224 if (fwrite(cmd, 1, sizeof(cmd), adbd_fp) != sizeof(cmd)) {
225 adblogwrite("Error writing TWIMG to adbd\n");
226 close_backup_fds();
227 return -1;
228 }
229 fflush(adbd_fp);
230 writedata = true;
231 }
232 //we will be writing a tar from TWRP
233 else if (cmdtype == TWFN) {
234 struct twfilehdr twfilehdr;
235
236 adblogwrite("Writing TWFN\n");
237 adb_md5.initMD5();
238
239 ADBSTRUCT_STATIC_ASSERT(sizeof(twfilehdr) == MAX_ADB_READ);
240
241 memset(&twfilehdr, 0, sizeof(twfilehdr));
242 memcpy(&twfilehdr, cmd, sizeof(cmd));
243 md5fnsize = twfilehdr.size;
244
245 compressed = twfilehdr.compressed == 1 ? true: false;
246
247 if (fwrite(cmd, 1, sizeof(cmd), adbd_fp) != sizeof(cmd)) {
248 adblogwrite("Error writing TWFN to adbd\n");
249 close_backup_fds();
250 return -1;
251 }
252 fflush(adbd_fp);
253 writedata = true;
254 }
255 /*
256 We received the command that we are done with the file stream.
257 We will flush the remaining data stream.
258 Update md5 and write final results to adb stream.
259 If we need padding because the total bytes are not a multiple
260 of 512, we pad the end with 0s to we reach 512.
261 We also write the final md5 to the adb stream.
262 */
263 else if (cmdtype == TWEOF) {
264 adblogwrite("received TWEOF\n");
265 count = totalbytes / MAX_ADB_READ + 1;
266 count = count * MAX_ADB_READ;
267
268 while ((bytes = read(adb_read_fd, &result, sizeof(result))) == MAX_ADB_READ) {
269 totalbytes += bytes;
270 char *writeresult = new char [bytes];
271 memcpy(writeresult, result, bytes);
272 if (adb_md5.updateMD5stream((unsigned char *) writeresult, bytes) == -1)
273 adblogwrite("failed to update md5 stream\n");
274 if (fwrite(writeresult, 1, bytes, adbd_fp) != bytes) {
275 adblogwrite("Error writing backup data to adbd\n");
276 close_backup_fds();
277 return -1;
278 }
279 fflush(adbd_fp);
280 delete [] writeresult;
281 memset(&result, 0, sizeof(result));
282 }
283
284 if ((totalbytes % MAX_ADB_READ) != 0) {
285 adblogwrite("writing padding to stream\n");
286 char padding[count - totalbytes];
287 memset(padding, 0, sizeof(padding));
288 if (fwrite(padding, 1, sizeof(padding), adbd_fp) != sizeof(padding)) {
289 adblogwrite("Error writing padding to adbd\n");
290 close_backup_fds();
291 return -1;
292 }
293 if (adb_md5.updateMD5stream((unsigned char *) padding, sizeof(padding)) == -1)
294 adblogwrite("failed to update md5 stream\n");
295 fflush(adbd_fp);
296 totalbytes = 0;
297 }
298
299 AdbBackupFileTrailer md5trailer;
300
301 memset(&md5trailer, 0, sizeof(md5trailer));
302 adb_md5.finalizeMD5stream();
303
304 std::string md5string = adb_md5.createMD5string();
305
306 strncpy(md5trailer.start_of_trailer, TWRP, sizeof(md5trailer.start_of_trailer));
307 strncpy(md5trailer.type, MD5TRAILER, sizeof(md5trailer.type));
308 strncpy(md5trailer.md5, md5string.c_str(), sizeof(md5trailer.md5));
309
310 md5trailer.crc = crc32(0L, Z_NULL, 0);
311 md5trailer.crc = crc32(md5trailer.crc, (const unsigned char*) &md5trailer, sizeof(md5trailer));
312
313 md5trailer.ident = crc32(0L, Z_NULL, 0);
314 md5trailer.ident = crc32(md5trailer.ident, (const unsigned char*) &md5trailer, sizeof(md5trailer));
315 md5trailer.ident = crc32(md5trailer.ident, (const unsigned char*) &md5fnsize, sizeof(md5fnsize));
316
317 if (fwrite(&md5trailer, 1, sizeof(md5trailer), adbd_fp) != sizeof(md5trailer)) {
318 adblogwrite("Error writing md5trailer to adbd\n");
319 close_backup_fds();
320 return -1;
321 }
322 fflush(adbd_fp);
323 writedata = false;
324 firstDataPacket = true;
325 }
326 memset(&cmd, 0, sizeof(cmd));
327 }
328 //If we are to write data because of a new file stream, lets write all the data.
329 //This will allow us to not write data after a command structure has been written
330 //to the adb stream.
331 //If the stream is compressed, we need to always write the data.
332 if (writedata || compressed) {
bigbiff bigbiff4a2a1912017-06-03 10:55:46 -0400333 while ((bytes = read(adb_read_fd, &result, sizeof(result))) > 0) {
bigbiffce8f83c2015-12-12 18:30:21 -0500334 if (firstDataPacket) {
335 struct AdbBackupControlType data_block;
336
337 memset(&data_block, 0, sizeof(data_block));
338 strncpy(data_block.start_of_header, TWRP, sizeof(data_block.start_of_header));
339 strncpy(data_block.type, TWDATA, sizeof(data_block.type));
340 data_block.crc = crc32(0L, Z_NULL, 0);
341 data_block.crc = crc32(data_block.crc, (const unsigned char*) &data_block, sizeof(data_block));
342 if (fwrite(&data_block, 1, sizeof(data_block), adbd_fp) != sizeof(data_block)) {
343 adblogwrite("Error writing data_block to adbd\n");
344 close_backup_fds();
345 return -1;
346 }
347 fflush(adbd_fp);
348 firstDataPacket = false;
349 }
350 char *writeresult = new char [bytes];
351 memcpy(writeresult, result, bytes);
352
353 if (adb_md5.updateMD5stream((unsigned char *) writeresult, bytes) == -1)
354 adblogwrite("failed to update md5 stream\n");
355
356 totalbytes += bytes;
357 dataChunkBytes += bytes;
358
359 if (fwrite(writeresult, 1, bytes, adbd_fp) != bytes) {
360 adblogwrite("Error writing backup data to adbd\n");
361 close_backup_fds();
362 return -1;
363 }
364 fflush(adbd_fp);
365
366 delete [] writeresult;
367 memset(&result, 0, sizeof(result));
368 if (dataChunkBytes == DATA_MAX_CHUNK_SIZE - sizeof(result)) {
369 struct AdbBackupControlType data_block;
370
371 memset(&data_block, 0, sizeof(data_block));
372 strncpy(data_block.start_of_header, TWRP, sizeof(data_block.start_of_header));
373 strncpy(data_block.type, TWDATA, sizeof(data_block.type));
374 data_block.crc = crc32(0L, Z_NULL, 0);
375 data_block.crc = crc32(data_block.crc, (const unsigned char*) &data_block, sizeof(data_block));
376 if (fwrite(&data_block, 1, sizeof(data_block), adbd_fp) != sizeof(data_block)) {
377 adblogwrite("Error writing data_block to adbd\n");
378 close_backup_fds();
379 return -1;
380 }
381 fflush(adbd_fp);
382 dataChunkBytes = 0;
383 }
384
385 }
386 compressed = false;
387 }
388 }
389
390 //Write the final end adb structure to the adb stream
391 if (fwrite(&endadb, 1, sizeof(endadb), adbd_fp) != sizeof(endadb)) {
392 adblogwrite("Error writing endadb to adbd\n");
393 close_backup_fds();
394 return -1;
395 }
396 fflush(adbd_fp);
397 close_backup_fds();
398 return 0;
399}
400
401int twrpback::restore(void) {
402 twrpDigest adb_md5;
bigbiffce8f83c2015-12-12 18:30:21 -0500403 char result[MAX_ADB_READ];
404 struct AdbBackupControlType structcmd;
405 int adb_control_twrp_fd, errctr = 0;
406 uint64_t totalbytes = 0, dataChunkBytes = 0;
407 uint64_t md5fnsize = 0;
408 bool writedata, read_from_adb;
409 bool breakloop, eofsent, md5trsent;
410
411 breakloop = false;
412 read_from_adb = true;
413
414 signal(SIGPIPE, SIG_IGN);
415
416 adbd_fp = fdopen(adbd_fd, "r");
417 if (adbd_fp == NULL) {
418 adblogwrite("Unable to open adb_fp\n");
419 close_restore_fds();
420 return -1;
421 }
422
423 if(mkfifo(TW_ADB_RESTORE, 0666)) {
424 adblogwrite("Unable to create TW_ADB_RESTORE fifo\n");
425 close_restore_fds();
426 return -1;
427 }
428
429 adblogwrite("opening ORS_INPUT_FILE\n");
430 write_fd = open(ORS_INPUT_FILE, O_WRONLY);
431
432 while (write_fd < 0) {
433 write_fd = open(ORS_INPUT_FILE, O_WRONLY);
434 errctr++;
435 if (errctr > ADB_BU_MAX_ERROR) {
436 adblogwrite("Unable to open ORS_INPUT_FILE\n");
437 close_restore_fds();
438 return -1;
439 }
440 }
441
Ayke van Laethem05c2de42017-06-02 00:19:27 +0200442 memset(operation, 0, sizeof(operation));
bigbiffce8f83c2015-12-12 18:30:21 -0500443 sprintf(operation, "adbrestore");
444 if (write(write_fd, operation, sizeof(operation)) != sizeof(operation)) {
445 adblogwrite("Unable to write to ORS_INPUT_FILE\n");
446 close_restore_fds();
447 return -1;
448 }
449
450 ors_fd = open(ORS_OUTPUT_FILE, O_RDONLY);
451 if (ors_fd < 0) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600452 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500453 str << strerror(errno);
454 adblogwrite("Unable to write to ORS_OUTPUT_FILE: " + str.str() + "\n");
455 close_restore_fds();
456 return -1;
457 }
458
459 memset(&result, 0, sizeof(result));
460 memset(&cmd, 0, sizeof(cmd));
461
462 adblogwrite("opening TW_ADB_BU_CONTROL\n");
463 adb_control_bu_fd = open(TW_ADB_BU_CONTROL, O_RDONLY | O_NONBLOCK);
464 if (adb_control_bu_fd < 0) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600465 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500466 str << strerror(errno);
467 adblogwrite("Unable to open TW_ADB_BU_CONTROL for writing. " + str.str() + "\n");
468 close_restore_fds();
469 return -1;
470 }
471
472 adblogwrite("opening TW_ADB_TWRP_CONTROL\n");
473 adb_control_twrp_fd = open(TW_ADB_TWRP_CONTROL, O_WRONLY | O_NONBLOCK);
474 if (adb_control_twrp_fd < 0) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600475 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500476 str << strerror(errno);
477 adblogwrite("Unable to open TW_ADB_TWRP_CONTROL for writing. " + str.str() + ". Retrying...\n");
478 while (adb_control_twrp_fd < 0) {
479 adb_control_twrp_fd = open(TW_ADB_TWRP_CONTROL, O_WRONLY | O_NONBLOCK);
480 usleep(10000);
481 errctr++;
482 if (errctr > ADB_BU_MAX_ERROR) {
483 adblogwrite("Unable to open TW_ADB_TWRP_CONTROL\n");
484 close_backup_fds();
485 return -1;
486 }
487 }
488 }
489
490 //Loop until we receive TWENDADB from TWRP
491 while (!breakloop) {
492 memset(&cmd, 0, sizeof(cmd));
493 if (read(adb_control_bu_fd, &cmd, sizeof(cmd)) > 0) {
494 struct AdbBackupControlType structcmd;
495 memcpy(&structcmd, cmd, sizeof(cmd));
Ayke van Laethem05c2de42017-06-02 00:19:27 +0200496 std::string cmdtype = structcmd.get_type();
bigbiffce8f83c2015-12-12 18:30:21 -0500497
498 //If we receive TWEOF from TWRP close adb data fifo
499 if (cmdtype == TWEOF) {
500 adblogwrite("Received TWEOF\n");
501 struct AdbBackupControlType tweof;
502
503 memset(&tweof, 0, sizeof(tweof));
504 memcpy(&tweof, result, sizeof(result));
505 read_from_adb = true;
506 }
507 //Break when TWRP sends TWENDADB
508 else if (cmdtype == TWENDADB) {
509 adblogwrite("Received TWENDADB\n");
510 breakloop = true;
511 close_restore_fds();
512 }
513 //we received an error, exit and unlink
514 else if (cmdtype == TWERROR) {
515 adblogwrite("Error received. Quitting...\n");
516 close_restore_fds();
517 return -1;
518 }
519 }
bigbiffce8f83c2015-12-12 18:30:21 -0500520 //If we should read from the adb stream, write commands and data to TWRP
521 if (read_from_adb) {
bigbiffce8f83c2015-12-12 18:30:21 -0500522 int readbytes;
523 if ((readbytes = fread(result, 1, sizeof(result), adbd_fp)) == sizeof(result)) {
524 totalbytes += readbytes;
525 memcpy(&structcmd, result, sizeof(result));
Ayke van Laethem05c2de42017-06-02 00:19:27 +0200526 std::string cmdtype = structcmd.get_type();
bigbiffce8f83c2015-12-12 18:30:21 -0500527
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 }
bigbiff bigbiffb5ecaad2017-03-20 18:53:53 -0400550 read_from_adb = false;
bigbiffce8f83c2015-12-12 18:30:21 -0500551 }
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) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600576 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500577 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) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600607 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500608 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) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600641 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500642 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));
Ayke van Laethem05c2de42017-06-02 00:19:27 +0200667 std::string cmdtype = structcmd.get_type();
bigbiffce8f83c2015-12-12 18:30:21 -0500668
Ayke van Laethem05c2de42017-06-02 00:19:27 +0200669 if (cmdtype.substr(0, sizeof(MD5TRAILER) - 1) == MD5TRAILER) {
bigbiffce8f83c2015-12-12 18:30:21 -0500670 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) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600694 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500695 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) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600719 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500720 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) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600734 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500735 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
Matt Mowercc19c6f2017-02-22 11:31:35 -0600753 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500754 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) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600767 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500768 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) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600774 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500775 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
Ayke van Laethem05c2de42017-06-02 00:19:27 +0200782 if (argc <= 1) {
783 tw.adblogwrite("No parameters given, exiting...\n");
784 tw.close_restore_fds();
785 return -1;
786 }
787
bigbiffce8f83c2015-12-12 18:30:21 -0500788 command = argv[1];
789 for (index = 2; index < argc; index++) {
790 command = command + " " + argv[index];
791 }
792
793 pos = command.find("backup");
794 if (pos < 0) {
795 pos = command.find("restore");
796 }
797 command.erase(0, pos);
798 command.erase(std::remove(command.begin(), command.end(), '\''), command.end());
799 tw.adblogwrite("command: " + command + "\n");
800
801 if (command.substr(0, sizeof("backup") - 1) == "backup") {
802 tw.adblogwrite("Starting adb backup\n");
803 if (isdigit(*argv[1]))
804 tw.adbd_fd = atoi(argv[1]);
805 else
806 tw.adbd_fd = 1;
807 ret = tw.backup(command);
808 }
809 else if (command.substr(0, sizeof("restore") - 1) == "restore") {
810 tw.adblogwrite("Starting adb restore\n");
811 if (isdigit(*argv[1]))
812 tw.adbd_fd = atoi(argv[1]);
813 else
814 tw.adbd_fd = 0;
815 ret = tw.restore();
816 }
817 if (ret == 0)
818 tw.adblogwrite("Adb backup/restore completed\n");
819 else
820 tw.adblogwrite("Adb backup/restore failed\n");
821
822 if (unlink(TW_ADB_BU_CONTROL) < 0) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600823 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500824 str << strerror(errno);
825 tw.adblogwrite("Unable to remove TW_ADB_BU_CONTROL: " + str.str());
826 }
827 unlink(TW_ADB_TWRP_CONTROL);
828 return ret;
829}