Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(111)

Side by Side Diff: chrome/installer/mac/third_party/bsdiff/goobspatch.c

Issue 2716005: Modify bsdiff 4.3 to goobsdiff, which is appropriate for use as the Mac binary differ/patcher (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/installer/mac/third_party/bsdiff/goobsdiff.gyp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /*- 1 /*-
2 * Copyright 2003-2005 Colin Percival 2 * Copyright 2003-2005 Colin Percival
3 * All rights reserved 3 * All rights reserved
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted providing that the following conditions 6 * modification, are permitted providing that the following conditions
7 * are met: 7 * are met:
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 10 matching lines...) Expand all
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 22 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
23 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 23 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE. 24 * POSSIBILITY OF SUCH DAMAGE.
25 */ 25 */
26 26
27 #if 0 27 #if 0
28 __FBSDID("$FreeBSD: src/usr.bin/bsdiff/bspatch/bspatch.c,v 1.1 2005/08/06 01:59: 06 cperciva Exp $"); 28 __FBSDID("$FreeBSD: src/usr.bin/bsdiff/bspatch/bspatch.c,v 1.1 2005/08/06 01:59: 06 cperciva Exp $");
29 #endif 29 #endif
30 30
31 #include <sys/types.h>
32
31 #include <bzlib.h> 33 #include <bzlib.h>
34 #include <err.h>
35 #include <fcntl.h>
32 #include <stdlib.h> 36 #include <stdlib.h>
33 #include <stdio.h> 37 #include <stdio.h>
34 #include <string.h> 38 #include <string.h>
35 #include <err.h> 39 #include <openssl/sha.h>
36 #include <unistd.h> 40 #include <unistd.h>
37 #include <fcntl.h> 41 #include <zlib.h>
38 42
39 static off_t offtin(u_char *buf) 43 #if defined(__APPLE__)
40 { 44 #include <libkern/OSByteOrder.h>
41 » off_t y; 45 #define le64toh(x) OSSwapLittleToHostInt64(x)
42 46 #elif defined(__linux__)
43 » y=buf[7]&0x7F; 47 #include <endian.h>
44 » y=y*256;y+=buf[6]; 48 #elif defined(_WIN32) && (defined(_M_IX86) || defined(_M_X64))
45 » y=y*256;y+=buf[5]; 49 #define le64toh(x) (x)
46 » y=y*256;y+=buf[4]; 50 #else
47 » y=y*256;y+=buf[3]; 51 #error Provide le64toh for this platform
48 » y=y*256;y+=buf[2]; 52 #endif
49 » y=y*256;y+=buf[1]; 53
50 » y=y*256;y+=buf[0]; 54 static inline off_t offtin(u_char *buf)
51 55 {
52 » if(buf[7]&0x80) y=-y; 56 » return le64toh(*((off_t*)buf));
53 57 }
54 » return y; 58
59 static void sha1tostr(const u_char *sha1, char *sha1str)
60 {
61 » int i;
62 » for (i = 0; i < SHA_DIGEST_LENGTH; ++i)
63 » » sprintf(&sha1str[i * 2], "%02x", sha1[i]);
64 }
65
66 /* cfile is a uniform interface to read from maybe-compressed files. */
67
68 typedef struct {
69 » FILE *f; /* method = 1, 2 */
70 » union {
71 » » BZFILE *bz2; /* method = 2 */
72 » » gzFile gz; /* method = 3 */
73 » } u;
74 » const char *tag;
75 » unsigned char method;
76 } cfile;
77
78 /* Opens a file at path, seeks to offset off, and prepares for reading using
79 * the specified method. Supported methods are plain uncompressed (1), bzip2
80 * (2), and gzip (3). tag is used as an identifier for error reporting. */
81 static void cfopen(cfile *cf, const char *path, off_t off,
82 const char *tag, unsigned char method)
83 {
84 » int fd;
85 » int zerr;
86
87 » if (method == 1 || method == 2) {
88 » » /* Use stdio for uncompressed files. The bzip interface also
89 » » * sits on top of a stdio FILE* but does not take "ownership"
90 » » * of the FILE*. */
91 » » if ((cf->f = fopen(path, "rb")) == NULL)
92 » » » err(1, "fdopen(%s)", tag);
93 » » if ((fseeko(cf->f, off, SEEK_SET)) != 0)
94 » » » err(1, "fseeko(%s, %lld)", tag, off);
95 » » if (method == 2) {
96 » » » if ((cf->u.bz2 = BZ2_bzReadOpen(&zerr, cf->f, 0, 0,
97 » » » NULL, 0)) == NULL)
98 » » » » errx(1, "BZ2_bzReadOpen(%s): %d", tag, zerr);
99 » » }
100 » } else if (method == 3) {
101 » » if ((fd = open(path, O_RDONLY)) < 0)
102 » » » err(1, "open(%s)", tag);
103 » » if (lseek(fd, off, SEEK_SET) != off)
104 » » » err(1, "lseek(%s, %lld)", tag, off);
105 » » if ((cf->u.gz = gzdopen(fd, "rb")) == NULL)
106 » » » errx(1, "gzdopen(%s)", tag);
107 » } else {
108 » » errx(1, "cfopen(%s): unknown method %d", tag, method);
109 » }
110
111 » cf->tag = tag;
112 » cf->method = method;
113 }
114
115 static void cfclose(cfile *cf)
116 {
117 » int zerr;
118
119 » if (cf->method == 1 || cf->method == 2) {
120 » » if (cf->method == 2) {
121 » » » zerr = BZ_OK;
122 » » » BZ2_bzReadClose(&zerr, cf->u.bz2);
123 » » » if (zerr != BZ_OK)
124 » » » » errx(1, "BZ2_bzReadClose(%s): %d\n",
125 » » » » cf->tag, zerr);
126 » » }
127 » » if (fclose(cf->f) != 0)
128 » » » err(1, "fclose(%s)", cf->tag);
129 » } else if (cf->method == 3) {
130 » » if ((zerr = gzclose(cf->u.gz)) != Z_OK)
131 » » » errx(1, "gzclose(%s): %d", cf->tag, zerr);
132 » } else {
133 » » errx(1, "cfclose(%s): unknown method %d", cf->tag, cf->method);
134 » }
135 }
136
137 static void cfread(cfile *cf, u_char *buf, size_t len)
138 {
139 » size_t nread;
140 » int zerr;
141
142 » if (cf->method == 1) {
143 » » if ((nread = fread(buf, 1, len, cf->f)) != len) {
144 » » » if (!ferror(cf->f))
145 » » » » errx(1, "fread(%s, %zd): short read %zd",
146 » » » » cf->tag, len, nread);
147 » » » err(1, "fread(%s, %zd)", cf->tag, len);
148 » » }
149 » } else if (cf->method == 2) {
150 » » zerr = BZ_OK;
151 » » if ((nread = BZ2_bzRead(&zerr, cf->u.bz2, buf, len)) != len) {
152 » » » if (zerr == BZ_OK)
153 » » » » errx(1, "BZ2_bzRead(%s, %zd): short read %zd",
154 » » » » cf->tag, len, nread);
155 » » » errx(1, "BZ2_bzRead(%s, %zd): %d", cf->tag, len, zerr);
156 » » }
157 » } else if (cf->method == 3) {
158 » » if ((nread = gzread(cf->u.gz, buf, len)) != len) {
159 » » » zerr = Z_OK;
160 » » » gzerror(cf->u.gz, &zerr);
161 » » » if (zerr == Z_OK)
162 » » » » errx(1, "gzread(%s, %zd): short read %zd",
163 » » » » cf->tag, len, nread);
164 » » » errx(1, "gzread(%s, %zd): %d", cf->tag, len, zerr);
165 » » }
166 » } else {
167 » » errx(1, "cfread(%s, %zd): unknown method %d",
168 » » cf->tag, len, cf->method);
169 » }
55 } 170 }
56 171
57 int main(int argc,char * argv[]) 172 int main(int argc,char * argv[])
58 { 173 {
59 » FILE * f, * cpf, * dpf, * epf; 174 » FILE * f;
60 » BZFILE * cpfbz2, * dpfbz2, * epfbz2; 175 » cfile cf, df, ef;
61 » int cbz2err, dbz2err, ebz2err;
62 int fd; 176 int fd;
63 » ssize_t oldsize,newsize; 177 » off_t expect_oldsize, oldsize, newsize, patchsize;
64 » ssize_t bzctrllen,bzdatalen; 178 » off_t zctrllen, zdatalen, zextralen;
65 » u_char header[32],buf[8]; 179 » u_char header[96], buf[8];
66 u_char *old, *new; 180 u_char *old, *new;
67 off_t oldpos,newpos; 181 off_t oldpos,newpos;
68 off_t ctrl[3]; 182 off_t ctrl[3];
69 off_t lenread;
70 off_t i; 183 off_t i;
71 184 » u_char sha1[SHA_DIGEST_LENGTH];
72 » if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]); 185 » char sha1str[SHA_DIGEST_LENGTH * 2 + 1];
186 » char expected_sha1str[SHA_DIGEST_LENGTH * 2 + 1];
187
188 » if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile",argv[0]);
73 189
74 /* Open patch file */ 190 /* Open patch file */
75 » if ((f = fopen(argv[3], "r")) == NULL) 191 » if ((f = fopen(argv[3], "rb")) == NULL)
76 err(1, "fopen(%s)", argv[3]); 192 err(1, "fopen(%s)", argv[3]);
77 193
78 /* 194 /*
79 File format: 195 File format:
80 » » 0» 8» "BSDIFF40" 196 » » 0» 8» "BSDIFF4G"
81 » » 8» 8» X 197 » » 8» 8» length of compressed control block (x)
82 » » 16» 8» Y 198 » » 16» 8» length of compressed diff block (y)
83 » » 24» 8» sizeof(newfile) 199 » » 24» 8» length of compressed extra block (z)
84 » » 32» X» bzip2(control block) 200 » » 32» 8» length of old file
85 » » 32+X» Y» bzip2(diff block) 201 » » 40» 8» length of new file
86 » » 32+X+Y» ???» bzip2(extra block) 202 » » 48» 20» SHA1 of old file
87 » with control block a set of triples (x,y,z) meaning "add x bytes 203 » » 68» 20» SHA1 of new file
204 » » 88» 1» encoding of control block
205 » » 89» 1» encoding of diff block
206 » » 90» 1» encoding of extra block
207 » » 91» 5» unused
208 » » 96» x» compressed control block
209 » » 96+x» y» compressed diff block
210 » » 96+x+y» z» compressed extra block
211 » Encodings are 1 (uncompressed), 2 (bzip2), and 3 (gzip).
212 » The control block is a set of triples (x,y,z) meaning "add x bytes
88 from oldfile to x bytes from the diff block; copy y bytes from the 213 from oldfile to x bytes from the diff block; copy y bytes from the
89 extra block; seek forwards in oldfile by z bytes". 214 extra block; seek forwards in oldfile by z bytes".
90 */ 215 */
91 216
92 /* Read header */ 217 /* Read header */
93 » if (fread(header, 1, 32, f) < 32) { 218 » if (fread(header, 1, sizeof(header), f) < sizeof(header)) {
94 if (feof(f)) 219 if (feof(f))
95 » » » errx(1, "Corrupt patch\n"); 220 » » » errx(1, "corrupt patch (header size)");
96 err(1, "fread(%s)", argv[3]); 221 err(1, "fread(%s)", argv[3]);
97 } 222 }
98 223
99 /* Check for appropriate magic */ 224 /* Check for appropriate magic */
100 » if (memcmp(header, "BSDIFF40", 8) != 0) 225 » if (memcmp(header, "BSDIFF4G", 8) != 0)
101 » » errx(1, "Corrupt patch\n"); 226 » » errx(1, "corrupt patch (magic)");
102 227
103 /* Read lengths from header */ 228 /* Read lengths from header */
104 » bzctrllen=offtin(header+8); 229 » zctrllen = offtin(header + 8);
105 » bzdatalen=offtin(header+16); 230 » zdatalen = offtin(header + 16);
106 » newsize=offtin(header+24); 231 » zextralen = offtin(header + 24);
107 » if((bzctrllen<0) || (bzdatalen<0) || (newsize<0)) 232 » expect_oldsize = offtin(header + 32);
108 » » errx(1,"Corrupt patch\n"); 233 » newsize = offtin(header + 40);
109 234 » if (zctrllen < 0 || zdatalen < 0 || zextralen < 0)
110 » /* Close patch file and re-open it via libbzip2 at the right places */ 235 » » errx(1, "corrupt patch (stream sizes)");
236 » if (expect_oldsize < 0 || newsize < 0)
237 » » errx(1, "corrupt patch (file sizes)");
238
239 » if (fseeko(f, 0, SEEK_END) != 0 || (patchsize = ftello(f)) < 0)
240 » » err(1, "fseeko/ftello(%s)", argv[3]);
241 » if (patchsize != sizeof(header) + zctrllen + zdatalen + zextralen)
242 » » errx(1, "corrupt patch (patch size)");
243
244 » cfopen(&cf, argv[3], sizeof(header), "control", header[88]);
245 » cfopen(&df, argv[3], sizeof(header) + zctrllen, "diff", header[89]);
246 » cfopen(&ef, argv[3], sizeof(header) + zctrllen + zdatalen, "extra",
247 » header[90]);
248
111 if (fclose(f)) 249 if (fclose(f))
112 err(1, "fclose(%s)", argv[3]); 250 err(1, "fclose(%s)", argv[3]);
113 if ((cpf = fopen(argv[3], "r")) == NULL)
114 err(1, "fopen(%s)", argv[3]);
115 if (fseeko(cpf, 32, SEEK_SET))
116 err(1, "fseeko(%s, %lld)", argv[3],
117 (long long)32);
118 if ((cpfbz2 = BZ2_bzReadOpen(&cbz2err, cpf, 0, 0, NULL, 0)) == NULL)
119 errx(1, "BZ2_bzReadOpen, bz2err = %d", cbz2err);
120 if ((dpf = fopen(argv[3], "r")) == NULL)
121 err(1, "fopen(%s)", argv[3]);
122 if (fseeko(dpf, 32 + bzctrllen, SEEK_SET))
123 err(1, "fseeko(%s, %lld)", argv[3],
124 (long long)(32 + bzctrllen));
125 if ((dpfbz2 = BZ2_bzReadOpen(&dbz2err, dpf, 0, 0, NULL, 0)) == NULL)
126 errx(1, "BZ2_bzReadOpen, bz2err = %d", dbz2err);
127 if ((epf = fopen(argv[3], "r")) == NULL)
128 err(1, "fopen(%s)", argv[3]);
129 if (fseeko(epf, 32 + bzctrllen + bzdatalen, SEEK_SET))
130 err(1, "fseeko(%s, %lld)", argv[3],
131 (long long)(32 + bzctrllen + bzdatalen));
132 if ((epfbz2 = BZ2_bzReadOpen(&ebz2err, epf, 0, 0, NULL, 0)) == NULL)
133 errx(1, "BZ2_bzReadOpen, bz2err = %d", ebz2err);
134 251
135 if(((fd=open(argv[1],O_RDONLY,0))<0) || 252 if(((fd=open(argv[1],O_RDONLY,0))<0) ||
136 ((oldsize=lseek(fd,0,SEEK_END))==-1) || 253 ((oldsize=lseek(fd,0,SEEK_END))==-1) ||
137 ((old=malloc(oldsize+1))==NULL) || 254 ((old=malloc(oldsize+1))==NULL) ||
138 (lseek(fd,0,SEEK_SET)!=0) || 255 (lseek(fd,0,SEEK_SET)!=0) ||
139 (read(fd,old,oldsize)!=oldsize) || 256 (read(fd,old,oldsize)!=oldsize) ||
140 (close(fd)==-1)) err(1,"%s",argv[1]); 257 (close(fd)==-1)) err(1,"%s",argv[1]);
258 if (expect_oldsize != oldsize)
259 errx(1, "old size mismatch: %lld != %lld",
260 oldsize, expect_oldsize);
261 SHA1(old, oldsize, sha1);
262 if (memcmp(sha1, header + 48, sizeof(sha1)) != 0) {
263 sha1tostr(sha1, sha1str);
264 sha1tostr(header + 48, expected_sha1str);
265 errx(1, "old hash mismatch: %s != %s",
266 sha1str, expected_sha1str);
267 }
141 if((new=malloc(newsize+1))==NULL) err(1,NULL); 268 if((new=malloc(newsize+1))==NULL) err(1,NULL);
142 269
143 oldpos=0;newpos=0; 270 oldpos=0;newpos=0;
144 while(newpos<newsize) { 271 while(newpos<newsize) {
145 /* Read control data */ 272 /* Read control data */
146 for(i=0;i<=2;i++) { 273 for(i=0;i<=2;i++) {
147 » » » lenread = BZ2_bzRead(&cbz2err, cpfbz2, buf, 8); 274 » » » cfread(&cf, buf, 8);
148 » » » if ((lenread < 8) || ((cbz2err != BZ_OK) &&
149 » » » (cbz2err != BZ_STREAM_END)))
150 » » » » errx(1, "Corrupt patch\n");
151 ctrl[i]=offtin(buf); 275 ctrl[i]=offtin(buf);
152 }; 276 };
153 277
154 /* Sanity-check */ 278 /* Sanity-check */
155 if(newpos+ctrl[0]>newsize) 279 if(newpos+ctrl[0]>newsize)
156 » » » errx(1,"Corrupt patch\n"); 280 » » » errx(1,"corrupt patch (diff): overrun");
157 281
158 /* Read diff string */ 282 /* Read diff string */
159 » » lenread = BZ2_bzRead(&dbz2err, dpfbz2, new + newpos, ctrl[0]); 283 » » cfread(&df, new + newpos, ctrl[0]);
160 » » if ((lenread < ctrl[0]) ||
161 » » ((dbz2err != BZ_OK) && (dbz2err != BZ_STREAM_END)))
162 » » » errx(1, "Corrupt patch\n");
163 284
164 /* Add old data to diff string */ 285 /* Add old data to diff string */
165 for(i=0;i<ctrl[0];i++) 286 for(i=0;i<ctrl[0];i++)
166 if((oldpos+i>=0) && (oldpos+i<oldsize)) 287 if((oldpos+i>=0) && (oldpos+i<oldsize))
167 new[newpos+i]+=old[oldpos+i]; 288 new[newpos+i]+=old[oldpos+i];
168 289
169 /* Adjust pointers */ 290 /* Adjust pointers */
170 newpos+=ctrl[0]; 291 newpos+=ctrl[0];
171 oldpos+=ctrl[0]; 292 oldpos+=ctrl[0];
172 293
173 /* Sanity-check */ 294 /* Sanity-check */
174 if(newpos+ctrl[1]>newsize) 295 if(newpos+ctrl[1]>newsize)
175 » » » errx(1,"Corrupt patch\n"); 296 » » » errx(1,"corrupt patch (extra): overrun");
176 297
177 /* Read extra string */ 298 /* Read extra string */
178 » » lenread = BZ2_bzRead(&ebz2err, epfbz2, new + newpos, ctrl[1]); 299 » » cfread(&ef, new + newpos, ctrl[1]);
179 » » if ((lenread < ctrl[1]) ||
180 » » ((ebz2err != BZ_OK) && (ebz2err != BZ_STREAM_END)))
181 » » » errx(1, "Corrupt patch\n");
182 300
183 /* Adjust pointers */ 301 /* Adjust pointers */
184 newpos+=ctrl[1]; 302 newpos+=ctrl[1];
185 oldpos+=ctrl[2]; 303 oldpos+=ctrl[2];
186 }; 304 };
187 305
188 » /* Clean up the bzip2 reads */ 306 » /* Clean up the readers */
189 » BZ2_bzReadClose(&cbz2err, cpfbz2); 307 » cfclose(&cf);
190 » BZ2_bzReadClose(&dbz2err, dpfbz2); 308 » cfclose(&df);
191 » BZ2_bzReadClose(&ebz2err, epfbz2); 309 » cfclose(&ef);
192 » if (fclose(cpf) || fclose(dpf) || fclose(epf)) 310
193 » » err(1, "fclose(%s)", argv[3]); 311 » SHA1(new, newsize, sha1);
312 » if (memcmp(sha1, header + 68, sizeof(sha1)) != 0) {
313 » » sha1tostr(sha1, sha1str);
314 » » sha1tostr(header + 68, expected_sha1str);
315 » » errx(1, "new hash mismatch: %s != %s",
316 » » sha1str, expected_sha1str);
317 » }
194 318
195 /* Write the new file */ 319 /* Write the new file */
196 » if(((fd=open(argv[2],O_CREAT|O_TRUNC|O_WRONLY,0666))<0) || 320 » if(((fd=open(argv[2],O_CREAT|O_TRUNC|O_WRONLY,0644))<0) ||
197 (write(fd,new,newsize)!=newsize) || (close(fd)==-1)) 321 (write(fd,new,newsize)!=newsize) || (close(fd)==-1))
198 » » err(1,"%s",argv[2]); 322 » » err(1,"open/write/close(%s)",argv[2]);
199 323
200 free(new); 324 free(new);
201 free(old); 325 free(old);
202 326
203 return 0; 327 return 0;
204 } 328 }
OLDNEW
« no previous file with comments | « chrome/installer/mac/third_party/bsdiff/goobsdiff.gyp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698