• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "applypatch/applypatch.h"
18 
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <libgen.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/stat.h>
26 #include <sys/statfs.h>
27 #include <sys/types.h>
28 #include <unistd.h>
29 
30 #include <functional>
31 #include <memory>
32 #include <string>
33 #include <utility>
34 #include <vector>
35 
36 #include <android-base/logging.h>
37 #include <android-base/parseint.h>
38 #include <android-base/strings.h>
39 #include <openssl/sha.h>
40 
41 #include "edify/expr.h"
42 #include "ota_io.h"
43 #include "print_sha1.h"
44 
45 static int LoadPartitionContents(const std::string& filename, FileContents* file);
46 static size_t FileSink(const unsigned char* data, size_t len, int fd);
47 static int GenerateTarget(const FileContents& source_file, const std::unique_ptr<Value>& patch,
48                           const std::string& target_filename,
49                           const uint8_t target_sha1[SHA_DIGEST_LENGTH], const Value* bonus_data);
50 
51 // Read a file into memory; store the file contents and associated metadata in *file.
52 // Return 0 on success.
LoadFileContents(const char * filename,FileContents * file)53 int LoadFileContents(const char* filename, FileContents* file) {
54   // A special 'filename' beginning with "EMMC:" means to load the contents of a partition.
55   if (strncmp(filename, "EMMC:", 5) == 0) {
56     return LoadPartitionContents(filename, file);
57   }
58 
59   if (stat(filename, &file->st) == -1) {
60     printf("failed to stat \"%s\": %s\n", filename, strerror(errno));
61     return -1;
62   }
63 
64   std::vector<unsigned char> data(file->st.st_size);
65   unique_file f(ota_fopen(filename, "rb"));
66   if (!f) {
67     printf("failed to open \"%s\": %s\n", filename, strerror(errno));
68     return -1;
69   }
70 
71   size_t bytes_read = ota_fread(data.data(), 1, data.size(), f.get());
72   if (bytes_read != data.size()) {
73     printf("short read of \"%s\" (%zu bytes of %zu)\n", filename, bytes_read, data.size());
74     return -1;
75   }
76   file->data = std::move(data);
77   SHA1(file->data.data(), file->data.size(), file->sha1);
78   return 0;
79 }
80 
81 // Load the contents of an EMMC partition into the provided
82 // FileContents.  filename should be a string of the form
83 // "EMMC:<partition_device>:...".  The smallest size_n bytes for
84 // which that prefix of the partition contents has the corresponding
85 // sha1 hash will be loaded.  It is acceptable for a size value to be
86 // repeated with different sha1s.  Will return 0 on success.
87 //
88 // This complexity is needed because if an OTA installation is
89 // interrupted, the partition might contain either the source or the
90 // target data, which might be of different lengths.  We need to know
91 // the length in order to read from a partition (there is no
92 // "end-of-file" marker), so the caller must specify the possible
93 // lengths and the hash of the data, and we'll do the load expecting
94 // to find one of those hashes.
LoadPartitionContents(const std::string & filename,FileContents * file)95 static int LoadPartitionContents(const std::string& filename, FileContents* file) {
96   std::vector<std::string> pieces = android::base::Split(filename, ":");
97   if (pieces.size() < 4 || pieces.size() % 2 != 0 || pieces[0] != "EMMC") {
98     printf("LoadPartitionContents called with bad filename \"%s\"\n", filename.c_str());
99     return -1;
100   }
101 
102   size_t pair_count = (pieces.size() - 2) / 2;  // # of (size, sha1) pairs in filename
103   std::vector<std::pair<size_t, std::string>> pairs;
104   for (size_t i = 0; i < pair_count; ++i) {
105     size_t size;
106     if (!android::base::ParseUint(pieces[i * 2 + 2], &size) || size == 0) {
107       printf("LoadPartitionContents called with bad size \"%s\"\n", pieces[i * 2 + 2].c_str());
108       return -1;
109     }
110     pairs.push_back({ size, pieces[i * 2 + 3] });
111   }
112 
113   // Sort the pairs array so that they are in order of increasing size.
114   std::sort(pairs.begin(), pairs.end());
115 
116   const char* partition = pieces[1].c_str();
117   unique_file dev(ota_fopen(partition, "rb"));
118   if (!dev) {
119     printf("failed to open emmc partition \"%s\": %s\n", partition, strerror(errno));
120     return -1;
121   }
122 
123   SHA_CTX sha_ctx;
124   SHA1_Init(&sha_ctx);
125 
126   // Allocate enough memory to hold the largest size.
127   std::vector<unsigned char> buffer(pairs[pair_count - 1].first);
128   unsigned char* buffer_ptr = buffer.data();
129   size_t buffer_size = 0;  // # bytes read so far
130   bool found = false;
131 
132   for (const auto& pair : pairs) {
133     size_t current_size = pair.first;
134     const std::string& current_sha1 = pair.second;
135 
136     // Read enough additional bytes to get us up to the next size. (Again,
137     // we're trying the possibilities in order of increasing size).
138     size_t next = current_size - buffer_size;
139     if (next > 0) {
140       size_t read = ota_fread(buffer_ptr, 1, next, dev.get());
141       if (next != read) {
142         printf("short read (%zu bytes of %zu) for partition \"%s\"\n", read, next, partition);
143         return -1;
144       }
145       SHA1_Update(&sha_ctx, buffer_ptr, read);
146       buffer_size += read;
147       buffer_ptr += read;
148     }
149 
150     // Duplicate the SHA context and finalize the duplicate so we can
151     // check it against this pair's expected hash.
152     SHA_CTX temp_ctx;
153     memcpy(&temp_ctx, &sha_ctx, sizeof(SHA_CTX));
154     uint8_t sha_so_far[SHA_DIGEST_LENGTH];
155     SHA1_Final(sha_so_far, &temp_ctx);
156 
157     uint8_t parsed_sha[SHA_DIGEST_LENGTH];
158     if (ParseSha1(current_sha1.c_str(), parsed_sha) != 0) {
159       printf("failed to parse SHA-1 %s in %s\n", current_sha1.c_str(), filename.c_str());
160       return -1;
161     }
162 
163     if (memcmp(sha_so_far, parsed_sha, SHA_DIGEST_LENGTH) == 0) {
164       // We have a match. Stop reading the partition; we'll return the data we've read so far.
165       printf("partition read matched size %zu SHA-1 %s\n", current_size, current_sha1.c_str());
166       found = true;
167       break;
168     }
169   }
170 
171   if (!found) {
172     // Ran off the end of the list of (size, sha1) pairs without finding a match.
173     printf("contents of partition \"%s\" didn't match %s\n", partition, filename.c_str());
174     return -1;
175   }
176 
177   SHA1_Final(file->sha1, &sha_ctx);
178 
179   buffer.resize(buffer_size);
180   file->data = std::move(buffer);
181   // Fake some stat() info.
182   file->st.st_mode = 0644;
183   file->st.st_uid = 0;
184   file->st.st_gid = 0;
185 
186   return 0;
187 }
188 
189 // Save the contents of the given FileContents object under the given
190 // filename.  Return 0 on success.
SaveFileContents(const char * filename,const FileContents * file)191 int SaveFileContents(const char* filename, const FileContents* file) {
192   unique_fd fd(ota_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, S_IRUSR | S_IWUSR));
193   if (fd == -1) {
194     printf("failed to open \"%s\" for write: %s\n", filename, strerror(errno));
195     return -1;
196   }
197 
198   size_t bytes_written = FileSink(file->data.data(), file->data.size(), fd);
199   if (bytes_written != file->data.size()) {
200     printf("short write of \"%s\" (%zd bytes of %zu): %s\n", filename, bytes_written,
201            file->data.size(), strerror(errno));
202     return -1;
203   }
204   if (ota_fsync(fd) != 0) {
205     printf("fsync of \"%s\" failed: %s\n", filename, strerror(errno));
206     return -1;
207   }
208   if (ota_close(fd) != 0) {
209     printf("close of \"%s\" failed: %s\n", filename, strerror(errno));
210     return -1;
211   }
212 
213   if (chmod(filename, file->st.st_mode) != 0) {
214     printf("chmod of \"%s\" failed: %s\n", filename, strerror(errno));
215     return -1;
216   }
217   if (chown(filename, file->st.st_uid, file->st.st_gid) != 0) {
218     printf("chown of \"%s\" failed: %s\n", filename, strerror(errno));
219     return -1;
220   }
221 
222   return 0;
223 }
224 
225 // Write a memory buffer to 'target' partition, a string of the form
226 // "EMMC:<partition_device>[:...]". The target name
227 // might contain multiple colons, but WriteToPartition() only uses the first
228 // two and ignores the rest. Return 0 on success.
WriteToPartition(const unsigned char * data,size_t len,const std::string & target)229 int WriteToPartition(const unsigned char* data, size_t len, const std::string& target) {
230   std::vector<std::string> pieces = android::base::Split(target, ":");
231   if (pieces.size() < 2 || pieces[0] != "EMMC") {
232     printf("WriteToPartition called with bad target (%s)\n", target.c_str());
233     return -1;
234   }
235 
236   const char* partition = pieces[1].c_str();
237   unique_fd fd(ota_open(partition, O_RDWR));
238   if (fd == -1) {
239     printf("failed to open %s: %s\n", partition, strerror(errno));
240     return -1;
241   }
242 
243   size_t start = 0;
244   bool success = false;
245   for (size_t attempt = 0; attempt < 2; ++attempt) {
246     if (TEMP_FAILURE_RETRY(lseek(fd, start, SEEK_SET)) == -1) {
247       printf("failed seek on %s: %s\n", partition, strerror(errno));
248       return -1;
249     }
250     while (start < len) {
251       size_t to_write = len - start;
252       if (to_write > 1 << 20) to_write = 1 << 20;
253 
254       ssize_t written = TEMP_FAILURE_RETRY(ota_write(fd, data + start, to_write));
255       if (written == -1) {
256         printf("failed write writing to %s: %s\n", partition, strerror(errno));
257         return -1;
258       }
259       start += written;
260     }
261 
262     if (ota_fsync(fd) != 0) {
263       printf("failed to sync to %s: %s\n", partition, strerror(errno));
264       return -1;
265     }
266     if (ota_close(fd) != 0) {
267       printf("failed to close %s: %s\n", partition, strerror(errno));
268       return -1;
269     }
270 
271     fd.reset(ota_open(partition, O_RDONLY));
272     if (fd == -1) {
273       printf("failed to reopen %s for verify: %s\n", partition, strerror(errno));
274       return -1;
275     }
276 
277     // Drop caches so our subsequent verification read won't just be reading the cache.
278     sync();
279     unique_fd dc(ota_open("/proc/sys/vm/drop_caches", O_WRONLY));
280     if (TEMP_FAILURE_RETRY(ota_write(dc, "3\n", 2)) == -1) {
281       printf("write to /proc/sys/vm/drop_caches failed: %s\n", strerror(errno));
282     } else {
283       printf("  caches dropped\n");
284     }
285     ota_close(dc);
286     sleep(1);
287 
288     // Verify.
289     if (TEMP_FAILURE_RETRY(lseek(fd, 0, SEEK_SET)) == -1) {
290       printf("failed to seek back to beginning of %s: %s\n", partition, strerror(errno));
291       return -1;
292     }
293 
294     unsigned char buffer[4096];
295     start = len;
296     for (size_t p = 0; p < len; p += sizeof(buffer)) {
297       size_t to_read = len - p;
298       if (to_read > sizeof(buffer)) {
299         to_read = sizeof(buffer);
300       }
301 
302       size_t so_far = 0;
303       while (so_far < to_read) {
304         ssize_t read_count = TEMP_FAILURE_RETRY(ota_read(fd, buffer + so_far, to_read - so_far));
305         if (read_count == -1) {
306           printf("verify read error %s at %zu: %s\n", partition, p, strerror(errno));
307           return -1;
308         } else if (read_count == 0) {
309           printf("verify read reached unexpected EOF, %s at %zu\n", partition, p);
310           return -1;
311         }
312         if (static_cast<size_t>(read_count) < to_read) {
313           printf("short verify read %s at %zu: %zd %zu\n", partition, p, read_count, to_read);
314         }
315         so_far += read_count;
316       }
317 
318       if (memcmp(buffer, data + p, to_read) != 0) {
319         printf("verification failed starting at %zu\n", p);
320         start = p;
321         break;
322       }
323     }
324 
325     if (start == len) {
326       printf("verification read succeeded (attempt %zu)\n", attempt + 1);
327       success = true;
328       break;
329     }
330 
331     if (ota_close(fd) != 0) {
332       printf("failed to close %s: %s\n", partition, strerror(errno));
333       return -1;
334     }
335 
336     fd.reset(ota_open(partition, O_RDWR));
337     if (fd == -1) {
338       printf("failed to reopen %s for retry write && verify: %s\n", partition, strerror(errno));
339       return -1;
340     }
341   }
342 
343   if (!success) {
344     printf("failed to verify after all attempts\n");
345     return -1;
346   }
347 
348   if (ota_close(fd) == -1) {
349     printf("error closing %s: %s\n", partition, strerror(errno));
350     return -1;
351   }
352   sync();
353 
354   return 0;
355 }
356 
357 // Take a string 'str' of 40 hex digits and parse it into the 20
358 // byte array 'digest'.  'str' may contain only the digest or be of
359 // the form "<digest>:<anything>".  Return 0 on success, -1 on any
360 // error.
ParseSha1(const char * str,uint8_t * digest)361 int ParseSha1(const char* str, uint8_t* digest) {
362     const char* ps = str;
363     uint8_t* pd = digest;
364     for (int i = 0; i < SHA_DIGEST_LENGTH * 2; ++i, ++ps) {
365         int digit;
366         if (*ps >= '0' && *ps <= '9') {
367             digit = *ps - '0';
368         } else if (*ps >= 'a' && *ps <= 'f') {
369             digit = *ps - 'a' + 10;
370         } else if (*ps >= 'A' && *ps <= 'F') {
371             digit = *ps - 'A' + 10;
372         } else {
373             return -1;
374         }
375         if (i % 2 == 0) {
376             *pd = digit << 4;
377         } else {
378             *pd |= digit;
379             ++pd;
380         }
381     }
382     if (*ps != '\0') return -1;
383     return 0;
384 }
385 
386 // Search an array of sha1 strings for one matching the given sha1.
387 // Return the index of the match on success, or -1 if no match is
388 // found.
FindMatchingPatch(uint8_t * sha1,const std::vector<std::string> & patch_sha1_str)389 static int FindMatchingPatch(uint8_t* sha1, const std::vector<std::string>& patch_sha1_str) {
390   for (size_t i = 0; i < patch_sha1_str.size(); ++i) {
391     uint8_t patch_sha1[SHA_DIGEST_LENGTH];
392     if (ParseSha1(patch_sha1_str[i].c_str(), patch_sha1) == 0 &&
393         memcmp(patch_sha1, sha1, SHA_DIGEST_LENGTH) == 0) {
394       return i;
395     }
396   }
397   return -1;
398 }
399 
400 // Returns 0 if the contents of the file (argv[2]) or the cached file
401 // match any of the sha1's on the command line (argv[3:]).  Returns
402 // nonzero otherwise.
applypatch_check(const char * filename,const std::vector<std::string> & patch_sha1_str)403 int applypatch_check(const char* filename, const std::vector<std::string>& patch_sha1_str) {
404   FileContents file;
405 
406   // It's okay to specify no sha1s; the check will pass if the
407   // LoadFileContents is successful.  (Useful for reading
408   // partitions, where the filename encodes the sha1s; no need to
409   // check them twice.)
410   if (LoadFileContents(filename, &file) != 0 ||
411       (!patch_sha1_str.empty() && FindMatchingPatch(file.sha1, patch_sha1_str) < 0)) {
412     printf("file \"%s\" doesn't have any of expected sha1 sums; checking cache\n", filename);
413 
414     // If the source file is missing or corrupted, it might be because
415     // we were killed in the middle of patching it.  A copy of it
416     // should have been made in CACHE_TEMP_SOURCE.  If that file
417     // exists and matches the sha1 we're looking for, the check still
418     // passes.
419     if (LoadFileContents(CACHE_TEMP_SOURCE, &file) != 0) {
420       printf("failed to load cache file\n");
421       return 1;
422     }
423 
424     if (FindMatchingPatch(file.sha1, patch_sha1_str) < 0) {
425       printf("cache bits don't match any sha1 for \"%s\"\n", filename);
426       return 1;
427     }
428   }
429   return 0;
430 }
431 
ShowLicenses()432 int ShowLicenses() {
433     ShowBSDiffLicense();
434     return 0;
435 }
436 
FileSink(const unsigned char * data,size_t len,int fd)437 static size_t FileSink(const unsigned char* data, size_t len, int fd) {
438   size_t done = 0;
439   while (done < len) {
440     ssize_t wrote = TEMP_FAILURE_RETRY(ota_write(fd, data + done, len - done));
441     if (wrote == -1) {
442       printf("error writing %zd bytes: %s\n", (len - done), strerror(errno));
443       return done;
444     }
445     done += wrote;
446   }
447   return done;
448 }
449 
450 // Return the amount of free space (in bytes) on the filesystem
451 // containing filename.  filename must exist.  Return -1 on error.
FreeSpaceForFile(const char * filename)452 size_t FreeSpaceForFile(const char* filename) {
453     struct statfs sf;
454     if (statfs(filename, &sf) != 0) {
455         printf("failed to statfs %s: %s\n", filename, strerror(errno));
456         return -1;
457     }
458     return sf.f_bsize * sf.f_bavail;
459 }
460 
CacheSizeCheck(size_t bytes)461 int CacheSizeCheck(size_t bytes) {
462     if (MakeFreeSpaceOnCache(bytes) < 0) {
463         printf("unable to make %zu bytes available on /cache\n", bytes);
464         return 1;
465     } else {
466         return 0;
467     }
468 }
469 
470 // This function applies binary patches to EMMC target files in a way that is safe (the original
471 // file is not touched until we have the desired replacement for it) and idempotent (it's okay to
472 // run this program multiple times).
473 //
474 // - If the SHA-1 hash of <target_filename> is <target_sha1_string>, does nothing and exits
475 //   successfully.
476 //
477 // - Otherwise, if the SHA-1 hash of <source_filename> is one of the entries in <patch_sha1_str>,
478 //   the corresponding patch from <patch_data> (which must be a VAL_BLOB) is applied to produce a
479 //   new file (the type of patch is automatically detected from the blob data). If that new file
480 //   has SHA-1 hash <target_sha1_str>, moves it to replace <target_filename>, and exits
481 //   successfully. Note that if <source_filename> and <target_filename> are not the same,
482 //   <source_filename> is NOT deleted on success. <target_filename> may be the string "-" to mean
483 //   "the same as <source_filename>".
484 //
485 // - Otherwise, or if any error is encountered, exits with non-zero status.
486 //
487 // <source_filename> must refer to an EMMC partition to read the source data. See the comments for
488 // the LoadPartitionContents() function above for the format of such a filename. <target_size> has
489 // become obsolete since we have dropped the support for patching non-EMMC targets (EMMC targets
490 // have the size embedded in the filename).
applypatch(const char * source_filename,const char * target_filename,const char * target_sha1_str,size_t target_size __unused,const std::vector<std::string> & patch_sha1_str,const std::vector<std::unique_ptr<Value>> & patch_data,const Value * bonus_data)491 int applypatch(const char* source_filename, const char* target_filename,
492                const char* target_sha1_str, size_t target_size __unused,
493                const std::vector<std::string>& patch_sha1_str,
494                const std::vector<std::unique_ptr<Value>>& patch_data, const Value* bonus_data) {
495   printf("patch %s: ", source_filename);
496 
497   if (target_filename[0] == '-' && target_filename[1] == '\0') {
498     target_filename = source_filename;
499   }
500 
501   if (strncmp(target_filename, "EMMC:", 5) != 0) {
502     printf("Supporting patching EMMC targets only.\n");
503     return 1;
504   }
505 
506   uint8_t target_sha1[SHA_DIGEST_LENGTH];
507   if (ParseSha1(target_sha1_str, target_sha1) != 0) {
508     printf("failed to parse tgt-sha1 \"%s\"\n", target_sha1_str);
509     return 1;
510   }
511 
512   // We try to load the target file into the source_file object.
513   FileContents source_file;
514   if (LoadFileContents(target_filename, &source_file) == 0) {
515     if (memcmp(source_file.sha1, target_sha1, SHA_DIGEST_LENGTH) == 0) {
516       // The early-exit case: the patch was already applied, this file has the desired hash, nothing
517       // for us to do.
518       printf("already %s\n", short_sha1(target_sha1).c_str());
519       return 0;
520     }
521   }
522 
523   if (source_file.data.empty() ||
524       (target_filename != source_filename && strcmp(target_filename, source_filename) != 0)) {
525     // Need to load the source file: either we failed to load the target file, or we did but it's
526     // different from the expected.
527     source_file.data.clear();
528     LoadFileContents(source_filename, &source_file);
529   }
530 
531   if (!source_file.data.empty()) {
532     int to_use = FindMatchingPatch(source_file.sha1, patch_sha1_str);
533     if (to_use != -1) {
534       return GenerateTarget(source_file, patch_data[to_use], target_filename, target_sha1,
535                             bonus_data);
536     }
537   }
538 
539   printf("source file is bad; trying copy\n");
540 
541   FileContents copy_file;
542   if (LoadFileContents(CACHE_TEMP_SOURCE, &copy_file) < 0) {
543     printf("failed to read copy file\n");
544     return 1;
545   }
546 
547   int to_use = FindMatchingPatch(copy_file.sha1, patch_sha1_str);
548   if (to_use == -1) {
549     printf("copy file doesn't match source SHA-1s either\n");
550     return 1;
551   }
552 
553   return GenerateTarget(copy_file, patch_data[to_use], target_filename, target_sha1, bonus_data);
554 }
555 
556 /*
557  * This function flashes a given image to the target partition. It verifies
558  * the target cheksum first, and will return if target has the desired hash.
559  * It checks the checksum of the given source image before flashing, and
560  * verifies the target partition afterwards. The function is idempotent.
561  * Returns zero on success.
562  */
applypatch_flash(const char * source_filename,const char * target_filename,const char * target_sha1_str,size_t target_size)563 int applypatch_flash(const char* source_filename, const char* target_filename,
564                      const char* target_sha1_str, size_t target_size) {
565   printf("flash %s: ", target_filename);
566 
567   uint8_t target_sha1[SHA_DIGEST_LENGTH];
568   if (ParseSha1(target_sha1_str, target_sha1) != 0) {
569     printf("failed to parse tgt-sha1 \"%s\"\n", target_sha1_str);
570     return 1;
571   }
572 
573   std::string target_str(target_filename);
574   std::vector<std::string> pieces = android::base::Split(target_str, ":");
575   if (pieces.size() != 2 || pieces[0] != "EMMC") {
576     printf("invalid target name \"%s\"", target_filename);
577     return 1;
578   }
579 
580   // Load the target into the source_file object to see if already applied.
581   pieces.push_back(std::to_string(target_size));
582   pieces.push_back(target_sha1_str);
583   std::string fullname = android::base::Join(pieces, ':');
584   FileContents source_file;
585   if (LoadPartitionContents(fullname, &source_file) == 0 &&
586       memcmp(source_file.sha1, target_sha1, SHA_DIGEST_LENGTH) == 0) {
587     // The early-exit case: the image was already applied, this partition
588     // has the desired hash, nothing for us to do.
589     printf("already %s\n", short_sha1(target_sha1).c_str());
590     return 0;
591   }
592 
593   if (LoadFileContents(source_filename, &source_file) == 0) {
594     if (memcmp(source_file.sha1, target_sha1, SHA_DIGEST_LENGTH) != 0) {
595       // The source doesn't have desired checksum.
596       printf("source \"%s\" doesn't have expected sha1 sum\n", source_filename);
597       printf("expected: %s, found: %s\n", short_sha1(target_sha1).c_str(),
598              short_sha1(source_file.sha1).c_str());
599       return 1;
600     }
601   }
602 
603   if (WriteToPartition(source_file.data.data(), target_size, target_filename) != 0) {
604     printf("write of copied data to %s failed\n", target_filename);
605     return 1;
606   }
607   return 0;
608 }
609 
GenerateTarget(const FileContents & source_file,const std::unique_ptr<Value> & patch,const std::string & target_filename,const uint8_t target_sha1[SHA_DIGEST_LENGTH],const Value * bonus_data)610 static int GenerateTarget(const FileContents& source_file, const std::unique_ptr<Value>& patch,
611                           const std::string& target_filename,
612                           const uint8_t target_sha1[SHA_DIGEST_LENGTH], const Value* bonus_data) {
613   if (patch->type != VAL_BLOB) {
614     printf("patch is not a blob\n");
615     return 1;
616   }
617 
618   const char* header = &patch->data[0];
619   size_t header_bytes_read = patch->data.size();
620   bool use_bsdiff = false;
621   if (header_bytes_read >= 8 && memcmp(header, "BSDIFF40", 8) == 0) {
622     use_bsdiff = true;
623   } else if (header_bytes_read >= 8 && memcmp(header, "IMGDIFF2", 8) == 0) {
624     use_bsdiff = false;
625   } else {
626     printf("Unknown patch file format\n");
627     return 1;
628   }
629 
630   CHECK(android::base::StartsWith(target_filename, "EMMC:"));
631 
632   // We still write the original source to cache, in case the partition write is interrupted.
633   if (MakeFreeSpaceOnCache(source_file.data.size()) < 0) {
634     printf("not enough free space on /cache\n");
635     return 1;
636   }
637   if (SaveFileContents(CACHE_TEMP_SOURCE, &source_file) < 0) {
638     printf("failed to back up source file\n");
639     return 1;
640   }
641 
642   // We store the decoded output in memory.
643   std::string memory_sink_str;  // Don't need to reserve space.
644   SinkFn sink = [&memory_sink_str](const unsigned char* data, size_t len) {
645     memory_sink_str.append(reinterpret_cast<const char*>(data), len);
646     return len;
647   };
648 
649   SHA_CTX ctx;
650   SHA1_Init(&ctx);
651 
652   int result;
653   if (use_bsdiff) {
654     result = ApplyBSDiffPatch(source_file.data.data(), source_file.data.size(), patch.get(), 0,
655                               sink, &ctx);
656   } else {
657     result = ApplyImagePatch(source_file.data.data(), source_file.data.size(), patch.get(), sink,
658                              &ctx, bonus_data);
659   }
660 
661   if (result != 0) {
662     printf("applying patch failed\n");
663     return 1;
664   }
665 
666   uint8_t current_target_sha1[SHA_DIGEST_LENGTH];
667   SHA1_Final(current_target_sha1, &ctx);
668   if (memcmp(current_target_sha1, target_sha1, SHA_DIGEST_LENGTH) != 0) {
669     printf("patch did not produce expected sha1\n");
670     return 1;
671   } else {
672     printf("now %s\n", short_sha1(target_sha1).c_str());
673   }
674 
675   // Write back the temp file to the partition.
676   if (WriteToPartition(reinterpret_cast<const unsigned char*>(memory_sink_str.c_str()),
677                        memory_sink_str.size(), target_filename) != 0) {
678     printf("write of patched data to %s failed\n", target_filename.c_str());
679     return 1;
680   }
681 
682   // Delete the backup copy of the source.
683   unlink(CACHE_TEMP_SOURCE);
684 
685   // Success!
686   return 0;
687 }
688