aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--applypatch/applypatch.cpp45
-rw-r--r--applypatch/bspatch.cpp14
-rw-r--r--applypatch/imgpatch.cpp26
-rw-r--r--applypatch/include/applypatch/applypatch.h19
-rw-r--r--applypatch/include/applypatch/imgpatch.h9
-rw-r--r--tests/component/imgdiff_test.cpp80
-rw-r--r--updater/blockimg.cpp228
7 files changed, 190 insertions, 231 deletions
diff --git a/applypatch/applypatch.cpp b/applypatch/applypatch.cpp
index 7be3fdbd..51bf3932 100644
--- a/applypatch/applypatch.cpp
+++ b/applypatch/applypatch.cpp
@@ -27,6 +27,7 @@
27#include <sys/types.h> 27#include <sys/types.h>
28#include <unistd.h> 28#include <unistd.h>
29 29
30#include <functional>
30#include <memory> 31#include <memory>
31#include <string> 32#include <string>
32#include <utility> 33#include <utility>
@@ -42,7 +43,7 @@
42#include "print_sha1.h" 43#include "print_sha1.h"
43 44
44static int LoadPartitionContents(const std::string& filename, FileContents* file); 45static int LoadPartitionContents(const std::string& filename, FileContents* file);
45static ssize_t FileSink(const unsigned char* data, ssize_t len, void* token); 46static size_t FileSink(const unsigned char* data, size_t len, int fd);
46static int GenerateTarget(const FileContents& source_file, const std::unique_ptr<Value>& patch, 47static int GenerateTarget(const FileContents& source_file, const std::unique_ptr<Value>& patch,
47 const std::string& target_filename, 48 const std::string& target_filename,
48 const uint8_t target_sha1[SHA_DIGEST_LENGTH], const Value* bonus_data); 49 const uint8_t target_sha1[SHA_DIGEST_LENGTH], const Value* bonus_data);
@@ -194,8 +195,8 @@ int SaveFileContents(const char* filename, const FileContents* file) {
194 return -1; 195 return -1;
195 } 196 }
196 197
197 ssize_t bytes_written = FileSink(file->data.data(), file->data.size(), &fd); 198 size_t bytes_written = FileSink(file->data.data(), file->data.size(), fd);
198 if (bytes_written != static_cast<ssize_t>(file->data.size())) { 199 if (bytes_written != file->data.size()) {
199 printf("short write of \"%s\" (%zd bytes of %zu): %s\n", filename, bytes_written, 200 printf("short write of \"%s\" (%zd bytes of %zu): %s\n", filename, bytes_written,
200 file->data.size(), strerror(errno)); 201 file->data.size(), strerror(errno));
201 return -1; 202 return -1;
@@ -433,25 +434,17 @@ int ShowLicenses() {
433 return 0; 434 return 0;
434} 435}
435 436
436ssize_t FileSink(const unsigned char* data, ssize_t len, void* token) { 437static size_t FileSink(const unsigned char* data, size_t len, int fd) {
437 int fd = *static_cast<int*>(token); 438 size_t done = 0;
438 ssize_t done = 0; 439 while (done < len) {
439 ssize_t wrote; 440 ssize_t wrote = TEMP_FAILURE_RETRY(ota_write(fd, data + done, len - done));
440 while (done < len) { 441 if (wrote == -1) {
441 wrote = TEMP_FAILURE_RETRY(ota_write(fd, data+done, len-done)); 442 printf("error writing %zd bytes: %s\n", (len - done), strerror(errno));
442 if (wrote == -1) { 443 return done;
443 printf("error writing %zd bytes: %s\n", (len-done), strerror(errno));
444 return done;
445 }
446 done += wrote;
447 } 444 }
448 return done; 445 done += wrote;
449} 446 }
450 447 return done;
451ssize_t MemorySink(const unsigned char* data, ssize_t len, void* token) {
452 std::string* s = static_cast<std::string*>(token);
453 s->append(reinterpret_cast<const char*>(data), len);
454 return len;
455} 448}
456 449
457// Return the amount of free space (in bytes) on the filesystem 450// Return the amount of free space (in bytes) on the filesystem
@@ -647,9 +640,11 @@ static int GenerateTarget(const FileContents& source_file, const std::unique_ptr
647 } 640 }
648 641
649 // We store the decoded output in memory. 642 // We store the decoded output in memory.
650 SinkFn sink = MemorySink;
651 std::string memory_sink_str; // Don't need to reserve space. 643 std::string memory_sink_str; // Don't need to reserve space.
652 void* token = &memory_sink_str; 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 };
653 648
654 SHA_CTX ctx; 649 SHA_CTX ctx;
655 SHA1_Init(&ctx); 650 SHA1_Init(&ctx);
@@ -657,10 +652,10 @@ static int GenerateTarget(const FileContents& source_file, const std::unique_ptr
657 int result; 652 int result;
658 if (use_bsdiff) { 653 if (use_bsdiff) {
659 result = ApplyBSDiffPatch(source_file.data.data(), source_file.data.size(), patch.get(), 0, 654 result = ApplyBSDiffPatch(source_file.data.data(), source_file.data.size(), patch.get(), 0,
660 sink, token, &ctx); 655 sink, &ctx);
661 } else { 656 } else {
662 result = ApplyImagePatch(source_file.data.data(), source_file.data.size(), patch.get(), sink, 657 result = ApplyImagePatch(source_file.data.data(), source_file.data.size(), patch.get(), sink,
663 token, &ctx, bonus_data); 658 &ctx, bonus_data);
664 } 659 }
665 660
666 if (result != 0) { 661 if (result != 0) {
diff --git a/applypatch/bspatch.cpp b/applypatch/bspatch.cpp
index 9920c2be..f75a2c68 100644
--- a/applypatch/bspatch.cpp
+++ b/applypatch/bspatch.cpp
@@ -24,9 +24,9 @@
24#include <sys/types.h> 24#include <sys/types.h>
25 25
26#include <bspatch.h> 26#include <bspatch.h>
27#include <openssl/sha.h>
27 28
28#include "applypatch/applypatch.h" 29#include "applypatch/applypatch.h"
29#include "openssl/sha.h"
30 30
31void ShowBSDiffLicense() { 31void ShowBSDiffLicense() {
32 puts("The bsdiff library used herein is:\n" 32 puts("The bsdiff library used herein is:\n"
@@ -60,10 +60,10 @@ void ShowBSDiffLicense() {
60 ); 60 );
61} 61}
62 62
63int ApplyBSDiffPatch(const unsigned char* old_data, ssize_t old_size, const Value* patch, 63int ApplyBSDiffPatch(const unsigned char* old_data, size_t old_size, const Value* patch,
64 ssize_t patch_offset, SinkFn sink, void* token, SHA_CTX* ctx) { 64 size_t patch_offset, SinkFn sink, SHA_CTX* ctx) {
65 auto sha_sink = [&](const uint8_t* data, size_t len) { 65 auto sha_sink = [&sink, &ctx](const uint8_t* data, size_t len) {
66 len = sink(data, len, token); 66 len = sink(data, len);
67 if (ctx) SHA1_Update(ctx, data, len); 67 if (ctx) SHA1_Update(ctx, data, len);
68 return len; 68 return len;
69 }; 69 };
@@ -72,8 +72,8 @@ int ApplyBSDiffPatch(const unsigned char* old_data, ssize_t old_size, const Valu
72 patch->data.size(), sha_sink); 72 patch->data.size(), sha_sink);
73} 73}
74 74
75int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size, const Value* patch, 75int ApplyBSDiffPatchMem(const unsigned char* old_data, size_t old_size, const Value* patch,
76 ssize_t patch_offset, std::vector<unsigned char>* new_data) { 76 size_t patch_offset, std::vector<unsigned char>* new_data) {
77 auto vector_sink = [new_data](const uint8_t* data, size_t len) { 77 auto vector_sink = [new_data](const uint8_t* data, size_t len) {
78 new_data->insert(new_data->end(), data, data + len); 78 new_data->insert(new_data->end(), data, data + len);
79 return len; 79 return len;
diff --git a/applypatch/imgpatch.cpp b/applypatch/imgpatch.cpp
index adcc61fd..7d8b7361 100644
--- a/applypatch/imgpatch.cpp
+++ b/applypatch/imgpatch.cpp
@@ -43,12 +43,11 @@ static inline int32_t Read4(const void *address) {
43 return android::base::get_unaligned<int32_t>(address); 43 return android::base::get_unaligned<int32_t>(address);
44} 44}
45 45
46int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size, 46int ApplyImagePatch(const unsigned char* old_data, size_t old_size, const unsigned char* patch_data,
47 const unsigned char* patch_data, ssize_t patch_size, 47 size_t patch_size, SinkFn sink) {
48 SinkFn sink, void* token) {
49 Value patch(VAL_BLOB, std::string(reinterpret_cast<const char*>(patch_data), patch_size)); 48 Value patch(VAL_BLOB, std::string(reinterpret_cast<const char*>(patch_data), patch_size));
50 49
51 return ApplyImagePatch(old_data, old_size, &patch, sink, token, nullptr, nullptr); 50 return ApplyImagePatch(old_data, old_size, &patch, sink, nullptr, nullptr);
52} 51}
53 52
54/* 53/*
@@ -57,8 +56,8 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
57 * file, and update the SHA context with the output data as well. 56 * file, and update the SHA context with the output data as well.
58 * Return 0 on success. 57 * Return 0 on success.
59 */ 58 */
60int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size, const Value* patch, 59int ApplyImagePatch(const unsigned char* old_data, size_t old_size, const Value* patch, SinkFn sink,
61 SinkFn sink, void* token, SHA_CTX* ctx, const Value* bonus_data) { 60 SHA_CTX* ctx, const Value* bonus_data) {
62 if (patch->data.size() < 12) { 61 if (patch->data.size() < 12) {
63 printf("patch too short to contain header\n"); 62 printf("patch too short to contain header\n");
64 return -1; 63 return -1;
@@ -97,11 +96,11 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size, const Value
97 size_t src_len = static_cast<size_t>(Read8(normal_header + 8)); 96 size_t src_len = static_cast<size_t>(Read8(normal_header + 8));
98 size_t patch_offset = static_cast<size_t>(Read8(normal_header + 16)); 97 size_t patch_offset = static_cast<size_t>(Read8(normal_header + 16));
99 98
100 if (src_start + src_len > static_cast<size_t>(old_size)) { 99 if (src_start + src_len > old_size) {
101 printf("source data too short\n"); 100 printf("source data too short\n");
102 return -1; 101 return -1;
103 } 102 }
104 ApplyBSDiffPatch(old_data + src_start, src_len, patch, patch_offset, sink, token, ctx); 103 ApplyBSDiffPatch(old_data + src_start, src_len, patch, patch_offset, sink, ctx);
105 } else if (type == CHUNK_RAW) { 104 } else if (type == CHUNK_RAW) {
106 const char* raw_header = &patch->data[pos]; 105 const char* raw_header = &patch->data[pos];
107 pos += 4; 106 pos += 4;
@@ -110,15 +109,14 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size, const Value
110 return -1; 109 return -1;
111 } 110 }
112 111
113 ssize_t data_len = Read4(raw_header); 112 size_t data_len = static_cast<size_t>(Read4(raw_header));
114 113
115 if (pos + data_len > patch->data.size()) { 114 if (pos + data_len > patch->data.size()) {
116 printf("failed to read chunk %d raw data\n", i); 115 printf("failed to read chunk %d raw data\n", i);
117 return -1; 116 return -1;
118 } 117 }
119 if (ctx) SHA1_Update(ctx, &patch->data[pos], data_len); 118 if (ctx) SHA1_Update(ctx, &patch->data[pos], data_len);
120 if (sink(reinterpret_cast<const unsigned char*>(&patch->data[pos]), data_len, token) != 119 if (sink(reinterpret_cast<const unsigned char*>(&patch->data[pos]), data_len) != data_len) {
121 data_len) {
122 printf("failed to write chunk %d raw data\n", i); 120 printf("failed to write chunk %d raw data\n", i);
123 return -1; 121 return -1;
124 } 122 }
@@ -143,7 +141,7 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size, const Value
143 int memLevel = Read4(deflate_header + 52); 141 int memLevel = Read4(deflate_header + 52);
144 int strategy = Read4(deflate_header + 56); 142 int strategy = Read4(deflate_header + 56);
145 143
146 if (src_start + src_len > static_cast<size_t>(old_size)) { 144 if (src_start + src_len > old_size) {
147 printf("source data too short\n"); 145 printf("source data too short\n");
148 return -1; 146 return -1;
149 } 147 }
@@ -240,9 +238,9 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size, const Value
240 strm.avail_out = temp_data.size(); 238 strm.avail_out = temp_data.size();
241 strm.next_out = temp_data.data(); 239 strm.next_out = temp_data.data();
242 ret = deflate(&strm, Z_FINISH); 240 ret = deflate(&strm, Z_FINISH);
243 ssize_t have = temp_data.size() - strm.avail_out; 241 size_t have = temp_data.size() - strm.avail_out;
244 242
245 if (sink(temp_data.data(), have, token) != have) { 243 if (sink(temp_data.data(), have) != have) {
246 printf("failed to write %zd compressed bytes to output\n", have); 244 printf("failed to write %zd compressed bytes to output\n", have);
247 return -1; 245 return -1;
248 } 246 }
diff --git a/applypatch/include/applypatch/applypatch.h b/applypatch/include/applypatch/applypatch.h
index 4489decb..da55432d 100644
--- a/applypatch/include/applypatch/applypatch.h
+++ b/applypatch/include/applypatch/applypatch.h
@@ -20,6 +20,7 @@
20#include <stdint.h> 20#include <stdint.h>
21#include <sys/stat.h> 21#include <sys/stat.h>
22 22
23#include <functional>
23#include <memory> 24#include <memory>
24#include <string> 25#include <string>
25#include <vector> 26#include <vector>
@@ -41,7 +42,7 @@ struct FileContents {
41// and use it as the source instead. 42// and use it as the source instead.
42#define CACHE_TEMP_SOURCE "/cache/saved.file" 43#define CACHE_TEMP_SOURCE "/cache/saved.file"
43 44
44typedef ssize_t (*SinkFn)(const unsigned char*, ssize_t, void*); 45using SinkFn = std::function<size_t(const unsigned char*, size_t)>;
45 46
46// applypatch.cpp 47// applypatch.cpp
47int ShowLicenses(); 48int ShowLicenses();
@@ -66,18 +67,14 @@ int SaveFileContents(const char* filename, const FileContents* file);
66 67
67// bspatch.cpp 68// bspatch.cpp
68void ShowBSDiffLicense(); 69void ShowBSDiffLicense();
69int ApplyBSDiffPatch(const unsigned char* old_data, ssize_t old_size, 70int ApplyBSDiffPatch(const unsigned char* old_data, size_t old_size, const Value* patch,
70 const Value* patch, ssize_t patch_offset, 71 size_t patch_offset, SinkFn sink, SHA_CTX* ctx);
71 SinkFn sink, void* token, SHA_CTX* ctx); 72int ApplyBSDiffPatchMem(const unsigned char* old_data, size_t old_size, const Value* patch,
72int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size, 73 size_t patch_offset, std::vector<unsigned char>* new_data);
73 const Value* patch, ssize_t patch_offset,
74 std::vector<unsigned char>* new_data);
75 74
76// imgpatch.cpp 75// imgpatch.cpp
77int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size, 76int ApplyImagePatch(const unsigned char* old_data, size_t old_size, const Value* patch, SinkFn sink,
78 const Value* patch, 77 SHA_CTX* ctx, const Value* bonus_data);
79 SinkFn sink, void* token, SHA_CTX* ctx,
80 const Value* bonus_data);
81 78
82// freecache.cpp 79// freecache.cpp
83int MakeFreeSpaceOnCache(size_t bytes_needed); 80int MakeFreeSpaceOnCache(size_t bytes_needed);
diff --git a/applypatch/include/applypatch/imgpatch.h b/applypatch/include/applypatch/imgpatch.h
index 6549f79f..07c66094 100644
--- a/applypatch/include/applypatch/imgpatch.h
+++ b/applypatch/include/applypatch/imgpatch.h
@@ -19,10 +19,11 @@
19 19
20#include <sys/types.h> 20#include <sys/types.h>
21 21
22using SinkFn = ssize_t (*)(const unsigned char*, ssize_t, void*); 22#include <functional>
23 23
24int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size, 24using SinkFn = std::function<size_t(const unsigned char*, size_t)>;
25 const unsigned char* patch_data, ssize_t patch_size, 25
26 SinkFn sink, void* token); 26int ApplyImagePatch(const unsigned char* old_data, size_t old_size, const unsigned char* patch_data,
27 size_t patch_size, SinkFn sink);
27 28
28#endif // _APPLYPATCH_IMGPATCH_H 29#endif // _APPLYPATCH_IMGPATCH_H
diff --git a/tests/component/imgdiff_test.cpp b/tests/component/imgdiff_test.cpp
index 2f648501..7d00a3d5 100644
--- a/tests/component/imgdiff_test.cpp
+++ b/tests/component/imgdiff_test.cpp
@@ -14,6 +14,8 @@
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 16
17#include <stdio.h>
18
17#include <string> 19#include <string>
18#include <vector> 20#include <vector>
19 21
@@ -27,12 +29,6 @@
27 29
28using android::base::get_unaligned; 30using android::base::get_unaligned;
29 31
30static ssize_t MemorySink(const unsigned char* data, ssize_t len, void* token) {
31 std::string* s = static_cast<std::string*>(token);
32 s->append(reinterpret_cast<const char*>(data), len);
33 return len;
34}
35
36// Sanity check for the given imgdiff patch header. 32// Sanity check for the given imgdiff patch header.
37static void verify_patch_header(const std::string& patch, size_t* num_normal, size_t* num_raw, 33static void verify_patch_header(const std::string& patch, size_t* num_normal, size_t* num_raw,
38 size_t* num_deflate) { 34 size_t* num_deflate) {
@@ -79,6 +75,18 @@ static void verify_patch_header(const std::string& patch, size_t* num_normal, si
79 if (num_deflate != nullptr) *num_deflate = deflate; 75 if (num_deflate != nullptr) *num_deflate = deflate;
80} 76}
81 77
78static void verify_patched_image(const std::string& src, const std::string& patch,
79 const std::string& tgt) {
80 std::string patched;
81 ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast<const unsigned char*>(src.data()), src.size(),
82 reinterpret_cast<const unsigned char*>(patch.data()), patch.size(),
83 [&patched](const unsigned char* data, size_t len) {
84 patched.append(reinterpret_cast<const char*>(data), len);
85 return len;
86 }));
87 ASSERT_EQ(tgt, patched);
88}
89
82TEST(ImgdiffTest, invalid_args) { 90TEST(ImgdiffTest, invalid_args) {
83 // Insufficient inputs. 91 // Insufficient inputs.
84 ASSERT_EQ(2, imgdiff(1, (const char* []){ "imgdiff" })); 92 ASSERT_EQ(2, imgdiff(1, (const char* []){ "imgdiff" }));
@@ -124,11 +132,7 @@ TEST(ImgdiffTest, image_mode_smoke) {
124 ASSERT_EQ(0U, num_deflate); 132 ASSERT_EQ(0U, num_deflate);
125 ASSERT_EQ(1U, num_raw); 133 ASSERT_EQ(1U, num_raw);
126 134
127 std::string patched; 135 verify_patched_image(src, patch, tgt);
128 ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast<const unsigned char*>(src.data()), src.size(),
129 reinterpret_cast<const unsigned char*>(patch.data()), patch.size(),
130 MemorySink, &patched));
131 ASSERT_EQ(tgt, patched);
132} 136}
133 137
134TEST(ImgdiffTest, zip_mode_smoke_store) { 138TEST(ImgdiffTest, zip_mode_smoke_store) {
@@ -177,11 +181,7 @@ TEST(ImgdiffTest, zip_mode_smoke_store) {
177 ASSERT_EQ(0U, num_deflate); 181 ASSERT_EQ(0U, num_deflate);
178 ASSERT_EQ(1U, num_raw); 182 ASSERT_EQ(1U, num_raw);
179 183
180 std::string patched; 184 verify_patched_image(src, patch, tgt);
181 ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast<const unsigned char*>(src.data()), src.size(),
182 reinterpret_cast<const unsigned char*>(patch.data()), patch.size(),
183 MemorySink, &patched));
184 ASSERT_EQ(tgt, patched);
185} 185}
186 186
187TEST(ImgdiffTest, zip_mode_smoke_compressed) { 187TEST(ImgdiffTest, zip_mode_smoke_compressed) {
@@ -230,11 +230,7 @@ TEST(ImgdiffTest, zip_mode_smoke_compressed) {
230 ASSERT_EQ(1U, num_deflate); 230 ASSERT_EQ(1U, num_deflate);
231 ASSERT_EQ(2U, num_raw); 231 ASSERT_EQ(2U, num_raw);
232 232
233 std::string patched; 233 verify_patched_image(src, patch, tgt);
234 ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast<const unsigned char*>(src.data()), src.size(),
235 reinterpret_cast<const unsigned char*>(patch.data()), patch.size(),
236 MemorySink, &patched));
237 ASSERT_EQ(tgt, patched);
238} 234}
239 235
240TEST(ImgdiffTest, zip_mode_smoke_trailer_zeros) { 236TEST(ImgdiffTest, zip_mode_smoke_trailer_zeros) {
@@ -286,11 +282,7 @@ TEST(ImgdiffTest, zip_mode_smoke_trailer_zeros) {
286 ASSERT_EQ(1U, num_deflate); 282 ASSERT_EQ(1U, num_deflate);
287 ASSERT_EQ(2U, num_raw); 283 ASSERT_EQ(2U, num_raw);
288 284
289 std::string patched; 285 verify_patched_image(src, patch, tgt);
290 ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast<const unsigned char*>(src.data()), src.size(),
291 reinterpret_cast<const unsigned char*>(patch.data()), patch.size(),
292 MemorySink, &patched));
293 ASSERT_EQ(tgt, patched);
294} 286}
295 287
296TEST(ImgdiffTest, image_mode_simple) { 288TEST(ImgdiffTest, image_mode_simple) {
@@ -333,11 +325,7 @@ TEST(ImgdiffTest, image_mode_simple) {
333 ASSERT_EQ(1U, num_deflate); 325 ASSERT_EQ(1U, num_deflate);
334 ASSERT_EQ(2U, num_raw); 326 ASSERT_EQ(2U, num_raw);
335 327
336 std::string patched; 328 verify_patched_image(src, patch, tgt);
337 ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast<const unsigned char*>(src.data()), src.size(),
338 reinterpret_cast<const unsigned char*>(patch.data()), patch.size(),
339 MemorySink, &patched));
340 ASSERT_EQ(tgt, patched);
341} 329}
342 330
343TEST(ImgdiffTest, image_mode_different_num_chunks) { 331TEST(ImgdiffTest, image_mode_different_num_chunks) {
@@ -413,11 +401,7 @@ TEST(ImgdiffTest, image_mode_merge_chunks) {
413 ASSERT_EQ(1U, num_deflate); 401 ASSERT_EQ(1U, num_deflate);
414 ASSERT_EQ(2U, num_raw); 402 ASSERT_EQ(2U, num_raw);
415 403
416 std::string patched; 404 verify_patched_image(src, patch, tgt);
417 ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast<const unsigned char*>(src.data()), src.size(),
418 reinterpret_cast<const unsigned char*>(patch.data()), patch.size(),
419 MemorySink, &patched));
420 ASSERT_EQ(tgt, patched);
421} 405}
422 406
423TEST(ImgdiffTest, image_mode_spurious_magic) { 407TEST(ImgdiffTest, image_mode_spurious_magic) {
@@ -454,11 +438,7 @@ TEST(ImgdiffTest, image_mode_spurious_magic) {
454 ASSERT_EQ(0U, num_deflate); 438 ASSERT_EQ(0U, num_deflate);
455 ASSERT_EQ(1U, num_raw); 439 ASSERT_EQ(1U, num_raw);
456 440
457 std::string patched; 441 verify_patched_image(src, patch, tgt);
458 ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast<const unsigned char*>(src.data()), src.size(),
459 reinterpret_cast<const unsigned char*>(patch.data()), patch.size(),
460 MemorySink, &patched));
461 ASSERT_EQ(tgt, patched);
462} 442}
463 443
464TEST(ImgdiffTest, image_mode_short_input1) { 444TEST(ImgdiffTest, image_mode_short_input1) {
@@ -494,11 +474,7 @@ TEST(ImgdiffTest, image_mode_short_input1) {
494 ASSERT_EQ(0U, num_deflate); 474 ASSERT_EQ(0U, num_deflate);
495 ASSERT_EQ(1U, num_raw); 475 ASSERT_EQ(1U, num_raw);
496 476
497 std::string patched; 477 verify_patched_image(src, patch, tgt);
498 ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast<const unsigned char*>(src.data()), src.size(),
499 reinterpret_cast<const unsigned char*>(patch.data()), patch.size(),
500 MemorySink, &patched));
501 ASSERT_EQ(tgt, patched);
502} 478}
503 479
504TEST(ImgdiffTest, image_mode_short_input2) { 480TEST(ImgdiffTest, image_mode_short_input2) {
@@ -534,11 +510,7 @@ TEST(ImgdiffTest, image_mode_short_input2) {
534 ASSERT_EQ(0U, num_deflate); 510 ASSERT_EQ(0U, num_deflate);
535 ASSERT_EQ(1U, num_raw); 511 ASSERT_EQ(1U, num_raw);
536 512
537 std::string patched; 513 verify_patched_image(src, patch, tgt);
538 ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast<const unsigned char*>(src.data()), src.size(),
539 reinterpret_cast<const unsigned char*>(patch.data()), patch.size(),
540 MemorySink, &patched));
541 ASSERT_EQ(tgt, patched);
542} 514}
543 515
544TEST(ImgdiffTest, image_mode_single_entry_long) { 516TEST(ImgdiffTest, image_mode_single_entry_long) {
@@ -577,9 +549,5 @@ TEST(ImgdiffTest, image_mode_single_entry_long) {
577 ASSERT_EQ(0U, num_deflate); 549 ASSERT_EQ(0U, num_deflate);
578 ASSERT_EQ(0U, num_raw); 550 ASSERT_EQ(0U, num_raw);
579 551
580 std::string patched; 552 verify_patched_image(src, patch, tgt);
581 ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast<const unsigned char*>(src.data()), src.size(),
582 reinterpret_cast<const unsigned char*>(patch.data()), patch.size(),
583 MemorySink, &patched));
584 ASSERT_EQ(tgt, patched);
585} 553}
diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp
index 1cad6da9..8c0f885a 100644
--- a/updater/blockimg.cpp
+++ b/updater/blockimg.cpp
@@ -240,57 +240,54 @@ struct RangeSinkState {
240 size_t p_remain; 240 size_t p_remain;
241}; 241};
242 242
243static ssize_t RangeSinkWrite(const uint8_t* data, ssize_t size, void* token) { 243static size_t RangeSinkWrite(const uint8_t* data, size_t size, RangeSinkState* rss) {
244 RangeSinkState* rss = reinterpret_cast<RangeSinkState*>(token); 244 if (rss->p_remain == 0) {
245 245 LOG(ERROR) << "range sink write overrun";
246 if (rss->p_remain == 0) { 246 return 0;
247 LOG(ERROR) << "range sink write overrun"; 247 }
248 return 0;
249 }
250
251 ssize_t written = 0;
252 while (size > 0) {
253 size_t write_now = size;
254
255 if (rss->p_remain < write_now) {
256 write_now = rss->p_remain;
257 }
258 248
259 if (write_all(rss->fd, data, write_now) == -1) { 249 size_t written = 0;
260 break; 250 while (size > 0) {
261 } 251 size_t write_now = size;
262 252
263 data += write_now; 253 if (rss->p_remain < write_now) {
264 size -= write_now; 254 write_now = rss->p_remain;
255 }
265 256
266 rss->p_remain -= write_now; 257 if (write_all(rss->fd, data, write_now) == -1) {
267 written += write_now; 258 break;
259 }
268 260
269 if (rss->p_remain == 0) { 261 data += write_now;
270 // move to the next block 262 size -= write_now;
271 ++rss->p_block;
272 if (rss->p_block < rss->tgt.count) {
273 rss->p_remain = (rss->tgt.pos[rss->p_block * 2 + 1] -
274 rss->tgt.pos[rss->p_block * 2]) * BLOCKSIZE;
275 263
276 off64_t offset = static_cast<off64_t>(rss->tgt.pos[rss->p_block*2]) * BLOCKSIZE; 264 rss->p_remain -= write_now;
277 if (!discard_blocks(rss->fd, offset, rss->p_remain)) { 265 written += write_now;
278 break;
279 }
280 266
281 if (!check_lseek(rss->fd, offset, SEEK_SET)) { 267 if (rss->p_remain == 0) {
282 break; 268 // Move to the next block.
283 } 269 ++rss->p_block;
270 if (rss->p_block < rss->tgt.count) {
271 rss->p_remain =
272 (rss->tgt.pos[rss->p_block * 2 + 1] - rss->tgt.pos[rss->p_block * 2]) * BLOCKSIZE;
273
274 off64_t offset = static_cast<off64_t>(rss->tgt.pos[rss->p_block * 2]) * BLOCKSIZE;
275 if (!discard_blocks(rss->fd, offset, rss->p_remain)) {
276 break;
277 }
284 278
285 } else { 279 if (!check_lseek(rss->fd, offset, SEEK_SET)) {
286 // we can't write any more; return how many bytes have 280 break;
287 // been written so far.
288 break;
289 }
290 } 281 }
282
283 } else {
284 // We can't write any more; return how many bytes have been written so far.
285 break;
286 }
291 } 287 }
288 }
292 289
293 return written; 290 return written;
294} 291}
295 292
296// All of the data for all the 'new' transfers is contained in one 293// All of the data for all the 'new' transfers is contained in one
@@ -338,7 +335,7 @@ static bool receive_new_data(const uint8_t* data, size_t size, void* cookie) {
338 335
339 // At this point nti->rss is set, and we own it. The main 336 // At this point nti->rss is set, and we own it. The main
340 // thread is waiting for it to disappear from nti. 337 // thread is waiting for it to disappear from nti.
341 ssize_t written = RangeSinkWrite(data, size, nti->rss); 338 size_t written = RangeSinkWrite(data, size, nti->rss);
342 data += written; 339 data += written;
343 size -= written; 340 size -= written;
344 341
@@ -1259,92 +1256,95 @@ static int PerformCommandNew(CommandParameters& params) {
1259} 1256}
1260 1257
1261static int PerformCommandDiff(CommandParameters& params) { 1258static int PerformCommandDiff(CommandParameters& params) {
1259 // <offset> <length>
1260 if (params.cpos + 1 >= params.tokens.size()) {
1261 LOG(ERROR) << "missing patch offset or length for " << params.cmdname;
1262 return -1;
1263 }
1262 1264
1263 // <offset> <length> 1265 size_t offset;
1264 if (params.cpos + 1 >= params.tokens.size()) { 1266 if (!android::base::ParseUint(params.tokens[params.cpos++], &offset)) {
1265 LOG(ERROR) << "missing patch offset or length for " << params.cmdname; 1267 LOG(ERROR) << "invalid patch offset";
1266 return -1; 1268 return -1;
1267 } 1269 }
1268 1270
1269 size_t offset; 1271 size_t len;
1270 if (!android::base::ParseUint(params.tokens[params.cpos++], &offset)) { 1272 if (!android::base::ParseUint(params.tokens[params.cpos++], &len)) {
1271 LOG(ERROR) << "invalid patch offset"; 1273 LOG(ERROR) << "invalid patch len";
1272 return -1; 1274 return -1;
1273 } 1275 }
1274 1276
1275 size_t len; 1277 RangeSet tgt;
1276 if (!android::base::ParseUint(params.tokens[params.cpos++], &len)) { 1278 size_t blocks = 0;
1277 LOG(ERROR) << "invalid patch len"; 1279 bool overlap = false;
1278 return -1; 1280 int status = LoadSrcTgtVersion3(params, tgt, &blocks, false, &overlap);
1279 }
1280 1281
1281 RangeSet tgt; 1282 if (status == -1) {
1282 size_t blocks = 0; 1283 LOG(ERROR) << "failed to read blocks for diff";
1283 bool overlap = false; 1284 return -1;
1284 int status = LoadSrcTgtVersion3(params, tgt, &blocks, false, &overlap); 1285 }
1285 1286
1286 if (status == -1) { 1287 if (status == 0) {
1287 LOG(ERROR) << "failed to read blocks for diff"; 1288 params.foundwrites = true;
1288 return -1; 1289 } else if (params.foundwrites) {
1289 } 1290 LOG(WARNING) << "warning: commands executed out of order [" << params.cmdname << "]";
1291 }
1290 1292
1293 if (params.canwrite) {
1291 if (status == 0) { 1294 if (status == 0) {
1292 params.foundwrites = true; 1295 LOG(INFO) << "patching " << blocks << " blocks to " << tgt.size;
1293 } else if (params.foundwrites) { 1296 Value patch_value(
1294 LOG(WARNING) << "warning: commands executed out of order [" << params.cmdname << "]"; 1297 VAL_BLOB, std::string(reinterpret_cast<const char*>(params.patch_start + offset), len));
1295 } 1298 RangeSinkState rss(tgt);
1296 1299 rss.fd = params.fd;
1297 if (params.canwrite) { 1300 rss.p_block = 0;
1298 if (status == 0) { 1301 rss.p_remain = (tgt.pos[1] - tgt.pos[0]) * BLOCKSIZE;
1299 LOG(INFO) << "patching " << blocks << " blocks to " << tgt.size; 1302
1300 Value patch_value(VAL_BLOB, 1303 off64_t offset = static_cast<off64_t>(tgt.pos[0]) * BLOCKSIZE;
1301 std::string(reinterpret_cast<const char*>(params.patch_start + offset), len)); 1304 if (!discard_blocks(params.fd, offset, rss.p_remain)) {
1302 RangeSinkState rss(tgt); 1305 return -1;
1303 rss.fd = params.fd; 1306 }
1304 rss.p_block = 0;
1305 rss.p_remain = (tgt.pos[1] - tgt.pos[0]) * BLOCKSIZE;
1306
1307 off64_t offset = static_cast<off64_t>(tgt.pos[0]) * BLOCKSIZE;
1308 if (!discard_blocks(params.fd, offset, rss.p_remain)) {
1309 return -1;
1310 }
1311
1312 if (!check_lseek(params.fd, offset, SEEK_SET)) {
1313 return -1;
1314 }
1315 1307
1316 if (params.cmdname[0] == 'i') { // imgdiff 1308 if (!check_lseek(params.fd, offset, SEEK_SET)) {
1317 if (ApplyImagePatch(params.buffer.data(), blocks * BLOCKSIZE, &patch_value, 1309 return -1;
1318 &RangeSinkWrite, &rss, nullptr, nullptr) != 0) { 1310 }
1319 LOG(ERROR) << "Failed to apply image patch.";
1320 return -1;
1321 }
1322 } else {
1323 if (ApplyBSDiffPatch(params.buffer.data(), blocks * BLOCKSIZE, &patch_value,
1324 0, &RangeSinkWrite, &rss, nullptr) != 0) {
1325 LOG(ERROR) << "Failed to apply bsdiff patch.";
1326 return -1;
1327 }
1328 }
1329 1311
1330 // We expect the output of the patcher to fill the tgt ranges exactly. 1312 if (params.cmdname[0] == 'i') { // imgdiff
1331 if (rss.p_block != tgt.count || rss.p_remain != 0) { 1313 if (ApplyImagePatch(
1332 LOG(ERROR) << "range sink underrun?"; 1314 params.buffer.data(), blocks * BLOCKSIZE, &patch_value,
1333 } 1315 std::bind(&RangeSinkWrite, std::placeholders::_1, std::placeholders::_2, &rss),
1334 } else { 1316 nullptr, nullptr) != 0) {
1335 LOG(INFO) << "skipping " << blocks << " blocks already patched to " << tgt.size 1317 LOG(ERROR) << "Failed to apply image patch.";
1336 << " [" << params.cmdline << "]"; 1318 return -1;
1337 } 1319 }
1338 } 1320 } else {
1321 if (ApplyBSDiffPatch(
1322 params.buffer.data(), blocks * BLOCKSIZE, &patch_value, 0,
1323 std::bind(&RangeSinkWrite, std::placeholders::_1, std::placeholders::_2, &rss),
1324 nullptr) != 0) {
1325 LOG(ERROR) << "Failed to apply bsdiff patch.";
1326 return -1;
1327 }
1328 }
1339 1329
1340 if (!params.freestash.empty()) { 1330 // We expect the output of the patcher to fill the tgt ranges exactly.
1341 FreeStash(params.stashbase, params.freestash); 1331 if (rss.p_block != tgt.count || rss.p_remain != 0) {
1342 params.freestash.clear(); 1332 LOG(ERROR) << "range sink underrun?";
1333 }
1334 } else {
1335 LOG(INFO) << "skipping " << blocks << " blocks already patched to " << tgt.size << " ["
1336 << params.cmdline << "]";
1343 } 1337 }
1338 }
1344 1339
1345 params.written += tgt.size; 1340 if (!params.freestash.empty()) {
1341 FreeStash(params.stashbase, params.freestash);
1342 params.freestash.clear();
1343 }
1346 1344
1347 return 0; 1345 params.written += tgt.size;
1346
1347 return 0;
1348} 1348}
1349 1349
1350static int PerformCommandErase(CommandParameters& params) { 1350static int PerformCommandErase(CommandParameters& params) {