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