blob: 0d906763ad9047b2931c16f90ede8afcbcf06511 [file] [log] [blame]
The Android Open Source Projectc285fea2009-03-03 19:29:20 -08001/*-
2 * Copyright 2003-2005 Colin Percival
3 * All rights reserved
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted providing that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
23 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#if 0
28__FBSDID("$FreeBSD: src/usr.bin/bsdiff/bspatch/bspatch.c,v 1.1 2005/08/06 01:59:06 cperciva Exp $");
29#endif
30
Alex Deymob870eb52015-10-14 21:39:04 -070031#include "bspatch.h"
32
The Android Open Source Projectc285fea2009-03-03 19:29:20 -080033#include <bzlib.h>
Sen Jiang5b372b62016-03-28 16:14:35 -070034#include <errno.h>
The Android Open Source Projectc285fea2009-03-03 19:29:20 -080035#include <fcntl.h>
Gilad Arnold99b53742013-04-30 09:24:14 -070036#include <inttypes.h>
Gilad Arnold99b53742013-04-30 09:24:14 -070037#include <stdlib.h>
38#include <string.h>
39#include <unistd.h>
Sen Jiang5b372b62016-03-28 16:14:35 -070040#include <sys/stat.h>
Alex Deymob870eb52015-10-14 21:39:04 -070041#include <sys/types.h>
The Android Open Source Projectc285fea2009-03-03 19:29:20 -080042
Alex Deymo437b7af2015-10-14 20:13:58 -070043#include <algorithm>
44#include <memory>
45#include <limits>
Sen Jiang5b372b62016-03-28 16:14:35 -070046#include <vector>
Alex Deymo437b7af2015-10-14 20:13:58 -070047
Sen Jiang716d5692016-05-09 16:43:34 -070048#include "buffer_file.h"
Gilad Arnold99b53742013-04-30 09:24:14 -070049#include "extents.h"
Alex Deymo437b7af2015-10-14 20:13:58 -070050#include "extents_file.h"
51#include "file.h"
52#include "file_interface.h"
Sen Jiang5b372b62016-03-28 16:14:35 -070053#include "memory_file.h"
Sen Jiang716d5692016-05-09 16:43:34 -070054#include "sink_file.h"
Zdenek Behan339e0ee2010-06-14 12:50:53 -070055
Alex Deymo20891f92015-10-12 17:28:04 -070056namespace {
Zdenek Behan339e0ee2010-06-14 12:50:53 -070057
Sen Jiang716d5692016-05-09 16:43:34 -070058int64_t ParseInt64(const u_char* buf) {
Alex Deymo437b7af2015-10-14 20:13:58 -070059 int64_t y;
The Android Open Source Projectc285fea2009-03-03 19:29:20 -080060
Alex Deymob870eb52015-10-14 21:39:04 -070061 y = buf[7] & 0x7F;
62 y = y * 256;
63 y += buf[6];
64 y = y * 256;
65 y += buf[5];
66 y = y * 256;
67 y += buf[4];
68 y = y * 256;
69 y += buf[3];
70 y = y * 256;
71 y += buf[2];
72 y = y * 256;
73 y += buf[1];
74 y = y * 256;
75 y += buf[0];
The Android Open Source Projectc285fea2009-03-03 19:29:20 -080076
Alex Deymob870eb52015-10-14 21:39:04 -070077 if (buf[7] & 0x80)
78 y = -y;
The Android Open Source Projectc285fea2009-03-03 19:29:20 -080079
Alex Deymob870eb52015-10-14 21:39:04 -070080 return y;
The Android Open Source Projectc285fea2009-03-03 19:29:20 -080081}
82
Sen Jiang716d5692016-05-09 16:43:34 -070083bool ReadBZ2(bz_stream* stream, uint8_t* data, size_t size) {
84 stream->next_out = (char*)data;
85 while (size > 0) {
86 unsigned int read_size = std::min(
87 static_cast<size_t>(std::numeric_limits<unsigned int>::max()), size);
88 stream->avail_out = read_size;
89 int bz2err = BZ2_bzDecompress(stream);
90 if (bz2err != BZ_OK && bz2err != BZ_STREAM_END)
91 return false;
92 size -= read_size - stream->avail_out;
93 }
Sen Jiang5b372b62016-03-28 16:14:35 -070094 return true;
95}
96
Sen Jiangb552c792017-01-20 14:07:49 -080097int ReadBZ2AndWriteAll(const std::unique_ptr<bsdiff::FileInterface>& file,
98 bz_stream* stream,
99 size_t size,
100 uint8_t* buf,
101 size_t buf_size) {
Sen Jiang5b372b62016-03-28 16:14:35 -0700102 while (size > 0) {
103 size_t bytes_to_read = std::min(size, buf_size);
Sen Jiangb552c792017-01-20 14:07:49 -0800104 if (!ReadBZ2(stream, buf, bytes_to_read)) {
105 fprintf(stderr, "Failed to read bzip stream.\n");
106 return 2;
107 }
108 if (!WriteAll(file, buf, bytes_to_read)) {
109 perror("WriteAll() failed");
110 return 1;
111 }
Sen Jiang5b372b62016-03-28 16:14:35 -0700112 size -= bytes_to_read;
113 }
Sen Jiangb552c792017-01-20 14:07:49 -0800114 return 0;
Sen Jiang5b372b62016-03-28 16:14:35 -0700115}
116
Alex Deymo20891f92015-10-12 17:28:04 -0700117} // namespace
118
119namespace bsdiff {
120
Sen Jiang716d5692016-05-09 16:43:34 -0700121bool ReadAll(const std::unique_ptr<FileInterface>& file,
122 uint8_t* data,
123 size_t size) {
124 size_t offset = 0, read;
125 while (offset < size) {
126 if (!file->Read(data + offset, size - offset, &read) || read == 0)
127 return false;
128 offset += read;
129 }
130 return true;
131}
132
Sen Jiang5b372b62016-03-28 16:14:35 -0700133bool WriteAll(const std::unique_ptr<FileInterface>& file,
134 const uint8_t* data,
135 size_t size) {
136 size_t offset = 0, written;
137 while (offset < size) {
Sen Jiangb14bb552016-04-11 16:08:03 -0700138 if (!file->Write(data + offset, size - offset, &written) || written == 0)
Sen Jiang5b372b62016-03-28 16:14:35 -0700139 return false;
140 offset += written;
141 }
142 return true;
143}
144
145bool IsOverlapping(const char* old_filename,
146 const char* new_filename,
147 const std::vector<ex_t>& old_extents,
148 const std::vector<ex_t>& new_extents) {
149 struct stat old_stat, new_stat;
150 if (stat(new_filename, &new_stat) == -1) {
151 if (errno == ENOENT)
152 return false;
Sen Jiangb552c792017-01-20 14:07:49 -0800153 fprintf(stderr, "Error stat the new file %s: %s\n", new_filename,
154 strerror(errno));
155 return true;
Sen Jiang5b372b62016-03-28 16:14:35 -0700156 }
Sen Jiangb552c792017-01-20 14:07:49 -0800157 if (stat(old_filename, &old_stat) == -1) {
158 fprintf(stderr, "Error stat the old file %s: %s\n", old_filename,
159 strerror(errno));
160 return true;
161 }
Sen Jiang5b372b62016-03-28 16:14:35 -0700162
163 if (old_stat.st_dev != new_stat.st_dev || old_stat.st_ino != new_stat.st_ino)
164 return false;
165
166 if (old_extents.empty() && new_extents.empty())
167 return true;
168
169 for (ex_t old_ex : old_extents)
170 for (ex_t new_ex : new_extents)
171 if (static_cast<uint64_t>(old_ex.off) < new_ex.off + new_ex.len &&
172 static_cast<uint64_t>(new_ex.off) < old_ex.off + old_ex.len)
173 return true;
174
175 return false;
176}
177
Sen Jiangb552c792017-01-20 14:07:49 -0800178// Patch |old_filename| with |patch_filename| and save it to |new_filename|.
179// |old_extents| and |new_extents| are comma-separated lists of "offset:length"
180// extents of |old_filename| and |new_filename|.
181// Returns 0 on success, 1 on I/O error and 2 on data error.
182int bspatch(const char* old_filename,
183 const char* new_filename,
184 const char* patch_filename,
185 const char* old_extents,
186 const char* new_extents) {
Sen Jiang716d5692016-05-09 16:43:34 -0700187 std::unique_ptr<FileInterface> patch_file =
188 File::FOpen(patch_filename, O_RDONLY);
Sen Jiangb552c792017-01-20 14:07:49 -0800189 if (!patch_file) {
190 fprintf(stderr, "Error opening the patch file %s: %s\n", patch_filename,
191 strerror(errno));
192 return 1;
193 }
Sen Jiang716d5692016-05-09 16:43:34 -0700194 uint64_t patch_size;
195 patch_file->GetSize(&patch_size);
196 std::vector<uint8_t> patch(patch_size);
Sen Jiangb552c792017-01-20 14:07:49 -0800197 if (!ReadAll(patch_file, patch.data(), patch_size)) {
198 fprintf(stderr, "Error reading the patch file %s: %s\n", patch_filename,
199 strerror(errno));
200 return 1;
201 }
Sen Jiang716d5692016-05-09 16:43:34 -0700202 patch_file.reset();
The Android Open Source Projectc285fea2009-03-03 19:29:20 -0800203
Alex Deymob870eb52015-10-14 21:39:04 -0700204 int using_extents = (old_extents != NULL || new_extents != NULL);
The Android Open Source Projectc285fea2009-03-03 19:29:20 -0800205
Alex Deymob870eb52015-10-14 21:39:04 -0700206 // Open input file for reading.
Alex Deymo437b7af2015-10-14 20:13:58 -0700207 std::unique_ptr<FileInterface> old_file = File::FOpen(old_filename, O_RDONLY);
Sen Jiangb552c792017-01-20 14:07:49 -0800208 if (!old_file) {
209 fprintf(stderr, "Error opening the old file %s: %s\n", old_filename,
210 strerror(errno));
211 return 1;
212 }
Alex Deymo437b7af2015-10-14 20:13:58 -0700213
Sen Jiang5b372b62016-03-28 16:14:35 -0700214 std::vector<ex_t> parsed_old_extents;
Alex Deymob870eb52015-10-14 21:39:04 -0700215 if (using_extents) {
Sen Jiangb552c792017-01-20 14:07:49 -0800216 if (!ParseExtentStr(old_extents, &parsed_old_extents)) {
217 fprintf(stderr, "Error parsing the old extents\n");
218 return 2;
219 }
Alex Deymo437b7af2015-10-14 20:13:58 -0700220 old_file.reset(new ExtentsFile(std::move(old_file), parsed_old_extents));
221 }
222
Sen Jiang5b372b62016-03-28 16:14:35 -0700223 // Open output file for writing.
224 std::unique_ptr<FileInterface> new_file =
225 File::FOpen(new_filename, O_CREAT | O_WRONLY);
Sen Jiangb552c792017-01-20 14:07:49 -0800226 if (!new_file) {
227 fprintf(stderr, "Error opening the new file %s: %s\n", new_filename,
228 strerror(errno));
229 return 1;
230 }
Sen Jiang5b372b62016-03-28 16:14:35 -0700231
232 std::vector<ex_t> parsed_new_extents;
233 if (using_extents) {
Sen Jiangb552c792017-01-20 14:07:49 -0800234 if (!ParseExtentStr(new_extents, &parsed_new_extents)) {
235 fprintf(stderr, "Error parsing the new extents\n");
236 return 2;
237 }
Sen Jiang5b372b62016-03-28 16:14:35 -0700238 new_file.reset(new ExtentsFile(std::move(new_file), parsed_new_extents));
239 }
240
241 if (IsOverlapping(old_filename, new_filename, parsed_old_extents,
242 parsed_new_extents)) {
243 // New and old file is overlapping, we can not stream output to new file,
Sen Jiang716d5692016-05-09 16:43:34 -0700244 // cache it in a buffer and write to the file at the end.
245 uint64_t newsize = ParseInt64(patch.data() + 24);
246 new_file.reset(new BufferFile(std::move(new_file), newsize));
Sen Jiang5b372b62016-03-28 16:14:35 -0700247 }
The Android Open Source Projectc285fea2009-03-03 19:29:20 -0800248
Sen Jiang716d5692016-05-09 16:43:34 -0700249 return bspatch(old_file, new_file, patch.data(), patch_size);
250}
251
Sen Jiangb552c792017-01-20 14:07:49 -0800252// Patch |old_data| with |patch_data| and save it by calling sink function.
253// Returns 0 on success, 1 on I/O error and 2 on data error.
Sen Jiang716d5692016-05-09 16:43:34 -0700254int bspatch(const uint8_t* old_data,
255 size_t old_size,
256 const uint8_t* patch_data,
257 size_t patch_size,
258 const sink_func& sink) {
259 std::unique_ptr<FileInterface> old_file(new MemoryFile(old_data, old_size));
260 std::unique_ptr<FileInterface> new_file(new SinkFile(sink));
261
262 return bspatch(old_file, new_file, patch_data, patch_size);
263}
264
Sen Jiangb552c792017-01-20 14:07:49 -0800265// Patch |old_file| with |patch_data| and save it to |new_file|.
266// Returns 0 on success, 1 on I/O error and 2 on data error.
Sen Jiang716d5692016-05-09 16:43:34 -0700267int bspatch(const std::unique_ptr<FileInterface>& old_file,
268 const std::unique_ptr<FileInterface>& new_file,
269 const uint8_t* patch_data,
270 size_t patch_size) {
271 int bz2err;
272 u_char buf[8];
273 off_t ctrl[3];
274
275 // File format:
276 // 0 8 "BSDIFF40"
277 // 8 8 X
278 // 16 8 Y
279 // 24 8 sizeof(new_filename)
280 // 32 X bzip2(control block)
281 // 32+X Y bzip2(diff block)
282 // 32+X+Y ??? bzip2(extra block)
283 // with control block a set of triples (x,y,z) meaning "add x bytes
284 // from oldfile to x bytes from the diff block; copy y bytes from the
285 // extra block; seek forwards in oldfile by z bytes".
286
287 // Check for appropriate magic.
Sen Jiangb552c792017-01-20 14:07:49 -0800288 if (memcmp(patch_data, "BSDIFF40", 8) != 0) {
289 fprintf(stderr, "Not a bsdiff patch.\n");
290 return 2;
291 }
Sen Jiang716d5692016-05-09 16:43:34 -0700292
293 // Read lengths from header.
294 uint64_t oldsize, newsize;
295 int64_t ctrl_len = ParseInt64(patch_data + 8);
296 int64_t data_len = ParseInt64(patch_data + 16);
297 int64_t signed_newsize = ParseInt64(patch_data + 24);
298 newsize = signed_newsize;
299 if ((ctrl_len < 0) || (data_len < 0) || (signed_newsize < 0) ||
Sen Jiangb552c792017-01-20 14:07:49 -0800300 (32 + ctrl_len + data_len > static_cast<int64_t>(patch_size))) {
301 fprintf(stderr, "Corrupt patch.\n");
302 return 2;
303 }
Sen Jiang716d5692016-05-09 16:43:34 -0700304
305 bz_stream cstream;
306 cstream.next_in = (char*)patch_data + 32;
307 cstream.avail_in = ctrl_len;
308 cstream.bzalloc = nullptr;
309 cstream.bzfree = nullptr;
310 cstream.opaque = nullptr;
Sen Jiangb552c792017-01-20 14:07:49 -0800311 if ((bz2err = BZ2_bzDecompressInit(&cstream, 0, 0)) != BZ_OK) {
312 fprintf(stderr, "Failed to bzinit control stream (%d)\n", bz2err);
313 return 2;
314 }
Sen Jiang716d5692016-05-09 16:43:34 -0700315
316 bz_stream dstream;
317 dstream.next_in = (char*)patch_data + 32 + ctrl_len;
318 dstream.avail_in = data_len;
319 dstream.bzalloc = nullptr;
320 dstream.bzfree = nullptr;
321 dstream.opaque = nullptr;
Sen Jiangb552c792017-01-20 14:07:49 -0800322 if ((bz2err = BZ2_bzDecompressInit(&dstream, 0, 0)) != BZ_OK) {
323 fprintf(stderr, "Failed to bzinit diff stream (%d)\n", bz2err);
324 return 2;
325 }
Sen Jiang716d5692016-05-09 16:43:34 -0700326
327 bz_stream estream;
328 estream.next_in = (char*)patch_data + 32 + ctrl_len + data_len;
329 estream.avail_in = patch_size - (32 + ctrl_len + data_len);
330 estream.bzalloc = nullptr;
331 estream.bzfree = nullptr;
332 estream.opaque = nullptr;
Sen Jiangb552c792017-01-20 14:07:49 -0800333 if ((bz2err = BZ2_bzDecompressInit(&estream, 0, 0)) != BZ_OK) {
334 fprintf(stderr, "Failed to bzinit extra stream (%d)\n", bz2err);
335 return 2;
336 }
Sen Jiang716d5692016-05-09 16:43:34 -0700337
338 uint64_t old_file_pos = 0;
339
Sen Jiangb552c792017-01-20 14:07:49 -0800340 if (!old_file->GetSize(&oldsize)) {
341 fprintf(stderr, "Cannot obtain the size of old file.\n");
342 return 1;
343 }
Sen Jiang716d5692016-05-09 16:43:34 -0700344
Alex Deymo437b7af2015-10-14 20:13:58 -0700345 // The oldpos can be negative, but the new pos is only incremented linearly.
346 int64_t oldpos = 0;
347 uint64_t newpos = 0;
Sen Jiang5b372b62016-03-28 16:14:35 -0700348 std::vector<uint8_t> old_buf(1024 * 1024), new_buf(1024 * 1024);
Alex Deymob870eb52015-10-14 21:39:04 -0700349 while (newpos < newsize) {
Sen Jiang5b372b62016-03-28 16:14:35 -0700350 int64_t i;
Alex Deymob870eb52015-10-14 21:39:04 -0700351 // Read control data.
352 for (i = 0; i <= 2; i++) {
Sen Jiangb552c792017-01-20 14:07:49 -0800353 if (!ReadBZ2(&cstream, buf, 8)) {
354 fprintf(stderr, "Failed to read control stream.\n");
355 return 2;
356 }
Alex Deymo437b7af2015-10-14 20:13:58 -0700357 ctrl[i] = ParseInt64(buf);
Sen Jiang5b372b62016-03-28 16:14:35 -0700358 }
The Android Open Source Projectc285fea2009-03-03 19:29:20 -0800359
Alex Deymob870eb52015-10-14 21:39:04 -0700360 // Sanity-check.
Sen Jiangb552c792017-01-20 14:07:49 -0800361 if (ctrl[0] < 0 || ctrl[1] < 0) {
362 fprintf(stderr, "Corrupt patch.\n");
363 return 2;
364 }
Doug Zongker4d054792014-05-13 08:37:06 -0700365
Alex Deymob870eb52015-10-14 21:39:04 -0700366 // Sanity-check.
Sen Jiangb552c792017-01-20 14:07:49 -0800367 if (newpos + ctrl[0] > newsize) {
368 fprintf(stderr, "Corrupt patch.\n");
369 return 2;
370 }
The Android Open Source Projectc285fea2009-03-03 19:29:20 -0800371
Sen Jiangb552c792017-01-20 14:07:49 -0800372 int ret = 0;
Alex Deymob870eb52015-10-14 21:39:04 -0700373 // Add old data to diff string. It is enough to fseek once, at
374 // the beginning of the sequence, to avoid unnecessary overhead.
Alex Deymob870eb52015-10-14 21:39:04 -0700375 if ((i = oldpos) < 0) {
Sen Jiang5b372b62016-03-28 16:14:35 -0700376 // Write diff block directly to new file without adding old data,
377 // because we will skip part where |oldpos| < 0.
Sen Jiangb552c792017-01-20 14:07:49 -0800378 ret = ReadBZ2AndWriteAll(new_file, &dstream, -i, new_buf.data(),
379 new_buf.size());
380 if (ret)
381 return ret;
Alex Deymob870eb52015-10-14 21:39:04 -0700382 i = 0;
383 }
Sen Jiang5b372b62016-03-28 16:14:35 -0700384
Alex Deymo437b7af2015-10-14 20:13:58 -0700385 // We just checked that |i| is not negative.
Sen Jiangb552c792017-01-20 14:07:49 -0800386 if (static_cast<uint64_t>(i) != old_file_pos && !old_file->Seek(i)) {
387 fprintf(stderr, "Error seeking input file to offset %" PRId64 ": %s\n", i,
388 strerror(errno));
389 return 1;
390 }
Alex Deymob870eb52015-10-14 21:39:04 -0700391 if ((old_file_pos = oldpos + ctrl[0]) > oldsize)
392 old_file_pos = oldsize;
Alex Deymo437b7af2015-10-14 20:13:58 -0700393
Sen Jiang5b372b62016-03-28 16:14:35 -0700394 size_t chunk_size = old_file_pos - i;
Alex Deymo437b7af2015-10-14 20:13:58 -0700395 while (chunk_size > 0) {
396 size_t read_bytes;
Sen Jiang5b372b62016-03-28 16:14:35 -0700397 size_t bytes_to_read = std::min(chunk_size, old_buf.size());
Sen Jiangb552c792017-01-20 14:07:49 -0800398 if (!old_file->Read(old_buf.data(), bytes_to_read, &read_bytes)) {
399 perror("Error reading from input file");
400 return 1;
401 }
402 if (!read_bytes) {
403 fprintf(stderr, "EOF reached while reading from input file.\n");
404 return 2;
405 }
Sen Jiang5b372b62016-03-28 16:14:35 -0700406 // Read same amount of bytes from diff block
Sen Jiangb552c792017-01-20 14:07:49 -0800407 if (!ReadBZ2(&dstream, new_buf.data(), read_bytes)) {
408 fprintf(stderr, "Failed to read diff stream.\n");
409 return 2;
410 }
Sen Jiangd87c8352015-11-20 16:14:36 -0800411 // new_buf already has data from diff block, adds old data to it.
412 for (size_t k = 0; k < read_bytes; k++)
Sen Jiang5b372b62016-03-28 16:14:35 -0700413 new_buf[k] += old_buf[k];
Sen Jiangb552c792017-01-20 14:07:49 -0800414 if (!WriteAll(new_file, new_buf.data(), read_bytes)) {
415 perror("Error writing to new file");
416 return 1;
417 }
Alex Deymo437b7af2015-10-14 20:13:58 -0700418 chunk_size -= read_bytes;
Alex Deymob870eb52015-10-14 21:39:04 -0700419 }
The Android Open Source Projectc285fea2009-03-03 19:29:20 -0800420
Alex Deymob870eb52015-10-14 21:39:04 -0700421 // Adjust pointers.
422 newpos += ctrl[0];
423 oldpos += ctrl[0];
The Android Open Source Projectc285fea2009-03-03 19:29:20 -0800424
Sen Jiang5b372b62016-03-28 16:14:35 -0700425 if (oldpos > static_cast<int64_t>(oldsize)) {
426 // Write diff block directly to new file without adding old data,
427 // because we skipped part where |oldpos| > oldsize.
Sen Jiangb552c792017-01-20 14:07:49 -0800428 ret = ReadBZ2AndWriteAll(new_file, &dstream, oldpos - oldsize,
429 new_buf.data(), new_buf.size());
430 if (ret)
431 return ret;
Sen Jiang5b372b62016-03-28 16:14:35 -0700432 }
433
Alex Deymob870eb52015-10-14 21:39:04 -0700434 // Sanity-check.
Sen Jiangb552c792017-01-20 14:07:49 -0800435 if (newpos + ctrl[1] > newsize) {
436 fprintf(stderr, "Corrupt patch.\n");
437 return 2;
438 }
The Android Open Source Projectc285fea2009-03-03 19:29:20 -0800439
Sen Jiang5b372b62016-03-28 16:14:35 -0700440 // Read extra block.
Sen Jiangb552c792017-01-20 14:07:49 -0800441 ret = ReadBZ2AndWriteAll(new_file, &estream, ctrl[1], new_buf.data(),
442 new_buf.size());
443 if (ret)
444 return ret;
The Android Open Source Projectc285fea2009-03-03 19:29:20 -0800445
Alex Deymob870eb52015-10-14 21:39:04 -0700446 // Adjust pointers.
447 newpos += ctrl[1];
448 oldpos += ctrl[2];
Sen Jiang5b372b62016-03-28 16:14:35 -0700449 }
The Android Open Source Projectc285fea2009-03-03 19:29:20 -0800450
Alex Deymob870eb52015-10-14 21:39:04 -0700451 // Close input file.
Alex Deymo437b7af2015-10-14 20:13:58 -0700452 old_file->Close();
Gilad Arnold99b53742013-04-30 09:24:14 -0700453
Alex Deymob870eb52015-10-14 21:39:04 -0700454 // Clean up the bzip2 reads.
Sen Jiang716d5692016-05-09 16:43:34 -0700455 BZ2_bzDecompressEnd(&cstream);
456 BZ2_bzDecompressEnd(&dstream);
457 BZ2_bzDecompressEnd(&estream);
The Android Open Source Projectc285fea2009-03-03 19:29:20 -0800458
Sen Jiangb552c792017-01-20 14:07:49 -0800459 if (!new_file->Close()) {
460 perror("Error closing new file");
461 return 1;
462 }
The Android Open Source Projectc285fea2009-03-03 19:29:20 -0800463
Alex Deymob870eb52015-10-14 21:39:04 -0700464 return 0;
The Android Open Source Projectc285fea2009-03-03 19:29:20 -0800465}
Alex Deymo20891f92015-10-12 17:28:04 -0700466
467} // namespace bsdiff