2 * Copyright 2003-2005 Colin Percival
3 * Copyright 2012 Matthew Endsley
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted providing that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
27 * Modifications are made in reimplementing suffix sort array generation
28 * and how the data is read and written to.Iterative part replaced the
29 * recursive implementation to avoid buffer overflow problems
31 //#define ZLIB_MOD //not stable yet.
32 //#define MAX_MATCH_SIZE // define ( MAX_MATCH_SIZE or CONST_MEMORY_USAGE ) or ( none of them )
33 #define CONST_MEMORY_USAGE (64*1024) //tests show smallest time when using 64 kb
34 #define PATCH_FILE_FORMAT_MOD
35 #define BSDIFF_HEADER "BSDIFF40"
36 #define SSDIFF_HEADER "SSDIFF40"
37 //#define MULTI_THREADING
48 #include <7zVersion.h>
52 static void *SzAlloc(void *p, size_t size)
58 static void SzFree(void *p, void *address)
63 ISzAlloc g_Alloc = { SzAlloc, SzFree };
65 static off_t offtin(u_char *buf)
91 #define IN_BUF_SIZE (1 << 16)
92 #define OUT_BUF_SIZE (1 << 16)
94 SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inStream,
95 UInt64 *unpackSize, unsigned char *dec_data)
97 int thereIsSize = (*unpackSize != (UInt64)(Int64) - 1);
99 Byte inBuf[IN_BUF_SIZE];
100 Byte outBuf[OUT_BUF_SIZE];
101 size_t inPos = 0, inSize = 0, outPos = 0;
108 if (inPos == inSize) {
109 inSize = IN_BUF_SIZE;
110 RINOK(inStream->Read(inStream, inBuf, &inSize));
115 SizeT inProcessed = inSize - inPos;
116 SizeT outProcessed = OUT_BUF_SIZE - outPos;
117 ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
120 if (thereIsSize && outProcessed > *unpackSize) {
121 outProcessed = (SizeT) * unpackSize;
122 finishMode = LZMA_FINISH_END;
125 res = LzmaDec_DecodeToBuf(state, outBuf + outPos, &outProcessed,
126 inBuf + inPos, &inProcessed, finishMode, &status);
127 inPos += inProcessed;
128 outPos += outProcessed;
129 *unpackSize -= outProcessed;
130 memcpy(dec_data + offset, outBuf, outProcessed);
131 offset += outProcessed;
135 if ((res != SZ_OK) || (thereIsSize && *unpackSize == 0))
138 if (inProcessed == 0 && outProcessed == 0) {
139 if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK)
140 return SZ_ERROR_DATA;
146 int apply_patch(const char *oldfile, unsigned char *patch_buffer, unsigned char **dest_buf, ssize_t *dest_size)
148 int fd = -1, result = 0;
149 off_t oldsize, newsize;
150 u_char header[16], buf[8];
152 off_t oldpos, newpos;
153 off_t ctrl[4]; /////////////////////////////////////THREAD
154 off_t total_write; /////////////////////////////////////////THREAD
156 off_t memory_usage = CONST_MEMORY_USAGE;
158 off_t patch_buffer_offset = 0;
167 32 X bzip2(control block)
168 32+X Y bzip2(diff block)
169 32+X+Y ??? bzip2(extra block)
170 with control block a set of triples (x,y,z) meaning "add x bytes
171 from oldfile to x bytes from the diff block; copy y bytes from the
172 extra block; seek forwards in oldfile by z bytes".
176 memcpy(header, patch_buffer, 16);
178 printf("%s().%d Corrupt decoded patch buffer\n", __FUNCTION__, __LINE__);
182 /* Check for appropriate magic */
183 if (memcmp(header, BSDIFF_HEADER, 8) != 0 && memcmp(header, SSDIFF_HEADER, 8) != 0) {
184 printf("%s().%d Patch buffer header corrupt\n", __FUNCTION__, __LINE__);
188 /* Read lengths from header */
189 newsize = offtin(header + 8);
192 printf("%s().%d Patch buffer corrupt\n", __FUNCTION__, __LINE__);
196 /* Cset patch_buffer_offset at the right place */
197 patch_buffer_offset += 16;
199 if (((fd = open(oldfile, O_RDONLY, 0)) < 0) ||
200 ((oldsize = lseek(fd, 0, SEEK_END)) == -1) ||
201 ((old = malloc(memory_usage + 1)) == NULL) ||
202 (lseek(fd, 0, SEEK_SET) != 0)) {
203 printf("Corruption in old file %s\n", oldfile);
208 if ((*dest_buf = malloc(newsize + 1)) == NULL) {
209 printf("Corruption in old file %s\n", oldfile);
218 while (total_write != newsize) {
219 /* Read control data */
220 for (j = 0; j <= 3; j++) {
221 memcpy(buf, patch_buffer + patch_buffer_offset, 8);
222 patch_buffer_offset += 8;
223 ctrl[j] = offtin(buf);
226 total_write += (ctrl[0] + ctrl[1]);
230 //////////////////////////////////////////////////////////////////////////////////
232 match_size = ctrl[0];
233 while (flag == true) {
234 if (match_size <= memory_usage) {
235 if (pread(fd, old, match_size, oldpos) != match_size) {
236 printf("Corruption in old file %s\n", oldfile);
240 if (newpos + match_size > newsize) {
241 printf("%s().%d Corrupt patch\n", __FUNCTION__, __LINE__);
245 memcpy((*dest_buf) + newpos, patch_buffer + patch_buffer_offset, match_size);
246 patch_buffer_offset += match_size;
247 for (j = 0; j < match_size; j++)
248 (*dest_buf)[newpos + j] += old[j];
249 newpos += match_size;
252 if (pread(fd, old, memory_usage, oldpos) != memory_usage) {
253 printf("%s().%d Corruption in old file %s\n", __FUNCTION__, __LINE__ , oldfile);
257 if (newpos + memory_usage > newsize) {
258 printf("%s().%d Corrupt patch\n", __FUNCTION__, __LINE__);
262 memcpy((*dest_buf) + newpos, patch_buffer + patch_buffer_offset, memory_usage);
263 patch_buffer_offset += memory_usage;
264 for (j = 0; j < memory_usage; j++)
265 (*dest_buf)[newpos + j] += old[j];
266 match_size -= memory_usage;
267 oldpos += memory_usage;
268 newpos += memory_usage;
272 ////////////////////////////////////////////////////////////////////////////////////////
274 if (newpos + ctrl[1] > newsize) {
275 printf("%s().%d Corrupt patch\n", __FUNCTION__, __LINE__);
279 /* Read extra string */
280 memcpy((*dest_buf) + newpos, patch_buffer + patch_buffer_offset, ctrl[1]);
281 patch_buffer_offset += ctrl[1];
283 *dest_size = newsize;