blob: d88a9c9da590790ff136d90db3cd8f2dafaa6bf3 [file] [log] [blame]
bigbiffce8f83c2015-12-12 18:30:21 -05001/*
bigbiff bigbiff19fb79c2016-09-05 21:04:51 -04002 Copyright 2013 to 2017 TeamWin
bigbiffce8f83c2015-12-12 18:30:21 -05003 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>
bigbiffce8f83c2015-12-12 18:30:21 -050031#include <sstream>
bigbiff bigbiff19fb79c2016-09-05 21:04:51 -040032#include <fstream>
bigbiffce8f83c2015-12-12 18:30:21 -050033#include <algorithm>
bigbiff bigbiff19fb79c2016-09-05 21:04:51 -040034#include <utils/threads.h>
35#include <pthread.h>
bigbiffce8f83c2015-12-12 18:30:21 -050036
37#include "twadbstream.h"
38#include "twrpback.hpp"
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -040039#include "libtwadbbu.hpp"
bigbiff bigbiff56cf5642016-08-19 17:43:45 -040040#include "../twrpDigest/twrpDigest.hpp"
41#include "../twrpDigest/twrpMD5.hpp"
bigbiff bigbiff19fb79c2016-09-05 21:04:51 -040042#include "../twrpAdbBuFifo.hpp"
bigbiffce8f83c2015-12-12 18:30:21 -050043
44twrpback::twrpback(void) {
45 read_fd = 0;
46 write_fd = 0;
47 adb_control_twrp_fd = 0;
48 adb_control_bu_fd = 0;
49 adb_read_fd = 0;
50 adb_write_fd = 0;
51 adb_write_fd = 0;
52 ors_fd = 0;
53 firstPart = true;
bigbiff bigbiff19fb79c2016-09-05 21:04:51 -040054 createFifos();
bigbiffce8f83c2015-12-12 18:30:21 -050055 adbloginit();
56}
57
58twrpback::~twrpback(void) {
59 adblogfile.close();
bigbiff bigbiff19fb79c2016-09-05 21:04:51 -040060 closeFifos();
61}
62
63void twrpback::createFifos(void) {
64 if (mkfifo(TW_ADB_BU_CONTROL, 0666) < 0) {
65 std::stringstream str;
66 str << strerror(errno);
67 adblogwrite("Unable to create TW_ADB_BU_CONTROL fifo: " + str.str() + "\n");
68 }
69 if (mkfifo(TW_ADB_TWRP_CONTROL, 0666) < 0) {
70 std::stringstream str;
71 str << strerror(errno);
72 adblogwrite("Unable to create TW_ADB_TWRP_CONTROL fifo: " + str.str() + "\n");
73 unlink(TW_ADB_BU_CONTROL);
74 }
75}
76
77void twrpback::closeFifos(void) {
78 if (unlink(TW_ADB_BU_CONTROL) < 0) {
79 std::stringstream str;
80 str << strerror(errno);
81 adblogwrite("Unable to remove TW_ADB_BU_CONTROL: " + str.str());
82 }
83 if (unlink(TW_ADB_TWRP_CONTROL) < 0) {
84 std::stringstream str;
85 str << strerror(errno);
86 adblogwrite("Unable to remove TW_ADB_TWRP_CONTROL: " + str.str());
87 }
bigbiffce8f83c2015-12-12 18:30:21 -050088}
89
90void twrpback::adbloginit(void) {
91 adblogfile.open("/tmp/adb.log", std::fstream::app);
92}
93
94void twrpback::adblogwrite(std::string writemsg) {
95 adblogfile << writemsg << std::flush;
96}
97
98void twrpback::close_backup_fds() {
99 if (ors_fd > 0)
100 close(ors_fd);
101 if (write_fd > 0)
102 close(write_fd);
103 if (adb_read_fd > 0)
104 close(adb_read_fd);
105 if (adb_control_bu_fd > 0)
106 close(adb_control_bu_fd);
107 if (adbd_fp != NULL)
108 fclose(adbd_fp);
109 if (access(TW_ADB_BACKUP, F_OK) == 0)
110 unlink(TW_ADB_BACKUP);
111}
112
113void twrpback::close_restore_fds() {
114 if (ors_fd > 0)
115 close(ors_fd);
116 if (write_fd > 0)
117 close(write_fd);
118 if (adb_control_bu_fd > 0)
119 close(adb_control_bu_fd);
120 if (adb_control_twrp_fd > 0)
121 close(adb_control_twrp_fd);
122 if (adbd_fp != NULL)
123 fclose(adbd_fp);
124 if (access(TW_ADB_RESTORE, F_OK) == 0)
125 unlink(TW_ADB_RESTORE);
126}
127
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400128bool twrpback::backup(std::string command) {
bigbiff bigbiff56cf5642016-08-19 17:43:45 -0400129 twrpMD5 digest;
bigbiffce8f83c2015-12-12 18:30:21 -0500130 bool breakloop = false;
131 int bytes = 0, errctr = 0;
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400132 char adbReadStream[MAX_ADB_READ];
133 uint64_t totalbytes = 0, dataChunkBytes = 0, fileBytes = 0;
134 int64_t count = false; // Count of how many blocks set
bigbiffce8f83c2015-12-12 18:30:21 -0500135 uint64_t md5fnsize = 0;
136 struct AdbBackupControlType endadb;
137
138 ADBSTRUCT_STATIC_ASSERT(sizeof(endadb) == MAX_ADB_READ);
139
140 bool writedata = true;
141 bool compressed = false;
142 bool firstDataPacket = true;
143
144 adbd_fp = fdopen(adbd_fd, "w");
145 if (adbd_fp == NULL) {
146 adblogwrite("Unable to open adb_fp\n");
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400147 return false;
bigbiffce8f83c2015-12-12 18:30:21 -0500148 }
149
150 if (mkfifo(TW_ADB_BACKUP, 0666) < 0) {
151 adblogwrite("Unable to create TW_ADB_BACKUP fifo\n");
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400152 return false;
bigbiffce8f83c2015-12-12 18:30:21 -0500153 }
154
bigbiff bigbiff19fb79c2016-09-05 21:04:51 -0400155 adblogwrite("opening TW_ADB_FIFO\n");
156 write_fd = open(TW_ADB_FIFO, O_WRONLY);
bigbiffce8f83c2015-12-12 18:30:21 -0500157 while (write_fd < 0) {
bigbiff bigbiff19fb79c2016-09-05 21:04:51 -0400158 write_fd = open(TW_ADB_FIFO, O_WRONLY);
bigbiffce8f83c2015-12-12 18:30:21 -0500159 usleep(10000);
160 errctr++;
161 if (errctr > ADB_BU_MAX_ERROR) {
bigbiff bigbiff19fb79c2016-09-05 21:04:51 -0400162 adblogwrite("Unable to open TW_ADB_FIFO\n");
bigbiffce8f83c2015-12-12 18:30:21 -0500163 close_backup_fds();
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400164 return false;
bigbiffce8f83c2015-12-12 18:30:21 -0500165 }
166 }
167
Ayke van Laethem05c2de42017-06-02 00:19:27 +0200168 memset(operation, 0, sizeof(operation));
169 if (snprintf(operation, sizeof(operation), "adbbackup %s", command.c_str()) >= sizeof(operation)) {
170 adblogwrite("Operation too big to write to ORS_INPUT_FILE\n");
171 close_backup_fds();
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400172 return false;
Ayke van Laethem05c2de42017-06-02 00:19:27 +0200173 }
bigbiffce8f83c2015-12-12 18:30:21 -0500174 if (write(write_fd, operation, sizeof(operation)) != sizeof(operation)) {
175 adblogwrite("Unable to write to ORS_INPUT_FILE\n");
176 close_backup_fds();
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400177 return false;
bigbiffce8f83c2015-12-12 18:30:21 -0500178 }
179
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400180 memset(&adbReadStream, 0, sizeof(adbReadStream));
bigbiffce8f83c2015-12-12 18:30:21 -0500181 memset(&cmd, 0, sizeof(cmd));
182
183 adblogwrite("opening TW_ADB_BU_CONTROL\n");
184 adb_control_bu_fd = open(TW_ADB_BU_CONTROL, O_RDONLY | O_NONBLOCK);
185 if (adb_control_bu_fd < 0) {
186 adblogwrite("Unable to open TW_ADB_BU_CONTROL for reading.\n");
187 close_backup_fds();
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400188 return false;
bigbiffce8f83c2015-12-12 18:30:21 -0500189 }
190
191 adblogwrite("opening TW_ADB_BACKUP\n");
192 adb_read_fd = open(TW_ADB_BACKUP, O_RDONLY | O_NONBLOCK);
193 if (adb_read_fd < 0) {
194 adblogwrite("Unable to open TW_ADB_BACKUP for reading.\n");
195 close_backup_fds();
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400196 return false;
bigbiffce8f83c2015-12-12 18:30:21 -0500197 }
198
199 //loop until TWENDADB sent
200 while (!breakloop) {
201 if (read(adb_control_bu_fd, &cmd, sizeof(cmd)) > 0) {
202 struct AdbBackupControlType structcmd;
203
204 memcpy(&structcmd, cmd, sizeof(cmd));
Ayke van Laethem05c2de42017-06-02 00:19:27 +0200205 std::string cmdtype = structcmd.get_type();
bigbiffce8f83c2015-12-12 18:30:21 -0500206
207 //we received an error, exit and unlink
208 if (cmdtype == TWERROR) {
209 writedata = false;
210 adblogwrite("Error received. Quitting...\n");
211 close_backup_fds();
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400212 return false;
bigbiffce8f83c2015-12-12 18:30:21 -0500213 }
214 //we received the end of adb backup stream so we should break the loop
215 else if (cmdtype == TWENDADB) {
216 writedata = false;
217 adblogwrite("Recieved TWENDADB\n");
218 memcpy(&endadb, cmd, sizeof(cmd));
Matt Mowercc19c6f2017-02-22 11:31:35 -0600219 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500220 str << totalbytes;
221 adblogwrite(str.str() + " total bytes written\n");
222 breakloop = true;
223 }
224 //we recieved the TWSTREAMHDR structure metadata to write to adb
225 else if (cmdtype == TWSTREAMHDR) {
226 writedata = false;
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400227 adblogwrite("writing TWSTREAMHDR\n");
bigbiffce8f83c2015-12-12 18:30:21 -0500228 if (fwrite(cmd, 1, sizeof(cmd), adbd_fp) != sizeof(cmd)) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600229 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500230 str << strerror(errno);
231 adblogwrite("Error writing TWSTREAMHDR to adbd" + str.str() + "\n");
232 close_backup_fds();
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400233 return false;
bigbiffce8f83c2015-12-12 18:30:21 -0500234 }
235 fflush(adbd_fp);
236 }
237 //we will be writing an image from TWRP
238 else if (cmdtype == TWIMG) {
239 struct twfilehdr twimghdr;
240
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400241 adblogwrite("writing TWIMG\n");
bigbiff bigbiff56cf5642016-08-19 17:43:45 -0400242 digest.init();
bigbiffce8f83c2015-12-12 18:30:21 -0500243 memset(&twimghdr, 0, sizeof(twimghdr));
244 memcpy(&twimghdr, cmd, sizeof(cmd));
245 md5fnsize = twimghdr.size;
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400246 compressed = false;
bigbiffce8f83c2015-12-12 18:30:21 -0500247
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400248 if (fwrite(cmd, 1, sizeof(cmd), adbd_fp) != sizeof(cmd)) {
bigbiffce8f83c2015-12-12 18:30:21 -0500249 adblogwrite("Error writing TWIMG to adbd\n");
250 close_backup_fds();
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400251 return false;
bigbiffce8f83c2015-12-12 18:30:21 -0500252 }
253 fflush(adbd_fp);
254 writedata = true;
255 }
256 //we will be writing a tar from TWRP
257 else if (cmdtype == TWFN) {
258 struct twfilehdr twfilehdr;
259
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400260 adblogwrite("writing TWFN\n");
bigbiff bigbiff56cf5642016-08-19 17:43:45 -0400261 digest.init();
bigbiffce8f83c2015-12-12 18:30:21 -0500262
263 ADBSTRUCT_STATIC_ASSERT(sizeof(twfilehdr) == MAX_ADB_READ);
264
265 memset(&twfilehdr, 0, sizeof(twfilehdr));
266 memcpy(&twfilehdr, cmd, sizeof(cmd));
267 md5fnsize = twfilehdr.size;
268
269 compressed = twfilehdr.compressed == 1 ? true: false;
270
271 if (fwrite(cmd, 1, sizeof(cmd), adbd_fp) != sizeof(cmd)) {
272 adblogwrite("Error writing TWFN to adbd\n");
273 close_backup_fds();
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400274 return false;
bigbiffce8f83c2015-12-12 18:30:21 -0500275 }
276 fflush(adbd_fp);
277 writedata = true;
278 }
279 /*
280 We received the command that we are done with the file stream.
281 We will flush the remaining data stream.
282 Update md5 and write final results to adb stream.
283 If we need padding because the total bytes are not a multiple
284 of 512, we pad the end with 0s to we reach 512.
285 We also write the final md5 to the adb stream.
286 */
287 else if (cmdtype == TWEOF) {
288 adblogwrite("received TWEOF\n");
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400289 while ((bytes = read(adb_read_fd, &adbReadStream, sizeof(adbReadStream)) != 0)) {
bigbiffce8f83c2015-12-12 18:30:21 -0500290 totalbytes += bytes;
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400291 fileBytes += bytes;
292 dataChunkBytes += bytes;
293
294 char *writeAdbReadStream = new char [bytes];
295 memcpy(writeAdbReadStream, adbReadStream, bytes);
296
297 digest.update((unsigned char *) writeAdbReadStream, bytes);
298 if (fwrite(writeAdbReadStream, 1, bytes, adbd_fp) < 0) {
299 std::stringstream str;
300 str << strerror(errno);
301 adblogwrite("Cannot write to adbd stream: " + str.str() + "\n");
bigbiffce8f83c2015-12-12 18:30:21 -0500302 }
303 fflush(adbd_fp);
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400304 delete [] writeAdbReadStream;
305 memset(adbReadStream, 0, sizeof(adbReadStream));
bigbiffce8f83c2015-12-12 18:30:21 -0500306 }
307
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400308 count = fileBytes / DATA_MAX_CHUNK_SIZE + 1;
309 count = count * DATA_MAX_CHUNK_SIZE;
310
311 if (fileBytes % DATA_MAX_CHUNK_SIZE != 0) {
312 char padding[count - fileBytes];
313 int paddingBytes = sizeof(padding);
314 std::stringstream paddingStr;
315 paddingStr << paddingBytes;
316 memset(padding, 0, paddingBytes);
317 adblogwrite("writing padding to stream: " + paddingStr.str() + " bytes\n");
318 if (fwrite(padding, 1, paddingBytes, adbd_fp) != sizeof(padding)) {
bigbiffce8f83c2015-12-12 18:30:21 -0500319 adblogwrite("Error writing padding to adbd\n");
320 close_backup_fds();
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400321 return false;
bigbiffce8f83c2015-12-12 18:30:21 -0500322 }
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400323 totalbytes += paddingBytes;
324 digest.update((unsigned char *) padding, paddingBytes);
bigbiffce8f83c2015-12-12 18:30:21 -0500325 fflush(adbd_fp);
bigbiffce8f83c2015-12-12 18:30:21 -0500326 }
327
328 AdbBackupFileTrailer md5trailer;
329
330 memset(&md5trailer, 0, sizeof(md5trailer));
bigbiffce8f83c2015-12-12 18:30:21 -0500331
bigbiff bigbiff56cf5642016-08-19 17:43:45 -0400332 std::string md5string = digest.return_digest_string();
bigbiffce8f83c2015-12-12 18:30:21 -0500333
334 strncpy(md5trailer.start_of_trailer, TWRP, sizeof(md5trailer.start_of_trailer));
335 strncpy(md5trailer.type, MD5TRAILER, sizeof(md5trailer.type));
336 strncpy(md5trailer.md5, md5string.c_str(), sizeof(md5trailer.md5));
337
338 md5trailer.crc = crc32(0L, Z_NULL, 0);
339 md5trailer.crc = crc32(md5trailer.crc, (const unsigned char*) &md5trailer, sizeof(md5trailer));
340
341 md5trailer.ident = crc32(0L, Z_NULL, 0);
342 md5trailer.ident = crc32(md5trailer.ident, (const unsigned char*) &md5trailer, sizeof(md5trailer));
343 md5trailer.ident = crc32(md5trailer.ident, (const unsigned char*) &md5fnsize, sizeof(md5fnsize));
344
345 if (fwrite(&md5trailer, 1, sizeof(md5trailer), adbd_fp) != sizeof(md5trailer)) {
346 adblogwrite("Error writing md5trailer to adbd\n");
347 close_backup_fds();
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400348 return false;
bigbiffce8f83c2015-12-12 18:30:21 -0500349 }
350 fflush(adbd_fp);
351 writedata = false;
352 firstDataPacket = true;
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400353 fileBytes = 0;
bigbiffce8f83c2015-12-12 18:30:21 -0500354 }
355 memset(&cmd, 0, sizeof(cmd));
356 }
357 //If we are to write data because of a new file stream, lets write all the data.
358 //This will allow us to not write data after a command structure has been written
359 //to the adb stream.
360 //If the stream is compressed, we need to always write the data.
361 if (writedata || compressed) {
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400362 while ((bytes = read(adb_read_fd, &adbReadStream, sizeof(adbReadStream))) > 0) {
bigbiffce8f83c2015-12-12 18:30:21 -0500363 if (firstDataPacket) {
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400364 if (!twadbbu::Write_TWDATA(adbd_fp)) {
bigbiffce8f83c2015-12-12 18:30:21 -0500365 close_backup_fds();
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400366 return false;
bigbiffce8f83c2015-12-12 18:30:21 -0500367 }
368 fflush(adbd_fp);
369 firstDataPacket = false;
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400370 dataChunkBytes += sizeof(adbReadStream);
bigbiffce8f83c2015-12-12 18:30:21 -0500371 }
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400372 char *writeAdbReadStream = new char [bytes];
373 memcpy(writeAdbReadStream, adbReadStream, bytes);
bigbiffce8f83c2015-12-12 18:30:21 -0500374
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400375 digest.update((unsigned char *) writeAdbReadStream, bytes);
bigbiffce8f83c2015-12-12 18:30:21 -0500376
377 totalbytes += bytes;
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400378 fileBytes += bytes;
bigbiffce8f83c2015-12-12 18:30:21 -0500379 dataChunkBytes += bytes;
380
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400381 if (fwrite(writeAdbReadStream, 1, bytes, adbd_fp) != bytes) {
bigbiffce8f83c2015-12-12 18:30:21 -0500382 adblogwrite("Error writing backup data to adbd\n");
383 close_backup_fds();
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400384 return false;
bigbiffce8f83c2015-12-12 18:30:21 -0500385 }
386 fflush(adbd_fp);
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400387 delete [] writeAdbReadStream;
bigbiffce8f83c2015-12-12 18:30:21 -0500388
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400389 memset(&adbReadStream, 0, sizeof(adbReadStream));
bigbiffce8f83c2015-12-12 18:30:21 -0500390
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400391 if (dataChunkBytes == DATA_MAX_CHUNK_SIZE) {
392 dataChunkBytes = 0;
393 firstDataPacket = true;
394 }
395 else if (dataChunkBytes > (DATA_MAX_CHUNK_SIZE - sizeof(adbReadStream))) {
396 int bytesLeft = DATA_MAX_CHUNK_SIZE - dataChunkBytes;
397 char extraData[bytesLeft];
398
399 memset(&extraData, 0, bytesLeft);
400 while ((bytes = read(adb_read_fd, &extraData, bytesLeft)) != 0) {
401 if (bytes > 0) {
402 totalbytes += bytes;
403 fileBytes += bytes;
404 dataChunkBytes += bytes;
405
406 bytesLeft -= bytes;
407 char *writeAdbReadStream = new char [bytes];
408 memcpy(writeAdbReadStream, extraData, bytes);
409
410 digest.update((unsigned char *) writeAdbReadStream, bytes);
411 if (fwrite(writeAdbReadStream, 1, bytes, adbd_fp) < 0) {
412 std::stringstream str;
413 str << strerror(errno);
414 adblogwrite("Cannot write to adbd stream: " + str.str() + "\n");
415 close_restore_fds();
416 return false;
417 }
418 fflush(adbd_fp);
419 delete [] writeAdbReadStream;
420 }
421 memset(&extraData, 0, bytesLeft);
422 if (bytesLeft == 0) {
423 break;
424 }
bigbiffce8f83c2015-12-12 18:30:21 -0500425 }
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400426
bigbiffce8f83c2015-12-12 18:30:21 -0500427 fflush(adbd_fp);
428 dataChunkBytes = 0;
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400429 firstDataPacket = true;
bigbiffce8f83c2015-12-12 18:30:21 -0500430 }
bigbiffce8f83c2015-12-12 18:30:21 -0500431 }
bigbiffce8f83c2015-12-12 18:30:21 -0500432 }
433 }
434
435 //Write the final end adb structure to the adb stream
436 if (fwrite(&endadb, 1, sizeof(endadb), adbd_fp) != sizeof(endadb)) {
437 adblogwrite("Error writing endadb to adbd\n");
438 close_backup_fds();
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400439 return false;
bigbiffce8f83c2015-12-12 18:30:21 -0500440 }
441 fflush(adbd_fp);
442 close_backup_fds();
443 return 0;
444}
445
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400446bool twrpback::restore(void) {
bigbiff bigbiff56cf5642016-08-19 17:43:45 -0400447 twrpMD5 digest;
448 char cmd[MAX_ADB_READ];
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400449 char readAdbStream[MAX_ADB_READ];
bigbiffce8f83c2015-12-12 18:30:21 -0500450 struct AdbBackupControlType structcmd;
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400451 int errctr = 0;
bigbiffce8f83c2015-12-12 18:30:21 -0500452 uint64_t totalbytes = 0, dataChunkBytes = 0;
453 uint64_t md5fnsize = 0;
454 bool writedata, read_from_adb;
455 bool breakloop, eofsent, md5trsent;
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400456 bool compressed;
457 bool md5TrailerReceived = false;
bigbiffce8f83c2015-12-12 18:30:21 -0500458
459 breakloop = false;
460 read_from_adb = true;
461
462 signal(SIGPIPE, SIG_IGN);
463
464 adbd_fp = fdopen(adbd_fd, "r");
465 if (adbd_fp == NULL) {
466 adblogwrite("Unable to open adb_fp\n");
467 close_restore_fds();
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400468 return false;
bigbiffce8f83c2015-12-12 18:30:21 -0500469 }
470
471 if(mkfifo(TW_ADB_RESTORE, 0666)) {
472 adblogwrite("Unable to create TW_ADB_RESTORE fifo\n");
473 close_restore_fds();
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400474 return false;
bigbiffce8f83c2015-12-12 18:30:21 -0500475 }
476
bigbiff bigbiff19fb79c2016-09-05 21:04:51 -0400477 adblogwrite("opening TW_ADB_FIFO\n");
478 write_fd = open(TW_ADB_FIFO, O_WRONLY);
bigbiffce8f83c2015-12-12 18:30:21 -0500479
480 while (write_fd < 0) {
bigbiff bigbiff19fb79c2016-09-05 21:04:51 -0400481 write_fd = open(TW_ADB_FIFO, O_WRONLY);
bigbiffce8f83c2015-12-12 18:30:21 -0500482 errctr++;
483 if (errctr > ADB_BU_MAX_ERROR) {
bigbiff bigbiff19fb79c2016-09-05 21:04:51 -0400484 adblogwrite("Unable to open TW_ADB_FIFO\n");
bigbiffce8f83c2015-12-12 18:30:21 -0500485 close_restore_fds();
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400486 return false;
bigbiffce8f83c2015-12-12 18:30:21 -0500487 }
488 }
489
Ayke van Laethem05c2de42017-06-02 00:19:27 +0200490 memset(operation, 0, sizeof(operation));
bigbiffce8f83c2015-12-12 18:30:21 -0500491 sprintf(operation, "adbrestore");
492 if (write(write_fd, operation, sizeof(operation)) != sizeof(operation)) {
bigbiff bigbiff19fb79c2016-09-05 21:04:51 -0400493 adblogwrite("Unable to write to TW_ADB_FIFO\n");
bigbiffce8f83c2015-12-12 18:30:21 -0500494 close_restore_fds();
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400495 return false;
bigbiffce8f83c2015-12-12 18:30:21 -0500496 }
497
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400498 memset(&readAdbStream, 0, sizeof(readAdbStream));
bigbiffce8f83c2015-12-12 18:30:21 -0500499 memset(&cmd, 0, sizeof(cmd));
500
501 adblogwrite("opening TW_ADB_BU_CONTROL\n");
502 adb_control_bu_fd = open(TW_ADB_BU_CONTROL, O_RDONLY | O_NONBLOCK);
503 if (adb_control_bu_fd < 0) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600504 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500505 str << strerror(errno);
506 adblogwrite("Unable to open TW_ADB_BU_CONTROL for writing. " + str.str() + "\n");
507 close_restore_fds();
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400508 return false;
bigbiffce8f83c2015-12-12 18:30:21 -0500509 }
510
511 adblogwrite("opening TW_ADB_TWRP_CONTROL\n");
512 adb_control_twrp_fd = open(TW_ADB_TWRP_CONTROL, O_WRONLY | O_NONBLOCK);
513 if (adb_control_twrp_fd < 0) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600514 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500515 str << strerror(errno);
516 adblogwrite("Unable to open TW_ADB_TWRP_CONTROL for writing. " + str.str() + ". Retrying...\n");
517 while (adb_control_twrp_fd < 0) {
518 adb_control_twrp_fd = open(TW_ADB_TWRP_CONTROL, O_WRONLY | O_NONBLOCK);
519 usleep(10000);
520 errctr++;
521 if (errctr > ADB_BU_MAX_ERROR) {
522 adblogwrite("Unable to open TW_ADB_TWRP_CONTROL\n");
523 close_backup_fds();
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400524 return false;
bigbiffce8f83c2015-12-12 18:30:21 -0500525 }
526 }
527 }
528
529 //Loop until we receive TWENDADB from TWRP
530 while (!breakloop) {
531 memset(&cmd, 0, sizeof(cmd));
532 if (read(adb_control_bu_fd, &cmd, sizeof(cmd)) > 0) {
533 struct AdbBackupControlType structcmd;
534 memcpy(&structcmd, cmd, sizeof(cmd));
Ayke van Laethem05c2de42017-06-02 00:19:27 +0200535 std::string cmdtype = structcmd.get_type();
bigbiffce8f83c2015-12-12 18:30:21 -0500536
537 //If we receive TWEOF from TWRP close adb data fifo
538 if (cmdtype == TWEOF) {
539 adblogwrite("Received TWEOF\n");
540 struct AdbBackupControlType tweof;
541
542 memset(&tweof, 0, sizeof(tweof));
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400543 memcpy(&tweof, readAdbStream, sizeof(readAdbStream));
bigbiffce8f83c2015-12-12 18:30:21 -0500544 read_from_adb = true;
545 }
546 //Break when TWRP sends TWENDADB
547 else if (cmdtype == TWENDADB) {
548 adblogwrite("Received TWENDADB\n");
549 breakloop = true;
550 close_restore_fds();
551 }
552 //we received an error, exit and unlink
553 else if (cmdtype == TWERROR) {
554 adblogwrite("Error received. Quitting...\n");
555 close_restore_fds();
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400556 return false;
bigbiffce8f83c2015-12-12 18:30:21 -0500557 }
558 }
bigbiffce8f83c2015-12-12 18:30:21 -0500559 //If we should read from the adb stream, write commands and data to TWRP
560 if (read_from_adb) {
bigbiffce8f83c2015-12-12 18:30:21 -0500561 int readbytes;
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400562 if ((readbytes = fread(readAdbStream, 1, sizeof(readAdbStream), adbd_fp)) == sizeof(readAdbStream)) {
563 memcpy(&structcmd, readAdbStream, sizeof(readAdbStream));
Ayke van Laethem05c2de42017-06-02 00:19:27 +0200564 std::string cmdtype = structcmd.get_type();
bigbiffce8f83c2015-12-12 18:30:21 -0500565
566 //Tell TWRP we have read the entire adb stream
567 if (cmdtype == TWENDADB) {
568 struct AdbBackupControlType endadb;
569 uint32_t crc, endadbcrc;
570
bigbiffce8f83c2015-12-12 18:30:21 -0500571 memset(&endadb, 0, sizeof(endadb));
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400572 memcpy(&endadb, readAdbStream, sizeof(readAdbStream));
bigbiffce8f83c2015-12-12 18:30:21 -0500573 endadbcrc = endadb.crc;
574 memset(&endadb.crc, 0, sizeof(endadb.crc));
575 crc = crc32(0L, Z_NULL, 0);
576 crc = crc32(crc, (const unsigned char*) &endadb, sizeof(endadb));
577
578 if (crc == endadbcrc) {
579 adblogwrite("Sending TWENDADB\n");
580 if (write(adb_control_twrp_fd, &endadb, sizeof(endadb)) < 1) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600581 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500582 str << strerror(errno);
583 adblogwrite("Cannot write to ADB_CONTROL_READ_FD: " + str.str() + "\n");
584 close_restore_fds();
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400585 return false;
bigbiffce8f83c2015-12-12 18:30:21 -0500586 }
bigbiff bigbiffb5ecaad2017-03-20 18:53:53 -0400587 read_from_adb = false;
bigbiffce8f83c2015-12-12 18:30:21 -0500588 }
589 else {
590 adblogwrite("ADB TWENDADB crc header doesn't match\n");
591 close_restore_fds();
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400592 return false;
bigbiffce8f83c2015-12-12 18:30:21 -0500593 }
594 }
595 //Send TWRP partition metadata
596 else if (cmdtype == TWSTREAMHDR) {
597 struct AdbBackupStreamHeader cnthdr;
598 uint32_t crc, cnthdrcrc;
599
600 ADBSTRUCT_STATIC_ASSERT(sizeof(cnthdr) == MAX_ADB_READ);
bigbiffce8f83c2015-12-12 18:30:21 -0500601
602 memset(&cnthdr, 0, sizeof(cnthdr));
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400603 memcpy(&cnthdr, readAdbStream, sizeof(readAdbStream));
bigbiffce8f83c2015-12-12 18:30:21 -0500604 cnthdrcrc = cnthdr.crc;
605 memset(&cnthdr.crc, 0, sizeof(cnthdr.crc));
606 crc = crc32(0L, Z_NULL, 0);
607 crc = crc32(crc, (const unsigned char*) &cnthdr, sizeof(cnthdr));
608
609 if (crc == cnthdrcrc) {
610 adblogwrite("Restoring TWSTREAMHDR\n");
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400611 if (write(adb_control_twrp_fd, readAdbStream, sizeof(readAdbStream)) < 0) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600612 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500613 str << strerror(errno);
614 adblogwrite("Cannot write to adb_control_twrp_fd: " + str.str() + "\n");
615 close_restore_fds();
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400616 return false;
bigbiffce8f83c2015-12-12 18:30:21 -0500617 }
618 }
619 else {
620 adblogwrite("ADB TWSTREAMHDR crc header doesn't match\n");
621 close_restore_fds();
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400622 return false;
bigbiffce8f83c2015-12-12 18:30:21 -0500623 }
624 }
625 //Tell TWRP we are sending a partition image
626 else if (cmdtype == TWIMG) {
627 struct twfilehdr twimghdr;
628 uint32_t crc, twimghdrcrc;
629
bigbiff bigbiff56cf5642016-08-19 17:43:45 -0400630 digest.init();
bigbiffce8f83c2015-12-12 18:30:21 -0500631 adblogwrite("Restoring TWIMG\n");
632 memset(&twimghdr, 0, sizeof(twimghdr));
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400633 memcpy(&twimghdr, readAdbStream, sizeof(readAdbStream));
bigbiffce8f83c2015-12-12 18:30:21 -0500634 md5fnsize = twimghdr.size;
635 twimghdrcrc = twimghdr.crc;
636 memset(&twimghdr.crc, 0, sizeof(twimghdr.crc));
637
638 crc = crc32(0L, Z_NULL, 0);
639 crc = crc32(crc, (const unsigned char*) &twimghdr, sizeof(twimghdr));
640 if (crc == twimghdrcrc) {
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400641 if (write(adb_control_twrp_fd, readAdbStream, sizeof(readAdbStream)) < 1) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600642 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500643 str << strerror(errno);
644 adblogwrite("Cannot write to adb_control_twrp_fd: " + str.str() + "\n");
645 close_restore_fds();
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400646 return false;
bigbiffce8f83c2015-12-12 18:30:21 -0500647 }
648 }
649 else {
650 adblogwrite("ADB TWIMG crc header doesn't match\n");
651 close_restore_fds();
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400652 return false;
bigbiffce8f83c2015-12-12 18:30:21 -0500653 }
654 adblogwrite("opening TW_ADB_RESTORE\n");
655 adb_write_fd = open(TW_ADB_RESTORE, O_WRONLY);
656 }
657 //Tell TWRP we are sending a tar stream
658 else if (cmdtype == TWFN) {
659 struct twfilehdr twfilehdr;
660 uint32_t crc, twfilehdrcrc;
661
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400662 digest.init();
bigbiffce8f83c2015-12-12 18:30:21 -0500663 adblogwrite("Restoring TWFN\n");
664 memset(&twfilehdr, 0, sizeof(twfilehdr));
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400665 memcpy(&twfilehdr, readAdbStream, sizeof(readAdbStream));
bigbiffce8f83c2015-12-12 18:30:21 -0500666 md5fnsize = twfilehdr.size;
667 twfilehdrcrc = twfilehdr.crc;
668 memset(&twfilehdr.crc, 0, sizeof(twfilehdr.crc));
669
670 crc = crc32(0L, Z_NULL, 0);
671 crc = crc32(crc, (const unsigned char*) &twfilehdr, sizeof(twfilehdr));
672
673 if (crc == twfilehdrcrc) {
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400674 if (write(adb_control_twrp_fd, readAdbStream, sizeof(readAdbStream)) < 1) {
Matt Mowercc19c6f2017-02-22 11:31:35 -0600675 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500676 str << strerror(errno);
677 adblogwrite("Cannot write to adb_control_twrp_fd: " + str.str() + "\n");
678 close_restore_fds();
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400679 return false;
bigbiffce8f83c2015-12-12 18:30:21 -0500680 }
681 }
682 else {
683 adblogwrite("ADB TWFN crc header doesn't match\n");
684 close_restore_fds();
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400685 return false;
bigbiffce8f83c2015-12-12 18:30:21 -0500686 }
687
688 adblogwrite("opening TW_ADB_RESTORE\n");
689 adb_write_fd = open(TW_ADB_RESTORE, O_WRONLY);
690 }
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400691 else if (cmdtype == MD5TRAILER) {
692 read_from_adb = false; //don't read from adb until TWRP sends TWEOF
693 close(adb_write_fd);
694 md5TrailerReceived = true;
695 if (!checkMD5Trailer(readAdbStream, md5fnsize, &digest)) {
696 close_restore_fds();
697 return false;
698 }
699 }
bigbiffce8f83c2015-12-12 18:30:21 -0500700 //Send the tar or partition image md5 to TWRP
701 else if (cmdtype == TWDATA) {
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400702 dataChunkBytes += sizeof(readAdbStream);
bigbiffce8f83c2015-12-12 18:30:21 -0500703 while (1) {
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400704 if ((readbytes = fread(readAdbStream, 1, sizeof(readAdbStream), adbd_fp)) != sizeof(readAdbStream)) {
bigbiffce8f83c2015-12-12 18:30:21 -0500705 close_restore_fds();
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400706 return false;
bigbiffce8f83c2015-12-12 18:30:21 -0500707 }
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400708
709 memcpy(&structcmd, readAdbStream, sizeof(readAdbStream));
710
711 char *readAdbReadStream = new char [readbytes];
712 memcpy(readAdbReadStream, readAdbStream, readbytes);
Ayke van Laethem05c2de42017-06-02 00:19:27 +0200713 std::string cmdtype = structcmd.get_type();
bigbiffce8f83c2015-12-12 18:30:21 -0500714 dataChunkBytes += readbytes;
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400715 delete [] readAdbReadStream;
716 totalbytes += readbytes;
717 digest.update((unsigned char*)readAdbReadStream, readbytes);
bigbiffce8f83c2015-12-12 18:30:21 -0500718
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400719 if (cmdtype == MD5TRAILER) {
720 read_from_adb = false; //don't read from adb until TWRP sends TWEOF
721 close(adb_write_fd);
722 if (!checkMD5Trailer(readAdbStream, md5fnsize, &digest)) {
723 close_restore_fds();
724 return false;
bigbiffce8f83c2015-12-12 18:30:21 -0500725 }
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400726 break;
bigbiffce8f83c2015-12-12 18:30:21 -0500727 }
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400728
729
730 if (write(adb_write_fd, readAdbStream, sizeof(readAdbStream)) < 0) {
731 adblogwrite("end of stream reached.\n");
732 break;
733 }
734 if (dataChunkBytes == DATA_MAX_CHUNK_SIZE) {
bigbiffce8f83c2015-12-12 18:30:21 -0500735 dataChunkBytes = 0;
736 break;
737 }
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400738 memset(&readAdbStream, 0, sizeof(readAdbStream));
bigbiffce8f83c2015-12-12 18:30:21 -0500739 }
740 }
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400741 else {
742 if (!md5TrailerReceived) {
743 char *readAdbReadStream = new char [readbytes];
744 memcpy(readAdbReadStream, readAdbStream, readbytes);
745 digest.update((unsigned char*)readAdbReadStream, readbytes);
746 totalbytes += readbytes;
747 delete [] readAdbReadStream;
748 }
749
750 }
bigbiffce8f83c2015-12-12 18:30:21 -0500751 }
752 }
753 }
754
Matt Mowercc19c6f2017-02-22 11:31:35 -0600755 std::stringstream str;
bigbiffce8f83c2015-12-12 18:30:21 -0500756 str << totalbytes;
757 adblogwrite(str.str() + " bytes restored from adbbackup\n");
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400758 return true;
bigbiffce8f83c2015-12-12 18:30:21 -0500759}
760
bigbiff bigbiff19fb79c2016-09-05 21:04:51 -0400761void twrpback::streamFileForTWRP(void) {
762 adblogwrite("streamFileForTwrp" + streamFn + "\n");
763}
bigbiffce8f83c2015-12-12 18:30:21 -0500764
bigbiff bigbiff19fb79c2016-09-05 21:04:51 -0400765void twrpback::setStreamFileName(std::string fn) {
766 streamFn = fn;
767 adbd_fd = open(fn.c_str(), O_RDONLY);
768 if (adbd_fd < 0) {
769 adblogwrite("Unable to open adb_fd\n");
770 close(adbd_fd);
771 return;
bigbiffce8f83c2015-12-12 18:30:21 -0500772 }
bigbiff bigbiff19fb79c2016-09-05 21:04:51 -0400773 restore();
774}
bigbiffce8f83c2015-12-12 18:30:21 -0500775
bigbiff bigbiff19fb79c2016-09-05 21:04:51 -0400776void twrpback::threadStream(void) {
777 pthread_t thread;
778 ThreadPtr streamPtr = &twrpback::streamFileForTWRP;
779 PThreadPtr p = *(PThreadPtr*)&streamPtr;
780 pthread_create(&thread, NULL, p, this);
781 pthread_join(thread, NULL);
bigbiffce8f83c2015-12-12 18:30:21 -0500782}
bigbiff bigbiffadcb4d82017-09-25 10:51:56 -0400783
784bool twrpback::checkMD5Trailer(char readAdbStream[], uint64_t md5fnsize, twrpMD5 *digest) {
785 struct AdbBackupFileTrailer md5tr;
786 uint32_t crc, md5trcrc, md5ident, md5identmatch;
787
788 ADBSTRUCT_STATIC_ASSERT(sizeof(md5tr) == MAX_ADB_READ);
789 memset(&md5tr, 0, sizeof(md5tr));
790 memcpy(&md5tr, readAdbStream, MAX_ADB_READ);
791 md5ident = md5tr.ident;
792
793 memset(&md5tr.ident, 0, sizeof(md5tr.ident));
794
795 md5identmatch = crc32(0L, Z_NULL, 0);
796 md5identmatch = crc32(md5identmatch, (const unsigned char*) &md5tr, sizeof(md5tr));
797 md5identmatch = crc32(md5identmatch, (const unsigned char*) &md5fnsize, sizeof(md5fnsize));
798
799 if (md5identmatch == md5ident) {
800 adblogwrite("checking MD5TRAILER\n");
801 md5trcrc = md5tr.crc;
802 memset(&md5tr.crc, 0, sizeof(md5tr.crc));
803 crc = crc32(0L, Z_NULL, 0);
804 crc = crc32(crc, (const unsigned char*) &md5tr, sizeof(md5tr));
805 if (crc == md5trcrc) {
806 if (write(adb_control_twrp_fd, &md5tr, sizeof(md5tr)) < 1) {
807 std::stringstream str;
808 str << strerror(errno);
809 adblogwrite("Cannot write to adb_control_twrp_fd: " + str.str() + "\n");
810 close_restore_fds();
811 return false;
812 }
813 }
814 else {
815 adblogwrite("ADB MD5TRAILER crc header doesn't match\n");
816 close_restore_fds();
817 return false;
818 }
819
820 AdbBackupFileTrailer md5;
821
822 memset(&md5, 0, sizeof(md5));
823 strncpy(md5.start_of_trailer, TWRP, sizeof(md5.start_of_trailer));
824 strncpy(md5.type, TWMD5, sizeof(md5.type));
825 std::string md5string = digest->return_digest_string();
826 strncpy(md5.md5, md5string.c_str(), sizeof(md5.md5));
827
828 adblogwrite("sending MD5 verification\n");
829 std::stringstream dstr;
830 dstr << adb_control_twrp_fd;
831 if (write(adb_control_twrp_fd, &md5, sizeof(md5)) < 1) {
832 std::stringstream str;
833 str << strerror(errno);
834 adblogwrite("Cannot write to adb_control_twrp_fd: " + str.str() + "\n");
835 close_restore_fds();
836 return false;
837 }
838 return true;
839 }
840 return false;
841}