blob: d552dcf832326eadc9ef30217cf0259a7d6737e1 [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 Deymoddf9db52017-03-02 16:10:41 -080031#include "bsdiff/bspatch.h"
Alex Deymob870eb52015-10-14 21:39:04 -070032
Sen Jiang5b372b62016-03-28 16:14:35 -070033#include <errno.h>
The Android Open Source Projectc285fea2009-03-03 19:29:20 -080034#include <fcntl.h>
Gilad Arnold99b53742013-04-30 09:24:14 -070035#include <inttypes.h>
Alex Deymoea72d9f2017-10-26 13:15:13 +020036#include <stdio.h>
Gilad Arnold99b53742013-04-30 09:24:14 -070037#include <stdlib.h>
38#include <string.h>
Sen Jiang5b372b62016-03-28 16:14:35 -070039#include <sys/stat.h>
Alex Deymob870eb52015-10-14 21:39:04 -070040#include <sys/types.h>
Alex Deymodcd423b2017-09-13 20:54:24 +020041#include <unistd.h>
The Android Open Source Projectc285fea2009-03-03 19:29:20 -080042
Alex Deymo437b7af2015-10-14 20:13:58 -070043#include <algorithm>
Alex Deymodcd423b2017-09-13 20:54:24 +020044#include <memory>
Sen Jiang5b372b62016-03-28 16:14:35 -070045#include <vector>
Alex Deymo437b7af2015-10-14 20:13:58 -070046
Alex Deymodcd423b2017-09-13 20:54:24 +020047#include "bsdiff/buffer_file.h"
Tianjie Xu65288122017-10-13 15:10:58 -070048#include "bsdiff/control_entry.h"
Alex Deymodcd423b2017-09-13 20:54:24 +020049#include "bsdiff/extents.h"
Alex Deymoddf9db52017-03-02 16:10:41 -080050#include "bsdiff/extents_file.h"
Alex Deymodcd423b2017-09-13 20:54:24 +020051#include "bsdiff/file.h"
Alex Deymoddf9db52017-03-02 16:10:41 -080052#include "bsdiff/file_interface.h"
Amin Hassani1106bf72017-11-15 17:26:03 -080053#include "bsdiff/logging.h"
Alex Deymodcd423b2017-09-13 20:54:24 +020054#include "bsdiff/memory_file.h"
Tianjie Xu65288122017-10-13 15:10:58 -070055#include "bsdiff/patch_reader.h"
Alex Deymodcd423b2017-09-13 20:54:24 +020056#include "bsdiff/sink_file.h"
Tianjie Xu65288122017-10-13 15:10:58 -070057#include "bsdiff/utils.h"
Zdenek Behan339e0ee2010-06-14 12:50:53 -070058
Alex Deymo20891f92015-10-12 17:28:04 -070059namespace {
Tianjie Xu65288122017-10-13 15:10:58 -070060// Read the data in |stream| and write |size| decompressed data to |file|;
61// using the buffer in |buf| with size |buf_size|.
62// Returns 0 on success, 1 on I/O error and 2 on data error.
63int ReadStreamAndWriteAll(
64 const std::unique_ptr<bsdiff::FileInterface>& file,
65 size_t size,
66 uint8_t* buf,
67 size_t buf_size,
68 const std::function<bool(uint8_t*, size_t)>& read_func) {
Sen Jiang716d5692016-05-09 16:43:34 -070069 while (size > 0) {
Tianjie Xu65288122017-10-13 15:10:58 -070070 size_t bytes_to_output = std::min(size, buf_size);
71 if (!read_func(buf, bytes_to_output)) {
Amin Hassani1106bf72017-11-15 17:26:03 -080072 LOG(ERROR) << "Failed to read stream.";
Sen Jiangb552c792017-01-20 14:07:49 -080073 return 2;
74 }
Tianjie Xu65288122017-10-13 15:10:58 -070075
76 if (!WriteAll(file, buf, bytes_to_output)) {
Amin Hassani1106bf72017-11-15 17:26:03 -080077 PLOG(ERROR) << "WriteAll() failed.";
Sen Jiangb552c792017-01-20 14:07:49 -080078 return 1;
79 }
Tianjie Xu65288122017-10-13 15:10:58 -070080 size -= bytes_to_output;
Sen Jiang5b372b62016-03-28 16:14:35 -070081 }
Sen Jiangb552c792017-01-20 14:07:49 -080082 return 0;
Sen Jiang5b372b62016-03-28 16:14:35 -070083}
84
Alex Deymo20891f92015-10-12 17:28:04 -070085} // namespace
86
87namespace bsdiff {
88
Sen Jiang716d5692016-05-09 16:43:34 -070089bool ReadAll(const std::unique_ptr<FileInterface>& file,
90 uint8_t* data,
91 size_t size) {
92 size_t offset = 0, read;
93 while (offset < size) {
94 if (!file->Read(data + offset, size - offset, &read) || read == 0)
95 return false;
96 offset += read;
97 }
98 return true;
99}
100
Sen Jiang5b372b62016-03-28 16:14:35 -0700101bool WriteAll(const std::unique_ptr<FileInterface>& file,
102 const uint8_t* data,
103 size_t size) {
104 size_t offset = 0, written;
105 while (offset < size) {
Sen Jiangb14bb552016-04-11 16:08:03 -0700106 if (!file->Write(data + offset, size - offset, &written) || written == 0)
Sen Jiang5b372b62016-03-28 16:14:35 -0700107 return false;
108 offset += written;
109 }
110 return true;
111}
112
113bool IsOverlapping(const char* old_filename,
114 const char* new_filename,
115 const std::vector<ex_t>& old_extents,
116 const std::vector<ex_t>& new_extents) {
117 struct stat old_stat, new_stat;
118 if (stat(new_filename, &new_stat) == -1) {
119 if (errno == ENOENT)
120 return false;
Amin Hassani1106bf72017-11-15 17:26:03 -0800121 PLOG(ERROR) << "Error stat the new file: " << new_filename;
Sen Jiangb552c792017-01-20 14:07:49 -0800122 return true;
Sen Jiang5b372b62016-03-28 16:14:35 -0700123 }
Sen Jiangb552c792017-01-20 14:07:49 -0800124 if (stat(old_filename, &old_stat) == -1) {
Amin Hassani1106bf72017-11-15 17:26:03 -0800125 PLOG(ERROR) << "Error stat the old file: " << old_filename;
Sen Jiangb552c792017-01-20 14:07:49 -0800126 return true;
127 }
Sen Jiang5b372b62016-03-28 16:14:35 -0700128
129 if (old_stat.st_dev != new_stat.st_dev || old_stat.st_ino != new_stat.st_ino)
130 return false;
131
132 if (old_extents.empty() && new_extents.empty())
133 return true;
134
135 for (ex_t old_ex : old_extents)
136 for (ex_t new_ex : new_extents)
137 if (static_cast<uint64_t>(old_ex.off) < new_ex.off + new_ex.len &&
138 static_cast<uint64_t>(new_ex.off) < old_ex.off + old_ex.len)
139 return true;
140
141 return false;
142}
143
Sen Jiangb552c792017-01-20 14:07:49 -0800144// Patch |old_filename| with |patch_filename| and save it to |new_filename|.
145// |old_extents| and |new_extents| are comma-separated lists of "offset:length"
146// extents of |old_filename| and |new_filename|.
147// Returns 0 on success, 1 on I/O error and 2 on data error.
148int bspatch(const char* old_filename,
149 const char* new_filename,
150 const char* patch_filename,
151 const char* old_extents,
152 const char* new_extents) {
Sen Jiang716d5692016-05-09 16:43:34 -0700153 std::unique_ptr<FileInterface> patch_file =
154 File::FOpen(patch_filename, O_RDONLY);
Sen Jiangb552c792017-01-20 14:07:49 -0800155 if (!patch_file) {
Amin Hassani1106bf72017-11-15 17:26:03 -0800156 PLOG(ERROR) << "Error opening the patch file: " << patch_filename;
Sen Jiangb552c792017-01-20 14:07:49 -0800157 return 1;
158 }
Sen Jiang716d5692016-05-09 16:43:34 -0700159 uint64_t patch_size;
160 patch_file->GetSize(&patch_size);
161 std::vector<uint8_t> patch(patch_size);
Sen Jiangb552c792017-01-20 14:07:49 -0800162 if (!ReadAll(patch_file, patch.data(), patch_size)) {
Amin Hassani1106bf72017-11-15 17:26:03 -0800163 PLOG(ERROR) << "Error reading the patch file: " << patch_filename;
Sen Jiangb552c792017-01-20 14:07:49 -0800164 return 1;
165 }
Sen Jiang716d5692016-05-09 16:43:34 -0700166 patch_file.reset();
The Android Open Source Projectc285fea2009-03-03 19:29:20 -0800167
Sen Jiang62d5e482017-01-24 16:25:25 -0800168 return bspatch(old_filename, new_filename, patch.data(), patch_size,
169 old_extents, new_extents);
170}
171
172// Patch |old_filename| with |patch_data| and save it to |new_filename|.
173// |old_extents| and |new_extents| are comma-separated lists of "offset:length"
174// extents of |old_filename| and |new_filename|.
175// Returns 0 on success, 1 on I/O error and 2 on data error.
176int bspatch(const char* old_filename,
177 const char* new_filename,
178 const uint8_t* patch_data,
179 size_t patch_size,
180 const char* old_extents,
181 const char* new_extents) {
Alex Deymob870eb52015-10-14 21:39:04 -0700182 int using_extents = (old_extents != NULL || new_extents != NULL);
The Android Open Source Projectc285fea2009-03-03 19:29:20 -0800183
Alex Deymob870eb52015-10-14 21:39:04 -0700184 // Open input file for reading.
Alex Deymo437b7af2015-10-14 20:13:58 -0700185 std::unique_ptr<FileInterface> old_file = File::FOpen(old_filename, O_RDONLY);
Sen Jiangb552c792017-01-20 14:07:49 -0800186 if (!old_file) {
Amin Hassani1106bf72017-11-15 17:26:03 -0800187 PLOG(ERROR) << "Error opening the old file: " << old_filename;
Sen Jiangb552c792017-01-20 14:07:49 -0800188 return 1;
189 }
Alex Deymo437b7af2015-10-14 20:13:58 -0700190
Sen Jiang5b372b62016-03-28 16:14:35 -0700191 std::vector<ex_t> parsed_old_extents;
Alex Deymob870eb52015-10-14 21:39:04 -0700192 if (using_extents) {
Sen Jiangb552c792017-01-20 14:07:49 -0800193 if (!ParseExtentStr(old_extents, &parsed_old_extents)) {
Amin Hassani1106bf72017-11-15 17:26:03 -0800194 LOG(ERROR) << "Error parsing the old extents.";
Sen Jiangb552c792017-01-20 14:07:49 -0800195 return 2;
196 }
Alex Deymo437b7af2015-10-14 20:13:58 -0700197 old_file.reset(new ExtentsFile(std::move(old_file), parsed_old_extents));
198 }
199
Sen Jiang5b372b62016-03-28 16:14:35 -0700200 // Open output file for writing.
201 std::unique_ptr<FileInterface> new_file =
202 File::FOpen(new_filename, O_CREAT | O_WRONLY);
Sen Jiangb552c792017-01-20 14:07:49 -0800203 if (!new_file) {
Amin Hassani1106bf72017-11-15 17:26:03 -0800204 PLOG(ERROR) << "Error opening the new file: " << new_filename;
Sen Jiangb552c792017-01-20 14:07:49 -0800205 return 1;
206 }
Sen Jiang5b372b62016-03-28 16:14:35 -0700207
208 std::vector<ex_t> parsed_new_extents;
209 if (using_extents) {
Sen Jiangb552c792017-01-20 14:07:49 -0800210 if (!ParseExtentStr(new_extents, &parsed_new_extents)) {
Amin Hassani1106bf72017-11-15 17:26:03 -0800211 LOG(ERROR) << "Error parsing the new extents.";
Sen Jiangb552c792017-01-20 14:07:49 -0800212 return 2;
213 }
Sen Jiang5b372b62016-03-28 16:14:35 -0700214 new_file.reset(new ExtentsFile(std::move(new_file), parsed_new_extents));
215 }
216
217 if (IsOverlapping(old_filename, new_filename, parsed_old_extents,
218 parsed_new_extents)) {
219 // New and old file is overlapping, we can not stream output to new file,
Sen Jiang716d5692016-05-09 16:43:34 -0700220 // cache it in a buffer and write to the file at the end.
Sen Jiang62d5e482017-01-24 16:25:25 -0800221 uint64_t newsize = ParseInt64(patch_data + 24);
Sen Jiang716d5692016-05-09 16:43:34 -0700222 new_file.reset(new BufferFile(std::move(new_file), newsize));
Sen Jiang5b372b62016-03-28 16:14:35 -0700223 }
The Android Open Source Projectc285fea2009-03-03 19:29:20 -0800224
Sen Jiang62d5e482017-01-24 16:25:25 -0800225 return bspatch(old_file, new_file, patch_data, patch_size);
Sen Jiang716d5692016-05-09 16:43:34 -0700226}
227
Sen Jiangb552c792017-01-20 14:07:49 -0800228// Patch |old_data| with |patch_data| and save it by calling sink function.
229// Returns 0 on success, 1 on I/O error and 2 on data error.
Sen Jiang716d5692016-05-09 16:43:34 -0700230int bspatch(const uint8_t* old_data,
231 size_t old_size,
232 const uint8_t* patch_data,
233 size_t patch_size,
234 const sink_func& sink) {
235 std::unique_ptr<FileInterface> old_file(new MemoryFile(old_data, old_size));
236 std::unique_ptr<FileInterface> new_file(new SinkFile(sink));
237
238 return bspatch(old_file, new_file, patch_data, patch_size);
239}
240
Sen Jiangb552c792017-01-20 14:07:49 -0800241// Patch |old_file| with |patch_data| and save it to |new_file|.
242// Returns 0 on success, 1 on I/O error and 2 on data error.
Sen Jiang716d5692016-05-09 16:43:34 -0700243int bspatch(const std::unique_ptr<FileInterface>& old_file,
244 const std::unique_ptr<FileInterface>& new_file,
245 const uint8_t* patch_data,
246 size_t patch_size) {
Tianjie Xu65288122017-10-13 15:10:58 -0700247 BsdiffPatchReader patch_reader;
248 if (!patch_reader.Init(patch_data, patch_size)) {
Amin Hassani1106bf72017-11-15 17:26:03 -0800249 LOG(ERROR) << "Failed to initialize patch reader.";
Sen Jiangb552c792017-01-20 14:07:49 -0800250 return 2;
251 }
Sen Jiang716d5692016-05-09 16:43:34 -0700252
Tianjie Xu65288122017-10-13 15:10:58 -0700253 uint64_t old_file_size;
254 if (!old_file->GetSize(&old_file_size)) {
Amin Hassani1106bf72017-11-15 17:26:03 -0800255 LOG(ERROR) << "Cannot obtain the size of old file.";
Sen Jiangb552c792017-01-20 14:07:49 -0800256 return 1;
257 }
Sen Jiang716d5692016-05-09 16:43:34 -0700258
Alex Deymo437b7af2015-10-14 20:13:58 -0700259 // The oldpos can be negative, but the new pos is only incremented linearly.
260 int64_t oldpos = 0;
261 uint64_t newpos = 0;
Tianjie Xu65288122017-10-13 15:10:58 -0700262 std::vector<uint8_t> old_buf(1024 * 1024);
263 std::vector<uint8_t> new_buf(1024 * 1024);
264 uint64_t old_file_pos = 0;
265 while (newpos < patch_reader.new_file_size()) {
266 ControlEntry control_entry(0, 0, 0);
267 if (!patch_reader.ParseControlEntry(&control_entry)) {
Amin Hassani1106bf72017-11-15 17:26:03 -0800268 LOG(ERROR) << "Failed to read control stream.";
Sen Jiangb552c792017-01-20 14:07:49 -0800269 return 2;
270 }
Doug Zongker4d054792014-05-13 08:37:06 -0700271
Alex Deymob870eb52015-10-14 21:39:04 -0700272 // Sanity-check.
Tianjie Xu65288122017-10-13 15:10:58 -0700273 if (newpos + control_entry.diff_size > patch_reader.new_file_size()) {
Amin Hassani1106bf72017-11-15 17:26:03 -0800274 LOG(ERROR) << "Corrupt patch.";
Sen Jiangb552c792017-01-20 14:07:49 -0800275 return 2;
276 }
The Android Open Source Projectc285fea2009-03-03 19:29:20 -0800277
Sen Jiangb552c792017-01-20 14:07:49 -0800278 int ret = 0;
Alex Deymob870eb52015-10-14 21:39:04 -0700279 // Add old data to diff string. It is enough to fseek once, at
280 // the beginning of the sequence, to avoid unnecessary overhead.
Tianjie Xu65288122017-10-13 15:10:58 -0700281 int64_t seek_offset = oldpos;
282 if (seek_offset < 0) {
Sen Jiang5b372b62016-03-28 16:14:35 -0700283 // Write diff block directly to new file without adding old data,
284 // because we will skip part where |oldpos| < 0.
Tianjie Xu65288122017-10-13 15:10:58 -0700285 ret = ReadStreamAndWriteAll(
286 new_file, oldpos - old_file_size, new_buf.data(), new_buf.size(),
287 std::bind(&BsdiffPatchReader::ReadDiffStream, &patch_reader,
288 std::placeholders::_1, std::placeholders::_2));
Sen Jiangb552c792017-01-20 14:07:49 -0800289 if (ret)
290 return ret;
Tianjie Xu65288122017-10-13 15:10:58 -0700291 seek_offset = 0;
Alex Deymob870eb52015-10-14 21:39:04 -0700292 }
Sen Jiang5b372b62016-03-28 16:14:35 -0700293
Tianjie Xu65288122017-10-13 15:10:58 -0700294 // We just checked that |seek_offset| is not negative.
295 if (static_cast<uint64_t>(seek_offset) != old_file_pos &&
296 !old_file->Seek(seek_offset)) {
Amin Hassani1106bf72017-11-15 17:26:03 -0800297 PLOG(ERROR) << "Error seeking input file to offset: " << seek_offset;
Sen Jiangb552c792017-01-20 14:07:49 -0800298 return 1;
299 }
Alex Deymo437b7af2015-10-14 20:13:58 -0700300
Tianjie Xu65288122017-10-13 15:10:58 -0700301 old_file_pos =
302 std::min<uint64_t>(oldpos + control_entry.diff_size, old_file_size);
303 size_t chunk_size = old_file_pos - seek_offset;
Alex Deymo437b7af2015-10-14 20:13:58 -0700304 while (chunk_size > 0) {
305 size_t read_bytes;
Sen Jiang5b372b62016-03-28 16:14:35 -0700306 size_t bytes_to_read = std::min(chunk_size, old_buf.size());
Sen Jiangb552c792017-01-20 14:07:49 -0800307 if (!old_file->Read(old_buf.data(), bytes_to_read, &read_bytes)) {
Amin Hassani1106bf72017-11-15 17:26:03 -0800308 PLOG(ERROR) << "Error reading from input file.";
Sen Jiangb552c792017-01-20 14:07:49 -0800309 return 1;
310 }
311 if (!read_bytes) {
Amin Hassani1106bf72017-11-15 17:26:03 -0800312 LOG(ERROR) << "EOF reached while reading from input file.";
Sen Jiangb552c792017-01-20 14:07:49 -0800313 return 2;
314 }
Sen Jiang5b372b62016-03-28 16:14:35 -0700315 // Read same amount of bytes from diff block
Tianjie Xu65288122017-10-13 15:10:58 -0700316 if (!patch_reader.ReadDiffStream(new_buf.data(), read_bytes)) {
Amin Hassani1106bf72017-11-15 17:26:03 -0800317 LOG(ERROR) << "Failed to read diff stream.";
Sen Jiangb552c792017-01-20 14:07:49 -0800318 return 2;
319 }
Sen Jiangd87c8352015-11-20 16:14:36 -0800320 // new_buf already has data from diff block, adds old data to it.
321 for (size_t k = 0; k < read_bytes; k++)
Sen Jiang5b372b62016-03-28 16:14:35 -0700322 new_buf[k] += old_buf[k];
Sen Jiangb552c792017-01-20 14:07:49 -0800323 if (!WriteAll(new_file, new_buf.data(), read_bytes)) {
Amin Hassani1106bf72017-11-15 17:26:03 -0800324 PLOG(ERROR) << "Error writing to new file.";
Sen Jiangb552c792017-01-20 14:07:49 -0800325 return 1;
326 }
Alex Deymo437b7af2015-10-14 20:13:58 -0700327 chunk_size -= read_bytes;
Alex Deymob870eb52015-10-14 21:39:04 -0700328 }
The Android Open Source Projectc285fea2009-03-03 19:29:20 -0800329
Alex Deymob870eb52015-10-14 21:39:04 -0700330 // Adjust pointers.
Tianjie Xu65288122017-10-13 15:10:58 -0700331 newpos += control_entry.diff_size;
332 oldpos += control_entry.diff_size;
The Android Open Source Projectc285fea2009-03-03 19:29:20 -0800333
Tianjie Xu65288122017-10-13 15:10:58 -0700334 if (oldpos > static_cast<int64_t>(old_file_size)) {
Sen Jiang5b372b62016-03-28 16:14:35 -0700335 // Write diff block directly to new file without adding old data,
Tianjie Xu65288122017-10-13 15:10:58 -0700336 // because we skipped part where |oldpos| > old_file_size.
337 ret = ReadStreamAndWriteAll(
338 new_file, oldpos - old_file_size, new_buf.data(), new_buf.size(),
339 std::bind(&BsdiffPatchReader::ReadDiffStream, &patch_reader,
340 std::placeholders::_1, std::placeholders::_2));
Sen Jiangb552c792017-01-20 14:07:49 -0800341 if (ret)
342 return ret;
Sen Jiang5b372b62016-03-28 16:14:35 -0700343 }
344
Alex Deymob870eb52015-10-14 21:39:04 -0700345 // Sanity-check.
Tianjie Xu65288122017-10-13 15:10:58 -0700346 if (newpos + control_entry.extra_size > patch_reader.new_file_size()) {
Amin Hassani1106bf72017-11-15 17:26:03 -0800347 LOG(ERROR) << "Corrupt patch.";
Sen Jiangb552c792017-01-20 14:07:49 -0800348 return 2;
349 }
The Android Open Source Projectc285fea2009-03-03 19:29:20 -0800350
Sen Jiang5b372b62016-03-28 16:14:35 -0700351 // Read extra block.
Tianjie Xu65288122017-10-13 15:10:58 -0700352 ret = ReadStreamAndWriteAll(
353 new_file, control_entry.extra_size, new_buf.data(), new_buf.size(),
354 std::bind(&BsdiffPatchReader::ReadExtraStream, &patch_reader,
355 std::placeholders::_1, std::placeholders::_2));
Sen Jiangb552c792017-01-20 14:07:49 -0800356 if (ret)
357 return ret;
The Android Open Source Projectc285fea2009-03-03 19:29:20 -0800358
Alex Deymob870eb52015-10-14 21:39:04 -0700359 // Adjust pointers.
Tianjie Xu65288122017-10-13 15:10:58 -0700360 newpos += control_entry.extra_size;
361 oldpos += control_entry.offset_increment;
Sen Jiang5b372b62016-03-28 16:14:35 -0700362 }
The Android Open Source Projectc285fea2009-03-03 19:29:20 -0800363
Alex Deymob870eb52015-10-14 21:39:04 -0700364 // Close input file.
Alex Deymo437b7af2015-10-14 20:13:58 -0700365 old_file->Close();
Gilad Arnold99b53742013-04-30 09:24:14 -0700366
Tianjie Xu65288122017-10-13 15:10:58 -0700367 if (!patch_reader.Finish()) {
Amin Hassani1106bf72017-11-15 17:26:03 -0800368 LOG(ERROR) << "Failed to finish the patch reader.";
Tianjie Xu65288122017-10-13 15:10:58 -0700369 return 2;
370 }
The Android Open Source Projectc285fea2009-03-03 19:29:20 -0800371
Sen Jiangb552c792017-01-20 14:07:49 -0800372 if (!new_file->Close()) {
Amin Hassani1106bf72017-11-15 17:26:03 -0800373 PLOG(ERROR) << "Error closing new file.";
Sen Jiangb552c792017-01-20 14:07:49 -0800374 return 1;
375 }
The Android Open Source Projectc285fea2009-03-03 19:29:20 -0800376
Alex Deymob870eb52015-10-14 21:39:04 -0700377 return 0;
The Android Open Source Projectc285fea2009-03-03 19:29:20 -0800378}
Alex Deymo20891f92015-10-12 17:28:04 -0700379
380} // namespace bsdiff