xref: /OK3568_Linux_fs/external/recovery/update_engine/do_patch.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*-
2*4882a593Smuzhiyun  * Copyright 2003-2005 Colin Percival
3*4882a593Smuzhiyun  * All rights reserved
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Redistribution and use in source and binary forms, with or without
6*4882a593Smuzhiyun  * modification, are permitted providing that the following conditions
7*4882a593Smuzhiyun  * are met:
8*4882a593Smuzhiyun  * 1. Redistributions of source code must retain the above copyright
9*4882a593Smuzhiyun  *    notice, this list of conditions and the following disclaimer.
10*4882a593Smuzhiyun  * 2. Redistributions in binary form must reproduce the above copyright
11*4882a593Smuzhiyun  *    notice, this list of conditions and the following disclaimer in the
12*4882a593Smuzhiyun  *    documentation and/or other materials provided with the distribution.
13*4882a593Smuzhiyun  *
14*4882a593Smuzhiyun  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15*4882a593Smuzhiyun  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16*4882a593Smuzhiyun  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*4882a593Smuzhiyun  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18*4882a593Smuzhiyun  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*4882a593Smuzhiyun  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*4882a593Smuzhiyun  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*4882a593Smuzhiyun  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22*4882a593Smuzhiyun  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
23*4882a593Smuzhiyun  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24*4882a593Smuzhiyun  * POSSIBILITY OF SUCH DAMAGE.
25*4882a593Smuzhiyun  */
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #if 0
28*4882a593Smuzhiyun __FBSDID("$FreeBSD: src/usr.bin/bsdiff/bspatch/bspatch.c,v 1.1 2005/08/06 01:59:06 cperciva Exp $");
29*4882a593Smuzhiyun #endif
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun #include <bzlib.h>
32*4882a593Smuzhiyun #include <stdlib.h>
33*4882a593Smuzhiyun #include <stdio.h>
34*4882a593Smuzhiyun #include <string.h>
35*4882a593Smuzhiyun #include <err.h>
36*4882a593Smuzhiyun #include <unistd.h>
37*4882a593Smuzhiyun #include <fcntl.h>
38*4882a593Smuzhiyun #include <sys/types.h>
39*4882a593Smuzhiyun #include <sys/mman.h>
40*4882a593Smuzhiyun #include <sys/stat.h>
41*4882a593Smuzhiyun #include <limits.h>
42*4882a593Smuzhiyun #include <errno.h>
43*4882a593Smuzhiyun #include <stdbool.h>
44*4882a593Smuzhiyun #include "md5sum.h"
45*4882a593Smuzhiyun #include "log.h"
46*4882a593Smuzhiyun 
offtin(unsigned char * buf)47*4882a593Smuzhiyun static off_t offtin(unsigned char *buf)
48*4882a593Smuzhiyun {
49*4882a593Smuzhiyun     off_t y;
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun     y = buf[7] & 0x7F;
52*4882a593Smuzhiyun     y = y * 256; y += buf[6];
53*4882a593Smuzhiyun     y = y * 256; y += buf[5];
54*4882a593Smuzhiyun     y = y * 256; y += buf[4];
55*4882a593Smuzhiyun     y = y * 256; y += buf[3];
56*4882a593Smuzhiyun     y = y * 256; y += buf[2];
57*4882a593Smuzhiyun     y = y * 256; y += buf[1];
58*4882a593Smuzhiyun     y = y * 256; y += buf[0];
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun     if (buf[7] & 0x80) y = -y;
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun     return y;
63*4882a593Smuzhiyun }
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun /* Return:
66*4882a593Smuzhiyun  * -1 patching error,
67*4882a593Smuzhiyun  *  0 not a diff img,
68*4882a593Smuzhiyun  * >0 the new image size
69*4882a593Smuzhiyun  * dst_file size if patch successfully
70*4882a593Smuzhiyun  */
do_patch_rkimg(const char * img,ssize_t offset,ssize_t size,const char * blk_dev,const char * dst_file)71*4882a593Smuzhiyun int do_patch_rkimg(const char *img, ssize_t offset, ssize_t size,
72*4882a593Smuzhiyun                    const char *blk_dev, const char *dst_file)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun #define TAIL_SIZE   80
75*4882a593Smuzhiyun #define TID_HEAD    0
76*4882a593Smuzhiyun #define TID_NAME    1
77*4882a593Smuzhiyun #define TID_OLD_SIZE    2
78*4882a593Smuzhiyun #define TID_NEW_SIZE    3
79*4882a593Smuzhiyun #define TID_MD5SUM  4
80*4882a593Smuzhiyun #define TOKENS      5
81*4882a593Smuzhiyun #define MAGIC_TAIL  "DIFF"
82*4882a593Smuzhiyun #define MD5SUM_LEN  32
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun     // For tail parsing.
85*4882a593Smuzhiyun     // Tail size is 80 bytes as like,
86*4882a593Smuzhiyun     //   "DIFF:%-15s:%-12s:%-12s:%-32s:"
87*4882a593Smuzhiyun     //   $name $old_size $new_size $md5sum
88*4882a593Smuzhiyun     int fd_img;
89*4882a593Smuzhiyun     const char *split = ": "; //space is a split char too
90*4882a593Smuzhiyun     char tail[TAIL_SIZE];
91*4882a593Smuzhiyun     ssize_t len, ret;
92*4882a593Smuzhiyun     ssize_t oldsize, newsize;
93*4882a593Smuzhiyun     char *saveptr, *str, *name, *md5sum, *token[TOKENS];
94*4882a593Smuzhiyun     int j;
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun     // For patching
97*4882a593Smuzhiyun     FILE * f = NULL, * cpf = NULL, * dpf = NULL, * epf = NULL;
98*4882a593Smuzhiyun     BZFILE * cpfbz2, * dpfbz2, * epfbz2;
99*4882a593Smuzhiyun     int cbz2err, dbz2err, ebz2err;
100*4882a593Smuzhiyun     int fd;
101*4882a593Smuzhiyun     ssize_t bzctrllen, bzdatalen;
102*4882a593Smuzhiyun     unsigned char header[32], buf[8];
103*4882a593Smuzhiyun     unsigned char *old  = NULL, *new_ptr = NULL;
104*4882a593Smuzhiyun     off_t oldpos, newpos;
105*4882a593Smuzhiyun     off_t ctrl[3];
106*4882a593Smuzhiyun     off_t lenread;
107*4882a593Smuzhiyun     off_t i;
108*4882a593Smuzhiyun     struct stat old_stat, dst_stat;
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun     if ((fd_img = open(img, O_RDONLY, 0)) < 0) {
111*4882a593Smuzhiyun         LOGE("open %s failed\n", img);
112*4882a593Smuzhiyun         return -1;
113*4882a593Smuzhiyun     }
114*4882a593Smuzhiyun     if (lseek(fd_img, offset + size - TAIL_SIZE, SEEK_SET) < 0) {
115*4882a593Smuzhiyun         LOGE("%s: lseek to: %ld failed: %s\n", img,
116*4882a593Smuzhiyun              offset + size - TAIL_SIZE, strerror(errno));
117*4882a593Smuzhiyun         close(fd_img);
118*4882a593Smuzhiyun         return -1;
119*4882a593Smuzhiyun     }
120*4882a593Smuzhiyun     len = 0;
121*4882a593Smuzhiyun     while (len != TAIL_SIZE) {
122*4882a593Smuzhiyun         ret = read(fd_img, tail + len, TAIL_SIZE - len);
123*4882a593Smuzhiyun         if (ret < 0) {
124*4882a593Smuzhiyun             LOGE("read %s tail err\n", img);
125*4882a593Smuzhiyun             close(fd_img);
126*4882a593Smuzhiyun             return -1;
127*4882a593Smuzhiyun         }
128*4882a593Smuzhiyun         len += ret;
129*4882a593Smuzhiyun     }
130*4882a593Smuzhiyun     close(fd_img);
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun     tail[TAIL_SIZE - 1] = '\0';
133*4882a593Smuzhiyun     for (j = 0, str = tail; j < TOKENS; j++, str = NULL) {
134*4882a593Smuzhiyun         token[j] = strtok_r(str, split, &saveptr);
135*4882a593Smuzhiyun         if (token[j] == NULL)
136*4882a593Smuzhiyun             break;
137*4882a593Smuzhiyun     }
138*4882a593Smuzhiyun     name = token[TID_NAME];
139*4882a593Smuzhiyun     md5sum = token[TID_MD5SUM];
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun     /* When unexpected reboot during patching/writing happened,
142*4882a593Smuzhiyun      * if dst_file is in correct state, then old image may already broken
143*4882a593Smuzhiyun      */
144*4882a593Smuzhiyun     if (stat(dst_file, &dst_stat) == 0 &&
145*4882a593Smuzhiyun         compareMd5sum(dst_file, (unsigned char *)md5sum, 0, dst_stat.st_size)) {
146*4882a593Smuzhiyun         LOGI("Recovery from unecptected reboot successfully.");
147*4882a593Smuzhiyun         return dst_stat.st_size;
148*4882a593Smuzhiyun     }
149*4882a593Smuzhiyun     /* If dst_file exist but md5sum is wrong, old image file is clean, hopefully */
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun     //check tail magic, return 0 if not exist
152*4882a593Smuzhiyun     if (j == 0 || strncmp(MAGIC_TAIL, token[TID_HEAD], strlen(MAGIC_TAIL)) != 0) {
153*4882a593Smuzhiyun         LOGW("Not a diff image, ret = %ld\n", ret);
154*4882a593Smuzhiyun         return 0;
155*4882a593Smuzhiyun     }
156*4882a593Smuzhiyun     LOGI("This is a diff image, patching...\n");
157*4882a593Smuzhiyun     if (j != TOKENS ||
158*4882a593Smuzhiyun         (oldsize = strtol(token[TID_OLD_SIZE], &saveptr, 10)) == 0 ||
159*4882a593Smuzhiyun         (errno == ERANGE && (oldsize == LONG_MAX || oldsize == LONG_MIN)) ||
160*4882a593Smuzhiyun         saveptr == token[TID_OLD_SIZE] ||
161*4882a593Smuzhiyun         (newsize = strtol(token[TID_NEW_SIZE], &saveptr, 10)) == 0 ||
162*4882a593Smuzhiyun         (errno == ERANGE && (newsize == LONG_MAX || newsize == LONG_MIN)) ||
163*4882a593Smuzhiyun         saveptr == token[TID_NEW_SIZE] ||
164*4882a593Smuzhiyun         strlen(token[TID_MD5SUM]) != MD5SUM_LEN) {
165*4882a593Smuzhiyun         LOGE("Bad Tail header of bsdiff patch\n");
166*4882a593Smuzhiyun         return -1;
167*4882a593Smuzhiyun     }
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun     //TODO: check dst_file dir size, return -1 if space too small.
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun     /* Open patch file */
172*4882a593Smuzhiyun     if ((f = fopen(img, "r")) == NULL) {
173*4882a593Smuzhiyun         LOGE("fopen %s err\n", img);
174*4882a593Smuzhiyun         return -1;
175*4882a593Smuzhiyun     }
176*4882a593Smuzhiyun     if (fseeko(f, offset, SEEK_SET)) {
177*4882a593Smuzhiyun         LOGE("fseeko %s err\n", img);
178*4882a593Smuzhiyun         fclose(f);
179*4882a593Smuzhiyun         return -1;
180*4882a593Smuzhiyun     }
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun     /*
183*4882a593Smuzhiyun     File format:
184*4882a593Smuzhiyun         0   8   "BSDIFF40"
185*4882a593Smuzhiyun         8   8   X
186*4882a593Smuzhiyun         16  8   Y
187*4882a593Smuzhiyun         24  8   sizeof(newfile)
188*4882a593Smuzhiyun         32  X   bzip2(control block)
189*4882a593Smuzhiyun         32+X    Y   bzip2(diff block)
190*4882a593Smuzhiyun         32+X+Y  ??? bzip2(extra block)
191*4882a593Smuzhiyun     with control block a set of triples (x,y,z) meaning "add x bytes
192*4882a593Smuzhiyun     from oldfile to x bytes from the diff block; copy y bytes from the
193*4882a593Smuzhiyun     extra block; seek forwards in oldfile by z bytes".
194*4882a593Smuzhiyun     */
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun     /* Read header */
197*4882a593Smuzhiyun     if (fread(header, 1, 32, f) < 32) {
198*4882a593Smuzhiyun         LOGE("Read header err\n");
199*4882a593Smuzhiyun         fclose(f);
200*4882a593Smuzhiyun         return -1;
201*4882a593Smuzhiyun     }
202*4882a593Smuzhiyun     fclose(f);
203*4882a593Smuzhiyun     f = NULL;
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun     /* Check for appropriate magic */
206*4882a593Smuzhiyun     if (memcmp(header, "BSDIFF40", 8) != 0) {
207*4882a593Smuzhiyun         LOGE("Bad header, Corrupt patch\n");
208*4882a593Smuzhiyun         return -1;
209*4882a593Smuzhiyun     }
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun     /* Read lengths from header */
212*4882a593Smuzhiyun     bzctrllen = offtin(header + 8);
213*4882a593Smuzhiyun     bzdatalen = offtin(header + 16);
214*4882a593Smuzhiyun     newsize = offtin(header + 24);
215*4882a593Smuzhiyun     if ((bzctrllen < 0) || (bzdatalen < 0) || (newsize <= 0)) {
216*4882a593Smuzhiyun         LOGE("Bad header len, Corrupt patch\n");
217*4882a593Smuzhiyun         return -1;
218*4882a593Smuzhiyun     }
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun     /* re-open patch file via libbzip2 at the right places */
221*4882a593Smuzhiyun     if ((cpf = fopen(img, "r")) == NULL)
222*4882a593Smuzhiyun         return -1;
223*4882a593Smuzhiyun     if (fseeko(cpf, offset + 32, SEEK_SET)) {
224*4882a593Smuzhiyun         LOGE("fseeko(%s, %lld) err\n", img, (long long)(32 + offset));
225*4882a593Smuzhiyun         goto cleanup;
226*4882a593Smuzhiyun     }
227*4882a593Smuzhiyun     if ((cpfbz2 = BZ2_bzReadOpen(&cbz2err, cpf, 0, 0, NULL, 0)) == NULL) {
228*4882a593Smuzhiyun         LOGE("BZ2_bzReadOpen, bz2err = %d, err\n", cbz2err);
229*4882a593Smuzhiyun         goto cleanup;
230*4882a593Smuzhiyun     }
231*4882a593Smuzhiyun     if ((dpf = fopen(img, "r")) == NULL)
232*4882a593Smuzhiyun         goto cleanup;
233*4882a593Smuzhiyun     if (fseeko(dpf, offset + 32 + bzctrllen, SEEK_SET)) {
234*4882a593Smuzhiyun         LOGE("fseeko(%s, %lld) err\n", img,
235*4882a593Smuzhiyun              (long long)(offset + 32 + bzctrllen));
236*4882a593Smuzhiyun         goto cleanup;
237*4882a593Smuzhiyun     }
238*4882a593Smuzhiyun     if ((dpfbz2 = BZ2_bzReadOpen(&dbz2err, dpf, 0, 0, NULL, 0)) == NULL) {
239*4882a593Smuzhiyun         LOGE("BZ2_bzReadOpen, bz2err = %d, err\n", dbz2err);
240*4882a593Smuzhiyun         goto cleanup;
241*4882a593Smuzhiyun     }
242*4882a593Smuzhiyun     if ((epf = fopen(img, "r")) == NULL) {
243*4882a593Smuzhiyun         LOGE("fopen(%s) err\n", img);
244*4882a593Smuzhiyun         goto cleanup;
245*4882a593Smuzhiyun     }
246*4882a593Smuzhiyun     if (fseeko(epf, offset + 32 + bzctrllen + bzdatalen, SEEK_SET)) {
247*4882a593Smuzhiyun         LOGE("fseeko(%s, %lld) err\n", img,
248*4882a593Smuzhiyun              (long long)(offset + 32 + bzctrllen + bzdatalen));
249*4882a593Smuzhiyun         goto cleanup;
250*4882a593Smuzhiyun     }
251*4882a593Smuzhiyun     if ((epfbz2 = BZ2_bzReadOpen(&ebz2err, epf, 0, 0, NULL, 0)) == NULL) {
252*4882a593Smuzhiyun         LOGE("BZ2_bzReadOpen, bz2err = %d\n", ebz2err);
253*4882a593Smuzhiyun         goto cleanup;
254*4882a593Smuzhiyun     }
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun     if (((fd = open(blk_dev, O_RDONLY, 0)) < 0) ||
257*4882a593Smuzhiyun         ((old = (unsigned char *)mmap(NULL, oldsize, PROT_READ,
258*4882a593Smuzhiyun                                       MAP_SHARED | MAP_POPULATE, fd, 0)) == MAP_FAILED)) {
259*4882a593Smuzhiyun         LOGE("open %s err\n", blk_dev);
260*4882a593Smuzhiyun         goto cleanup;
261*4882a593Smuzhiyun     }
262*4882a593Smuzhiyun     close(fd);
263*4882a593Smuzhiyun     fd = -1;
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun     /* mmap the new file */
266*4882a593Smuzhiyun     if (((fd = open(dst_file, O_CREAT | O_TRUNC | O_RDWR, 0666)) < 0) ||
267*4882a593Smuzhiyun         (lseek(fd, newsize - 1, SEEK_SET) != (newsize - 1)) ||
268*4882a593Smuzhiyun         (write(fd, "E", 1) != 1) ||
269*4882a593Smuzhiyun         (lseek(fd, 0, SEEK_SET) != 0) ||
270*4882a593Smuzhiyun         ((new_ptr = (unsigned char *)mmap(NULL, newsize, PROT_READ | PROT_WRITE,
271*4882a593Smuzhiyun                                           MAP_SHARED, fd, 0)) == MAP_FAILED)) {
272*4882a593Smuzhiyun         LOGE("mmap %s err\n", dst_file);
273*4882a593Smuzhiyun         goto cleanup;
274*4882a593Smuzhiyun     }
275*4882a593Smuzhiyun     close(fd);
276*4882a593Smuzhiyun     fd = -1;
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun     oldpos = 0; newpos = 0;
279*4882a593Smuzhiyun     while (newpos < newsize) {
280*4882a593Smuzhiyun         /* Read control data */
281*4882a593Smuzhiyun         for (i = 0; i <= 2; i++) {
282*4882a593Smuzhiyun             lenread = BZ2_bzRead(&cbz2err, cpfbz2, buf, 8);
283*4882a593Smuzhiyun             if ((lenread < 8) || ((cbz2err != BZ_OK) &&
284*4882a593Smuzhiyun                                   (cbz2err != BZ_STREAM_END))) {
285*4882a593Smuzhiyun                 LOGE("Read control data: Corrupt patch\n");
286*4882a593Smuzhiyun                 goto cleanup;
287*4882a593Smuzhiyun             }
288*4882a593Smuzhiyun             ctrl[i] = offtin(buf);
289*4882a593Smuzhiyun         };
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun         /* Sanity-check */
292*4882a593Smuzhiyun         if (newpos + ctrl[0] > newsize) {
293*4882a593Smuzhiyun             LOGE("Sanity-check: Corrupt patch\n");
294*4882a593Smuzhiyun             goto cleanup;
295*4882a593Smuzhiyun         }
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun         /* Read diff string */
298*4882a593Smuzhiyun         lenread = BZ2_bzRead(&dbz2err, dpfbz2, new_ptr + newpos, ctrl[0]);
299*4882a593Smuzhiyun         if ((lenread < ctrl[0]) ||
300*4882a593Smuzhiyun             ((dbz2err != BZ_OK) && (dbz2err != BZ_STREAM_END))) {
301*4882a593Smuzhiyun             LOGE("Read diff string: Corrupt patch\n");
302*4882a593Smuzhiyun             goto cleanup;
303*4882a593Smuzhiyun         }
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun         /* Add old data to diff string */
306*4882a593Smuzhiyun         for (i = 0; i < ctrl[0]; i++)
307*4882a593Smuzhiyun             if ((oldpos + i >= 0) && (oldpos + i < oldsize))
308*4882a593Smuzhiyun                 new_ptr[newpos + i] += old[oldpos + i];
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun         /* Adjust pointers */
311*4882a593Smuzhiyun         newpos += ctrl[0];
312*4882a593Smuzhiyun         oldpos += ctrl[0];
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun         /* Sanity-check */
315*4882a593Smuzhiyun         if (newpos + ctrl[1] > newsize) {
316*4882a593Smuzhiyun             LOGE("Sanity-check: Corrupt patch\n");
317*4882a593Smuzhiyun             goto cleanup;
318*4882a593Smuzhiyun         }
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun         /* Read extra string */
321*4882a593Smuzhiyun         lenread = BZ2_bzRead(&ebz2err, epfbz2, new_ptr + newpos, ctrl[1]);
322*4882a593Smuzhiyun         if ((lenread < ctrl[1]) ||
323*4882a593Smuzhiyun             ((ebz2err != BZ_OK) && (ebz2err != BZ_STREAM_END))) {
324*4882a593Smuzhiyun             LOGE("Read extra string: Corrupt patch\n");
325*4882a593Smuzhiyun             goto cleanup;
326*4882a593Smuzhiyun         }
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun         /* Adjust pointers */
329*4882a593Smuzhiyun         newpos += ctrl[1];
330*4882a593Smuzhiyun         oldpos += ctrl[2];
331*4882a593Smuzhiyun     };
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun     /* Clean up the bzip2 reads */
334*4882a593Smuzhiyun     BZ2_bzReadClose(&cbz2err, cpfbz2);
335*4882a593Smuzhiyun     BZ2_bzReadClose(&dbz2err, dpfbz2);
336*4882a593Smuzhiyun     BZ2_bzReadClose(&ebz2err, epfbz2);
337*4882a593Smuzhiyun     fclose(cpf);
338*4882a593Smuzhiyun     fclose(dpf);
339*4882a593Smuzhiyun     fclose(epf);
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun     munmap(new_ptr, newsize);
342*4882a593Smuzhiyun     munmap(old, oldsize);
343*4882a593Smuzhiyun     sync();
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun     //check md5sum
346*4882a593Smuzhiyun     if (!compareMd5sum(dst_file, (unsigned char *)md5sum, 0, newsize))
347*4882a593Smuzhiyun         return -1;
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun     LOGI("Diff patch apply successfully for %s, size: %ld\n",
350*4882a593Smuzhiyun          name, newsize);
351*4882a593Smuzhiyun     return newsize;
352*4882a593Smuzhiyun cleanup:
353*4882a593Smuzhiyun     if (new_ptr != NULL)
354*4882a593Smuzhiyun         munmap(new_ptr, newsize);
355*4882a593Smuzhiyun     if (old != NULL)
356*4882a593Smuzhiyun         munmap(old, oldsize);
357*4882a593Smuzhiyun     if (fd >= 0)
358*4882a593Smuzhiyun         close(fd);
359*4882a593Smuzhiyun     if (cpf != NULL)
360*4882a593Smuzhiyun         fclose(cpf);
361*4882a593Smuzhiyun     if (dpf != NULL)
362*4882a593Smuzhiyun         fclose(dpf);
363*4882a593Smuzhiyun     if (epf != NULL)
364*4882a593Smuzhiyun         fclose(epf);
365*4882a593Smuzhiyun     return -1;
366*4882a593Smuzhiyun }
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun #if 0
369*4882a593Smuzhiyun int main(int argc, char *argv[])
370*4882a593Smuzhiyun {
371*4882a593Smuzhiyun     do_patch_rkimg("./update.img", 676276, 16964, "OLD/Image/uboot.img", "uboot.img");
372*4882a593Smuzhiyun     do_patch_rkimg("./update.img", 672180, 3589, "OLD/Image/trust.img", "trust.img");
373*4882a593Smuzhiyun     do_patch_rkimg("./update.img", 743860, 532546, "OLD/Image/boot.img", "boot.img");
374*4882a593Smuzhiyun     do_patch_rkimg("./update.img", 15630772, 88186412, "OLD/Image/rootfs.img", "rootfs.img");
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun     return 0;
377*4882a593Smuzhiyun }
378*4882a593Smuzhiyun #endif
379