1c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project/*-
2c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project * Copyright 2003-2005 Colin Percival
3c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project * All rights reserved
4c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project *
5c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project * Redistribution and use in source and binary forms, with or without
6c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project * modification, are permitted providing that the following conditions
7c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project * are met:
8c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project * 1. Redistributions of source code must retain the above copyright
9c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project *    notice, this list of conditions and the following disclaimer.
10c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
11c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
12c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project *    documentation and/or other materials provided with the distribution.
13c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project *
14c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
23c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project * POSSIBILITY OF SUCH DAMAGE.
25c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project */
26c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project
27c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project#if 0
28c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project__FBSDID("$FreeBSD: src/usr.bin/bsdiff/bspatch/bspatch.c,v 1.1 2005/08/06 01:59:06 cperciva Exp $");
29c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project#endif
30c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project
31b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo#include "bspatch.h"
32b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo
33c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project#include <bzlib.h>
345b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang#include <errno.h>
3599b5374de3cf896b8b77779798218be279bda210Gilad Arnold#include <fcntl.h>
36339e0eece8287189e4e794ca3bbb5390e9332fe9Zdenek Behan#include <inttypes.h>
3799b5374de3cf896b8b77779798218be279bda210Gilad Arnold#include <stdlib.h>
38c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project#include <string.h>
39c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project#include <unistd.h>
405b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang#include <sys/stat.h>
41b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo#include <sys/types.h>
42c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project
43437b7afd23768d737055fa70b79f5f2f714583a5Alex Deymo#include <algorithm>
44437b7afd23768d737055fa70b79f5f2f714583a5Alex Deymo#include <memory>
45437b7afd23768d737055fa70b79f5f2f714583a5Alex Deymo#include <limits>
465b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang#include <vector>
47437b7afd23768d737055fa70b79f5f2f714583a5Alex Deymo
48716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang#include "buffer_file.h"
4999b5374de3cf896b8b77779798218be279bda210Gilad Arnold#include "extents.h"
50437b7afd23768d737055fa70b79f5f2f714583a5Alex Deymo#include "extents_file.h"
51437b7afd23768d737055fa70b79f5f2f714583a5Alex Deymo#include "file.h"
52437b7afd23768d737055fa70b79f5f2f714583a5Alex Deymo#include "file_interface.h"
535b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang#include "memory_file.h"
54716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang#include "sink_file.h"
55339e0eece8287189e4e794ca3bbb5390e9332fe9Zdenek Behan
5620891f9c246ec36e6c148579522ac00051b64457Alex Deymonamespace {
57339e0eece8287189e4e794ca3bbb5390e9332fe9Zdenek Behan
58716d569273ef2aeacfe7555f60f7784b2366225dSen Jiangint64_t ParseInt64(const u_char* buf) {
59437b7afd23768d737055fa70b79f5f2f714583a5Alex Deymo  int64_t y;
60b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo
61b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo  y = buf[7] & 0x7F;
62b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo  y = y * 256;
63b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo  y += buf[6];
64b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo  y = y * 256;
65b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo  y += buf[5];
66b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo  y = y * 256;
67b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo  y += buf[4];
68b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo  y = y * 256;
69b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo  y += buf[3];
70b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo  y = y * 256;
71b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo  y += buf[2];
72b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo  y = y * 256;
73b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo  y += buf[1];
74b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo  y = y * 256;
75b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo  y += buf[0];
76b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo
77b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo  if (buf[7] & 0x80)
78b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo    y = -y;
79b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo
80b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo  return y;
81c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project}
82c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project
83716d569273ef2aeacfe7555f60f7784b2366225dSen Jiangbool ReadBZ2(bz_stream* stream, uint8_t* data, size_t size) {
84716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  stream->next_out = (char*)data;
85716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  while (size > 0) {
86716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang    unsigned int read_size = std::min(
87716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang        static_cast<size_t>(std::numeric_limits<unsigned int>::max()), size);
88716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang    stream->avail_out = read_size;
89716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang    int bz2err = BZ2_bzDecompress(stream);
90716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang    if (bz2err != BZ_OK && bz2err != BZ_STREAM_END)
91716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang      return false;
92716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang    size -= read_size - stream->avail_out;
93716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  }
945b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang  return true;
955b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang}
965b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang
97b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiangint ReadBZ2AndWriteAll(const std::unique_ptr<bsdiff::FileInterface>& file,
98b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang                       bz_stream* stream,
99b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang                       size_t size,
100b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang                       uint8_t* buf,
101b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang                       size_t buf_size) {
1025b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang  while (size > 0) {
1035b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang    size_t bytes_to_read = std::min(size, buf_size);
104b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    if (!ReadBZ2(stream, buf, bytes_to_read)) {
105b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang      fprintf(stderr, "Failed to read bzip stream.\n");
106b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang      return 2;
107b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    }
108b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    if (!WriteAll(file, buf, bytes_to_read)) {
109b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang      perror("WriteAll() failed");
110b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang      return 1;
111b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    }
1125b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang    size -= bytes_to_read;
1135b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang  }
114b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang  return 0;
1155b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang}
1165b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang
11720891f9c246ec36e6c148579522ac00051b64457Alex Deymo}  // namespace
11820891f9c246ec36e6c148579522ac00051b64457Alex Deymo
11920891f9c246ec36e6c148579522ac00051b64457Alex Deymonamespace bsdiff {
12020891f9c246ec36e6c148579522ac00051b64457Alex Deymo
121716d569273ef2aeacfe7555f60f7784b2366225dSen Jiangbool ReadAll(const std::unique_ptr<FileInterface>& file,
122716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang             uint8_t* data,
123716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang             size_t size) {
124716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  size_t offset = 0, read;
125716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  while (offset < size) {
126716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang    if (!file->Read(data + offset, size - offset, &read) || read == 0)
127716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang      return false;
128716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang    offset += read;
129716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  }
130716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  return true;
131716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang}
132716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang
1335b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiangbool WriteAll(const std::unique_ptr<FileInterface>& file,
1345b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang              const uint8_t* data,
1355b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang              size_t size) {
1365b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang  size_t offset = 0, written;
1375b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang  while (offset < size) {
138b14bb55294132466913a07e2c0a54b8765c9240bSen Jiang    if (!file->Write(data + offset, size - offset, &written) || written == 0)
1395b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang      return false;
1405b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang    offset += written;
1415b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang  }
1425b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang  return true;
1435b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang}
1445b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang
1455b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiangbool IsOverlapping(const char* old_filename,
1465b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang                   const char* new_filename,
1475b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang                   const std::vector<ex_t>& old_extents,
1485b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang                   const std::vector<ex_t>& new_extents) {
1495b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang  struct stat old_stat, new_stat;
1505b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang  if (stat(new_filename, &new_stat) == -1) {
1515b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang    if (errno == ENOENT)
1525b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang      return false;
153b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    fprintf(stderr, "Error stat the new file %s: %s\n", new_filename,
154b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang            strerror(errno));
155b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    return true;
156b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang  }
157b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang  if (stat(old_filename, &old_stat) == -1) {
158b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    fprintf(stderr, "Error stat the old file %s: %s\n", old_filename,
159b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang            strerror(errno));
160b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    return true;
1615b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang  }
1625b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang
1635b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang  if (old_stat.st_dev != new_stat.st_dev || old_stat.st_ino != new_stat.st_ino)
1645b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang    return false;
1655b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang
1665b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang  if (old_extents.empty() && new_extents.empty())
1675b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang    return true;
1685b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang
1695b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang  for (ex_t old_ex : old_extents)
1705b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang    for (ex_t new_ex : new_extents)
1715b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang      if (static_cast<uint64_t>(old_ex.off) < new_ex.off + new_ex.len &&
1725b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang          static_cast<uint64_t>(new_ex.off) < old_ex.off + old_ex.len)
1735b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang        return true;
1745b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang
1755b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang  return false;
1765b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang}
1775b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang
178b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang// Patch |old_filename| with |patch_filename| and save it to |new_filename|.
179b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang// |old_extents| and |new_extents| are comma-separated lists of "offset:length"
180b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang// extents of |old_filename| and |new_filename|.
181b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang// Returns 0 on success, 1 on I/O error and 2 on data error.
182b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiangint bspatch(const char* old_filename,
183b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang            const char* new_filename,
184b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang            const char* patch_filename,
185b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang            const char* old_extents,
186b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang            const char* new_extents) {
187716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  std::unique_ptr<FileInterface> patch_file =
188716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang      File::FOpen(patch_filename, O_RDONLY);
189b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang  if (!patch_file) {
190b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    fprintf(stderr, "Error opening the patch file %s: %s\n", patch_filename,
191b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang            strerror(errno));
192b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    return 1;
193b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang  }
194716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  uint64_t patch_size;
195716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  patch_file->GetSize(&patch_size);
196716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  std::vector<uint8_t> patch(patch_size);
197b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang  if (!ReadAll(patch_file, patch.data(), patch_size)) {
198b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    fprintf(stderr, "Error reading the patch file %s: %s\n", patch_filename,
199b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang            strerror(errno));
200b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    return 1;
201b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang  }
202716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  patch_file.reset();
203b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo
20462d5e48122519abcc89837d99fc60a09fc8ba405Sen Jiang  return bspatch(old_filename, new_filename, patch.data(), patch_size,
20562d5e48122519abcc89837d99fc60a09fc8ba405Sen Jiang                 old_extents, new_extents);
20662d5e48122519abcc89837d99fc60a09fc8ba405Sen Jiang}
20762d5e48122519abcc89837d99fc60a09fc8ba405Sen Jiang
20862d5e48122519abcc89837d99fc60a09fc8ba405Sen Jiang// Patch |old_filename| with |patch_data| and save it to |new_filename|.
20962d5e48122519abcc89837d99fc60a09fc8ba405Sen Jiang// |old_extents| and |new_extents| are comma-separated lists of "offset:length"
21062d5e48122519abcc89837d99fc60a09fc8ba405Sen Jiang// extents of |old_filename| and |new_filename|.
21162d5e48122519abcc89837d99fc60a09fc8ba405Sen Jiang// Returns 0 on success, 1 on I/O error and 2 on data error.
21262d5e48122519abcc89837d99fc60a09fc8ba405Sen Jiangint bspatch(const char* old_filename,
21362d5e48122519abcc89837d99fc60a09fc8ba405Sen Jiang            const char* new_filename,
21462d5e48122519abcc89837d99fc60a09fc8ba405Sen Jiang            const uint8_t* patch_data,
21562d5e48122519abcc89837d99fc60a09fc8ba405Sen Jiang            size_t patch_size,
21662d5e48122519abcc89837d99fc60a09fc8ba405Sen Jiang            const char* old_extents,
21762d5e48122519abcc89837d99fc60a09fc8ba405Sen Jiang            const char* new_extents) {
218716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  int using_extents = (old_extents != NULL || new_extents != NULL);
219b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo
220b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo  // Open input file for reading.
221437b7afd23768d737055fa70b79f5f2f714583a5Alex Deymo  std::unique_ptr<FileInterface> old_file = File::FOpen(old_filename, O_RDONLY);
222b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang  if (!old_file) {
223b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    fprintf(stderr, "Error opening the old file %s: %s\n", old_filename,
224b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang            strerror(errno));
225b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    return 1;
226b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang  }
227437b7afd23768d737055fa70b79f5f2f714583a5Alex Deymo
2285b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang  std::vector<ex_t> parsed_old_extents;
229b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo  if (using_extents) {
230b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    if (!ParseExtentStr(old_extents, &parsed_old_extents)) {
231b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang      fprintf(stderr, "Error parsing the old extents\n");
232b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang      return 2;
233b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    }
234437b7afd23768d737055fa70b79f5f2f714583a5Alex Deymo    old_file.reset(new ExtentsFile(std::move(old_file), parsed_old_extents));
235437b7afd23768d737055fa70b79f5f2f714583a5Alex Deymo  }
236437b7afd23768d737055fa70b79f5f2f714583a5Alex Deymo
2375b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang  // Open output file for writing.
2385b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang  std::unique_ptr<FileInterface> new_file =
2395b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang      File::FOpen(new_filename, O_CREAT | O_WRONLY);
240b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang  if (!new_file) {
241b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    fprintf(stderr, "Error opening the new file %s: %s\n", new_filename,
242b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang            strerror(errno));
243b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    return 1;
244b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang  }
2455b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang
2465b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang  std::vector<ex_t> parsed_new_extents;
2475b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang  if (using_extents) {
248b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    if (!ParseExtentStr(new_extents, &parsed_new_extents)) {
249b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang      fprintf(stderr, "Error parsing the new extents\n");
250b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang      return 2;
251b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    }
2525b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang    new_file.reset(new ExtentsFile(std::move(new_file), parsed_new_extents));
2535b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang  }
2545b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang
2555b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang  if (IsOverlapping(old_filename, new_filename, parsed_old_extents,
2565b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang                    parsed_new_extents)) {
2575b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang    // New and old file is overlapping, we can not stream output to new file,
258716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang    // cache it in a buffer and write to the file at the end.
25962d5e48122519abcc89837d99fc60a09fc8ba405Sen Jiang    uint64_t newsize = ParseInt64(patch_data + 24);
260716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang    new_file.reset(new BufferFile(std::move(new_file), newsize));
2615b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang  }
262b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo
26362d5e48122519abcc89837d99fc60a09fc8ba405Sen Jiang  return bspatch(old_file, new_file, patch_data, patch_size);
264716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang}
265716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang
266b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang// Patch |old_data| with |patch_data| and save it by calling sink function.
267b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang// Returns 0 on success, 1 on I/O error and 2 on data error.
268716d569273ef2aeacfe7555f60f7784b2366225dSen Jiangint bspatch(const uint8_t* old_data,
269716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang            size_t old_size,
270716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang            const uint8_t* patch_data,
271716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang            size_t patch_size,
272716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang            const sink_func& sink) {
273716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  std::unique_ptr<FileInterface> old_file(new MemoryFile(old_data, old_size));
274716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  std::unique_ptr<FileInterface> new_file(new SinkFile(sink));
275716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang
276716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  return bspatch(old_file, new_file, patch_data, patch_size);
277716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang}
278716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang
279b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang// Patch |old_file| with |patch_data| and save it to |new_file|.
280b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang// Returns 0 on success, 1 on I/O error and 2 on data error.
281716d569273ef2aeacfe7555f60f7784b2366225dSen Jiangint bspatch(const std::unique_ptr<FileInterface>& old_file,
282716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang            const std::unique_ptr<FileInterface>& new_file,
283716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang            const uint8_t* patch_data,
284716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang            size_t patch_size) {
285716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  int bz2err;
286716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  u_char buf[8];
287716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  off_t ctrl[3];
288716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang
289716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  // File format:
290716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  //   0       8    "BSDIFF40"
291716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  //   8       8    X
292716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  //   16      8    Y
293716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  //   24      8    sizeof(new_filename)
294716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  //   32      X    bzip2(control block)
295716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  //   32+X    Y    bzip2(diff block)
296716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  //   32+X+Y  ???  bzip2(extra block)
297716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  // with control block a set of triples (x,y,z) meaning "add x bytes
298716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  // from oldfile to x bytes from the diff block; copy y bytes from the
299716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  // extra block; seek forwards in oldfile by z bytes".
300716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang
301716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  // Check for appropriate magic.
302b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang  if (memcmp(patch_data, "BSDIFF40", 8) != 0) {
303b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    fprintf(stderr, "Not a bsdiff patch.\n");
304b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    return 2;
305b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang  }
306716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang
307716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  // Read lengths from header.
308716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  uint64_t oldsize, newsize;
309716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  int64_t ctrl_len = ParseInt64(patch_data + 8);
310716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  int64_t data_len = ParseInt64(patch_data + 16);
311716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  int64_t signed_newsize = ParseInt64(patch_data + 24);
312716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  newsize = signed_newsize;
313716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  if ((ctrl_len < 0) || (data_len < 0) || (signed_newsize < 0) ||
314b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang      (32 + ctrl_len + data_len > static_cast<int64_t>(patch_size))) {
315b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    fprintf(stderr, "Corrupt patch.\n");
316b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    return 2;
317b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang  }
318716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang
319716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  bz_stream cstream;
320716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  cstream.next_in = (char*)patch_data + 32;
321716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  cstream.avail_in = ctrl_len;
322716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  cstream.bzalloc = nullptr;
323716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  cstream.bzfree = nullptr;
324716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  cstream.opaque = nullptr;
325b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang  if ((bz2err = BZ2_bzDecompressInit(&cstream, 0, 0)) != BZ_OK) {
326b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    fprintf(stderr, "Failed to bzinit control stream (%d)\n", bz2err);
327b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    return 2;
328b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang  }
329716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang
330716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  bz_stream dstream;
331716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  dstream.next_in = (char*)patch_data + 32 + ctrl_len;
332716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  dstream.avail_in = data_len;
333716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  dstream.bzalloc = nullptr;
334716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  dstream.bzfree = nullptr;
335716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  dstream.opaque = nullptr;
336b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang  if ((bz2err = BZ2_bzDecompressInit(&dstream, 0, 0)) != BZ_OK) {
337b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    fprintf(stderr, "Failed to bzinit diff stream (%d)\n", bz2err);
338b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    return 2;
339b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang  }
340716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang
341716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  bz_stream estream;
342716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  estream.next_in = (char*)patch_data + 32 + ctrl_len + data_len;
343716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  estream.avail_in = patch_size - (32 + ctrl_len + data_len);
344716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  estream.bzalloc = nullptr;
345716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  estream.bzfree = nullptr;
346716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  estream.opaque = nullptr;
347b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang  if ((bz2err = BZ2_bzDecompressInit(&estream, 0, 0)) != BZ_OK) {
348b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    fprintf(stderr, "Failed to bzinit extra stream (%d)\n", bz2err);
349b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    return 2;
350b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang  }
351716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang
352716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  uint64_t old_file_pos = 0;
353716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang
354b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang  if (!old_file->GetSize(&oldsize)) {
355b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    fprintf(stderr, "Cannot obtain the size of old file.\n");
356b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    return 1;
357b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang  }
358716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang
359437b7afd23768d737055fa70b79f5f2f714583a5Alex Deymo  // The oldpos can be negative, but the new pos is only incremented linearly.
360437b7afd23768d737055fa70b79f5f2f714583a5Alex Deymo  int64_t oldpos = 0;
361437b7afd23768d737055fa70b79f5f2f714583a5Alex Deymo  uint64_t newpos = 0;
3625b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang  std::vector<uint8_t> old_buf(1024 * 1024), new_buf(1024 * 1024);
363b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo  while (newpos < newsize) {
3645b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang    int64_t i;
365b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo    // Read control data.
366b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo    for (i = 0; i <= 2; i++) {
367b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang      if (!ReadBZ2(&cstream, buf, 8)) {
368b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang        fprintf(stderr, "Failed to read control stream.\n");
369b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang        return 2;
370b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang      }
371437b7afd23768d737055fa70b79f5f2f714583a5Alex Deymo      ctrl[i] = ParseInt64(buf);
3725b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang    }
373b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo
374b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo    // Sanity-check.
375b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    if (ctrl[0] < 0 || ctrl[1] < 0) {
376b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang      fprintf(stderr, "Corrupt patch.\n");
377b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang      return 2;
378b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    }
379b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo
380b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo    // Sanity-check.
381b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    if (newpos + ctrl[0] > newsize) {
382b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang      fprintf(stderr, "Corrupt patch.\n");
383b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang      return 2;
384b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    }
385b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo
386b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    int ret = 0;
387b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo    // Add old data to diff string. It is enough to fseek once, at
388b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo    // the beginning of the sequence, to avoid unnecessary overhead.
389b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo    if ((i = oldpos) < 0) {
3905b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang      // Write diff block directly to new file without adding old data,
3915b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang      // because we will skip part where |oldpos| < 0.
392b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang      ret = ReadBZ2AndWriteAll(new_file, &dstream, -i, new_buf.data(),
393b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang                               new_buf.size());
394b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang      if (ret)
395b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang        return ret;
396b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo      i = 0;
397b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo    }
3985b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang
399437b7afd23768d737055fa70b79f5f2f714583a5Alex Deymo    // We just checked that |i| is not negative.
400b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    if (static_cast<uint64_t>(i) != old_file_pos && !old_file->Seek(i)) {
401b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang      fprintf(stderr, "Error seeking input file to offset %" PRId64 ": %s\n", i,
402b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang              strerror(errno));
403b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang      return 1;
404b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    }
405b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo    if ((old_file_pos = oldpos + ctrl[0]) > oldsize)
406b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo      old_file_pos = oldsize;
407437b7afd23768d737055fa70b79f5f2f714583a5Alex Deymo
4085b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang    size_t chunk_size = old_file_pos - i;
409437b7afd23768d737055fa70b79f5f2f714583a5Alex Deymo    while (chunk_size > 0) {
410437b7afd23768d737055fa70b79f5f2f714583a5Alex Deymo      size_t read_bytes;
4115b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang      size_t bytes_to_read = std::min(chunk_size, old_buf.size());
412b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang      if (!old_file->Read(old_buf.data(), bytes_to_read, &read_bytes)) {
413b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang        perror("Error reading from input file");
414b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang        return 1;
415b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang      }
416b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang      if (!read_bytes) {
417b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang        fprintf(stderr, "EOF reached while reading from input file.\n");
418b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang        return 2;
419b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang      }
4205b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang      // Read same amount of bytes from diff block
421b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang      if (!ReadBZ2(&dstream, new_buf.data(), read_bytes)) {
422b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang        fprintf(stderr, "Failed to read diff stream.\n");
423b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang        return 2;
424b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang      }
425d87c83566c8411c16098dcc09ac56cce6007f9c6Sen Jiang      // new_buf already has data from diff block, adds old data to it.
426d87c83566c8411c16098dcc09ac56cce6007f9c6Sen Jiang      for (size_t k = 0; k < read_bytes; k++)
4275b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang        new_buf[k] += old_buf[k];
428b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang      if (!WriteAll(new_file, new_buf.data(), read_bytes)) {
429b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang        perror("Error writing to new file");
430b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang        return 1;
431b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang      }
432437b7afd23768d737055fa70b79f5f2f714583a5Alex Deymo      chunk_size -= read_bytes;
433b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo    }
434b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo
435b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo    // Adjust pointers.
436b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo    newpos += ctrl[0];
437b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo    oldpos += ctrl[0];
438b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo
4395b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang    if (oldpos > static_cast<int64_t>(oldsize)) {
4405b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang      // Write diff block directly to new file without adding old data,
4415b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang      // because we skipped part where |oldpos| > oldsize.
442b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang      ret = ReadBZ2AndWriteAll(new_file, &dstream, oldpos - oldsize,
443b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang                               new_buf.data(), new_buf.size());
444b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang      if (ret)
445b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang        return ret;
4465b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang    }
4475b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang
448b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo    // Sanity-check.
449b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    if (newpos + ctrl[1] > newsize) {
450b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang      fprintf(stderr, "Corrupt patch.\n");
451b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang      return 2;
452b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    }
453b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo
4545b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang    // Read extra block.
455b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    ret = ReadBZ2AndWriteAll(new_file, &estream, ctrl[1], new_buf.data(),
456b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang                             new_buf.size());
457b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    if (ret)
458b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang      return ret;
459b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo
460b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo    // Adjust pointers.
461b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo    newpos += ctrl[1];
462b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo    oldpos += ctrl[2];
4635b372b684ac4f9585fb2a00098d77f959bec0074Sen Jiang  }
464b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo
465b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo  // Close input file.
466437b7afd23768d737055fa70b79f5f2f714583a5Alex Deymo  old_file->Close();
467b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo
468b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo  // Clean up the bzip2 reads.
469716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  BZ2_bzDecompressEnd(&cstream);
470716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  BZ2_bzDecompressEnd(&dstream);
471716d569273ef2aeacfe7555f60f7784b2366225dSen Jiang  BZ2_bzDecompressEnd(&estream);
472b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo
473b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang  if (!new_file->Close()) {
474b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    perror("Error closing new file");
475b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang    return 1;
476b552c79a0d681f17ba19ff55e2062c483c236cc4Sen Jiang  }
477c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project
478b870eb5805202d3464e36f18060bdd4bcd367b30Alex Deymo  return 0;
479c285feace7a051368d4c5069cc6e0f30cd769f0dThe Android Open Source Project}
48020891f9c246ec36e6c148579522ac00051b64457Alex Deymo
48120891f9c246ec36e6c148579522ac00051b64457Alex Deymo}  // namespace bsdiff
482