| OLD | NEW |
| 1 From f8c00fab208cb07e46bc3cb7f651cead857adf07 Mon Sep 17 00:00:00 2001 | 1 --- work/bsdiff-4.3/bspatch.c» 2005-08-16 15:14:00.000000000 -0700 |
| 2 From: Andrew de los Reyes <adlr@chromium.org> | 2 +++ work/bsdiff-4.3-new/bspatch.c» 2010-08-04 10:07:05.000000000 -0700 |
| 3 Date: Mon, 19 Apr 2010 15:05:56 -0700 | |
| 4 Subject: [PATCH] bspatch: support input/output positioning | |
| 5 | |
| 6 For autoupdate, we need bspatch to read specific blocks from the | |
| 7 filesystem devic and write back to specific blocks of the device. | |
| 8 | |
| 9 Review URL: http://codereview.chromium.org/1595025 | |
| 10 --- | |
| 11 files/bspatch.c | 270 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- | |
| 12 1 files changed, 259 insertions(+), 11 deletions(-) | |
| 13 | |
| 14 diff --git a/files/bspatch.c b/files/bspatch.c | |
| 15 index f4b821c..48ac79a 100644 | |
| 16 --- a/files/bspatch.c | |
| 17 +++ b/files/bspatch.c | |
| 18 @@ -3,7 +3,7 @@ | 3 @@ -3,7 +3,7 @@ |
| 19 * All rights reserved | 4 * All rights reserved |
| 20 * | 5 * |
| 21 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
| 22 - * modification, are permitted providing that the following conditions | 7 - * modification, are permitted providing that the following conditions |
| 23 + * modification, are permitted providing that the following conditions | 8 + * modification, are permitted providing that the following conditions |
| 24 * are met: | 9 * are met: |
| 25 * 1. Redistributions of source code must retain the above copyright | 10 * 1. Redistributions of source code must retain the above copyright |
| 26 * notice, this list of conditions and the following disclaimer. | 11 * notice, this list of conditions and the following disclaimer. |
| 27 @@ -29,6 +29,9 @@ __FBSDID("$FreeBSD: src/usr.bin/bsdiff/bspatch/bspatch.c,v 1.1
2005/08/06 01:59: | 12 @@ -29,6 +29,9 @@ __FBSDID("$FreeBSD: src/usr.bin/bsdiff/b |
| 28 #endif | 13 #endif |
| 29 | 14 |
| 30 #include <bzlib.h> | 15 #include <bzlib.h> |
| 31 +#include <errno.h> | 16 +#include <errno.h> |
| 32 +#include <inttypes.h> | 17 +#include <inttypes.h> |
| 33 +#include <stdint.h> | 18 +#include <stdint.h> |
| 34 #include <stdlib.h> | 19 #include <stdlib.h> |
| 35 #include <stdio.h> | 20 #include <stdio.h> |
| 36 #include <string.h> | 21 #include <string.h> |
| 37 @@ -36,6 +39,235 @@ __FBSDID("$FreeBSD: src/usr.bin/bsdiff/bspatch/bspatch.c,v 1
.1 2005/08/06 01:59: | 22 @@ -36,6 +39,244 @@ __FBSDID("$FreeBSD: src/usr.bin/bsdiff/b |
| 38 #include <unistd.h> | 23 #include <unistd.h> |
| 39 #include <fcntl.h> | 24 #include <fcntl.h> |
| 40 | 25 |
| 41 +#define JOIN(a, b) __JOIN(a, b) | 26 +#define JOIN(a, b) __JOIN(a, b) |
| 42 +#define __JOIN(a, b) a ## b | 27 +#define __JOIN(a, b) a ## b |
| 43 +#define COMPILE_ASSERT(expr, message) \ | 28 +#define COMPILE_ASSERT(expr, message) \ |
| 44 + typedef char JOIN(message, JOIN(_, __LINE__)) [(expr) ? 1 : -1] | 29 + typedef char JOIN(message, JOIN(_, __LINE__)) [(expr) ? 1 : -1] |
| 45 + | 30 + |
| 46 +COMPILE_ASSERT(sizeof(int64_t) == 8, int64_t_64_bit); | 31 +COMPILE_ASSERT(sizeof(int64_t) == 8, int64_t_64_bit); |
| 32 +COMPILE_ASSERT(sizeof(off_t) == 8, off_t_64_bit); |
| 47 + | 33 + |
| 48 +#define MIN(a, b) \ | 34 +#define MIN(a, b) \ |
| 49 + ((a) < (b) ? (a) : (b)) | 35 + ((a) < (b) ? (a) : (b)) |
| 50 + | 36 + |
| 51 +// Reads next int from *ints. The int should be terminated with a comma | 37 +// Reads next int from *ints. The int should be terminated with a comma |
| 52 +// or NULL char. *ints will be updated to the space right after the comma | 38 +// or NULL char. *ints will be updated to the space right after the comma |
| 53 +// or set to NULL if this was the last number. This assumes the input is | 39 +// or set to NULL if this was the last number. This assumes the input is |
| 54 +// a valid string, as validated with PositionsStringIsValid(). | 40 +// a valid string, as validated with PositionsStringIsValid(). |
| 55 +// Returns 1 on success. | 41 +// Returns 1 on success. |
| 56 +int NextInt64(const char** ints, int64_t *out) { | 42 +int NextInt64(const char** ints, int64_t *out) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 72 + } | 58 + } |
| 73 + return 0; | 59 + return 0; |
| 74 +} | 60 +} |
| 75 + | 61 + |
| 76 +COMPILE_ASSERT(sizeof(intmax_t) == 8, intmax_t_not_64_bit); | 62 +COMPILE_ASSERT(sizeof(intmax_t) == 8, intmax_t_not_64_bit); |
| 77 + | 63 + |
| 78 +// Returns 1 if str can be converted to int64_t without over/underflowing. | 64 +// Returns 1 if str can be converted to int64_t without over/underflowing. |
| 79 +// str is assumed to point to an optional negative sign followed by numbers, | 65 +// str is assumed to point to an optional negative sign followed by numbers, |
| 80 +// optionally followed by non-numeric characters, followed by '\0'. | 66 +// optionally followed by non-numeric characters, followed by '\0'. |
| 81 +int IsValidInt64(const char* str) { | 67 +int IsValidInt64(const char* str) { |
| 82 +» const char* end_ptr; | 68 +» const char* end_ptr = 0; |
| 83 + errno = 0; | 69 + errno = 0; |
| 84 + intmax_t result = strtoimax(str, &end_ptr, /* base: */ 10); | 70 + intmax_t result = strtoimax(str, &end_ptr, /* base: */ 10); |
| 85 + return errno == 0; | 71 + return errno == 0; |
| 86 +} | 72 +} |
| 87 + | 73 + |
| 88 +// Input validator. Make sure the positions string is well formatted. | 74 +// Input validator. Make sure the positions string is well formatted. |
| 89 +// All numerical values are checked to make sure they don't over/underflow | 75 +// All numerical values are checked to make sure they don't over/underflow |
| 90 +// int64_t. Returns 1 if valid. | 76 +// int64_t. Returns 1 if valid. |
| 91 +int PositionsStringIsValid(const char* positions) { | 77 +int PositionsStringIsValid(const char* positions) { |
| 92 + if (positions == NULL) | 78 + if (positions == NULL) |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 141 + state = 0; | 127 + state = 0; |
| 142 + number_start = positions + 1; | 128 + number_start = positions + 1; |
| 143 + negative_valid = !negative_valid; | 129 + negative_valid = !negative_valid; |
| 144 + continue; | 130 + continue; |
| 145 + } | 131 + } |
| 146 + return (c == '\0'); | 132 + return (c == '\0'); |
| 147 + } | 133 + } |
| 148 + } | 134 + } |
| 149 +} | 135 +} |
| 150 + | 136 + |
| 137 +static const int64_t kMaxLength = sizeof(size_t) > 4 ? INT64_MAX : SIZE_MAX; |
| 138 + |
| 151 +// Reads into a buffer a series of byte ranges from filename. | 139 +// Reads into a buffer a series of byte ranges from filename. |
| 152 +// Each range is a pair of comma-separated ints from positions. | 140 +// Each range is a pair of comma-separated ints from positions. |
| 153 +// -1 as an offset means a sparse-hole. | 141 +// -1 as an offset means a sparse-hole. |
| 154 +// E.g. If positions were "1,5:23,4:-1,8:3,7", then we would return a buffer | 142 +// E.g. If positions were "1,5:23,4:-1,8:3,7", then we would return a buffer |
| 155 +// consisting of 5 bytes from offset 1 of the file, followed by | 143 +// consisting of 5 bytes from offset 1 of the file, followed by |
| 156 +// 4 bytes from offset 23, then 8 bytes of all zeros, then 7 bytes from | 144 +// 4 bytes from offset 23, then 8 bytes of all zeros, then 7 bytes from |
| 157 +// offset 3 in the file. | 145 +// offset 3 in the file. |
| 158 +// Returns NULL on error. | 146 +// Returns NULL on error. |
| 159 +static char* PositionedRead(const char* filename, | 147 +static char* PositionedRead(const char* filename, |
| 160 + const char* positions, | 148 + const char* positions, |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 208 + errx(1, "no support for sparse positions " | 196 + errx(1, "no support for sparse positions " |
| 209 + "yet during read\n"); | 197 + "yet during read\n"); |
| 210 + } | 198 + } |
| 211 + if (NextInt64(&p, &read_length) == 0) { | 199 + if (NextInt64(&p, &read_length) == 0) { |
| 212 + errx(1, "bad length parse (should never happen)\n"); | 200 + errx(1, "bad length parse (should never happen)\n"); |
| 213 + } | 201 + } |
| 214 + if (read_length < 0) { | 202 + if (read_length < 0) { |
| 215 + errx(1, "length can't be negative " | 203 + errx(1, "length can't be negative " |
| 216 + "(should never happen)\n"); | 204 + "(should never happen)\n"); |
| 217 + } | 205 + } |
| 218 +» » ssize_t rc = pread(fd, buf_tail, read_length, offset); | 206 +» » if (read_length > kMaxLength) { |
| 207 +» » » errx(1, "read length too large\n"); |
| 208 +» » } |
| 209 +» » ssize_t rc = pread(fd, buf_tail, (size_t)read_length, (off_t)off
set); |
| 219 + if (rc != read_length) { | 210 + if (rc != read_length) { |
| 220 + errx(1, "read failed\n"); | 211 + errx(1, "read failed\n"); |
| 221 + } | 212 + } |
| 222 + buf_tail += rc; | 213 + buf_tail += rc; |
| 223 + } | 214 + } |
| 224 + close(fd); | 215 + close(fd); |
| 225 + *old_size = length; | 216 + *old_size = length; |
| 226 + return buf; | 217 + return buf; |
| 227 +} | 218 +} |
| 228 + | 219 + |
| (...skipping 13 matching lines...) Expand all Loading... |
| 242 + int64_t offset, length; | 233 + int64_t offset, length; |
| 243 + if (NextInt64(&positions, &offset) == 0) { | 234 + if (NextInt64(&positions, &offset) == 0) { |
| 244 + break; | 235 + break; |
| 245 + } | 236 + } |
| 246 + if (NextInt64(&positions, &length) == 0) { | 237 + if (NextInt64(&positions, &length) == 0) { |
| 247 + errx(1, "bad length parse for write\n"); | 238 + errx(1, "bad length parse for write\n"); |
| 248 + } | 239 + } |
| 249 + if (length < 0) { | 240 + if (length < 0) { |
| 250 + errx(1, "length can't be negative for write\n"); | 241 + errx(1, "length can't be negative for write\n"); |
| 251 + } | 242 + } |
| 243 + if (length > kMaxLength) { |
| 244 + errx(1, "write length too large\n"); |
| 245 + } |
| 252 + | 246 + |
| 253 + if (offset < 0) { | 247 + if (offset < 0) { |
| 254 + // Sparse hole. Skip. | 248 + // Sparse hole. Skip. |
| 255 + } else { | 249 + } else { |
| 256 +» » » ssize_t rc = pwrite(fd, buf, length, offset); | 250 +» » » ssize_t rc = pwrite(fd, buf, (size_t)length, (off_t)offs
et); |
| 257 + if (rc != length) { | 251 + if (rc != length) { |
| 258 + errx(1, "write failed\n"); | 252 + errx(1, "write failed\n"); |
| 259 + } | 253 + } |
| 260 + } | 254 + } |
| 261 + buf += length; | 255 + buf += length; |
| 262 + new_size -= length; | 256 + new_size -= length; |
| 263 + } | 257 + } |
| 264 + if (new_size != 0) { | 258 + if (new_size != 0) { |
| 265 + errx(1, "output position length doesn't match new size\n"); | 259 + errx(1, "output position length doesn't match new size\n"); |
| 266 + } | 260 + } |
| 267 + close(fd); | 261 + close(fd); |
| 268 +} | 262 +} |
| 269 + | 263 + |
| 270 static off_t offtin(u_char *buf) | 264 static off_t offtin(u_char *buf) |
| 271 { | 265 { |
| 272 off_t y; | 266 off_t y; |
| 273 @@ -69,7 +301,13 @@ int main(int argc,char * argv[]) | 267 @@ -69,7 +310,13 @@ int main(int argc,char * argv[]) |
| 274 off_t lenread; | 268 off_t lenread; |
| 275 off_t i; | 269 off_t i; |
| 276 | 270 |
| 277 - if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]); | 271 - if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]); |
| 278 + if ((argc != 6) && (argc != 4)) { | 272 + if ((argc != 6) && (argc != 4)) { |
| 279 + errx(1,"usage: %s oldfile newfile patchfile \\\n" | 273 + errx(1,"usage: %s oldfile newfile patchfile \\\n" |
| 280 + " [in_offset,in_length,in_offset,in_length,... \\\n" | 274 + " [in_offset,in_length,in_offset,in_length,... \\\n" |
| 281 + " out_offset,out_length," | 275 + " out_offset,out_length," |
| 282 + "out_offset,out_length,...]\n",argv[0]); | 276 + "out_offset,out_length,...]\n",argv[0]); |
| 283 + } | 277 + } |
| 284 + int using_positioning = (argc == 6); | 278 + int using_positioning = (argc == 6); |
| 285 | 279 |
| 286 /* Open patch file */ | 280 /* Open patch file */ |
| 287 if ((f = fopen(argv[3], "r")) == NULL) | 281 if ((f = fopen(argv[3], "r")) == NULL) |
| 288 @@ -132,12 +370,18 @@ int main(int argc,char * argv[]) | 282 @@ -132,12 +379,18 @@ int main(int argc,char * argv[]) |
| 289 if ((epfbz2 = BZ2_bzReadOpen(&ebz2err, epf, 0, 0, NULL, 0)) == NULL) | 283 if ((epfbz2 = BZ2_bzReadOpen(&ebz2err, epf, 0, 0, NULL, 0)) == NULL) |
| 290 errx(1, "BZ2_bzReadOpen, bz2err = %d", ebz2err); | 284 errx(1, "BZ2_bzReadOpen, bz2err = %d", ebz2err); |
| 291 | 285 |
| 292 - if(((fd=open(argv[1],O_RDONLY,0))<0) || | 286 - if(((fd=open(argv[1],O_RDONLY,0))<0) || |
| 293 - ((oldsize=lseek(fd,0,SEEK_END))==-1) || | 287 - ((oldsize=lseek(fd,0,SEEK_END))==-1) || |
| 294 - ((old=malloc(oldsize+1))==NULL) || | 288 - ((old=malloc(oldsize+1))==NULL) || |
| 295 - (lseek(fd,0,SEEK_SET)!=0) || | 289 - (lseek(fd,0,SEEK_SET)!=0) || |
| 296 - (read(fd,old,oldsize)!=oldsize) || | 290 - (read(fd,old,oldsize)!=oldsize) || |
| 297 - (close(fd)==-1)) err(1,"%s",argv[1]); | 291 - (close(fd)==-1)) err(1,"%s",argv[1]); |
| 298 + // Read | 292 + // Read |
| 299 + | 293 + |
| 300 + if (!using_positioning) { | 294 + if (!using_positioning) { |
| 301 + if(((fd=open(argv[1],O_RDONLY,0))<0) || | 295 + if(((fd=open(argv[1],O_RDONLY,0))<0) || |
| 302 + ((oldsize=lseek(fd,0,SEEK_END))==-1) || | 296 + ((oldsize=lseek(fd,0,SEEK_END))==-1) || |
| 303 + ((old=malloc(oldsize+1))==NULL) || | 297 + ((old=malloc(oldsize+1))==NULL) || |
| 304 + (lseek(fd,0,SEEK_SET)!=0) || | 298 + (lseek(fd,0,SEEK_SET)!=0) || |
| 305 + (read(fd,old,oldsize)!=oldsize) || | 299 + (read(fd,old,oldsize)!=oldsize) || |
| 306 + (close(fd)==-1)) err(1,"%s",argv[1]); | 300 + (close(fd)==-1)) err(1,"%s",argv[1]); |
| 307 + } else { | 301 + } else { |
| 308 + old = PositionedRead(argv[1], argv[4], &oldsize); | 302 + old = PositionedRead(argv[1], argv[4], &oldsize); |
| 309 + } | 303 + } |
| 310 if((new=malloc(newsize+1))==NULL) err(1,NULL); | 304 if((new=malloc(newsize+1))==NULL) err(1,NULL); |
| 311 | 305 |
| 312 oldpos=0;newpos=0; | 306 oldpos=0;newpos=0; |
| 313 @@ -193,9 +437,13 @@ int main(int argc,char * argv[]) | 307 @@ -193,9 +446,13 @@ int main(int argc,char * argv[]) |
| 314 err(1, "fclose(%s)", argv[3]); | 308 err(1, "fclose(%s)", argv[3]); |
| 315 | 309 |
| 316 /* Write the new file */ | 310 /* Write the new file */ |
| 317 - if(((fd=open(argv[2],O_CREAT|O_TRUNC|O_WRONLY,0666))<0) || | 311 - if(((fd=open(argv[2],O_CREAT|O_TRUNC|O_WRONLY,0666))<0) || |
| 318 - (write(fd,new,newsize)!=newsize) || (close(fd)==-1)) | 312 - (write(fd,new,newsize)!=newsize) || (close(fd)==-1)) |
| 319 - err(1,"%s",argv[2]); | 313 - err(1,"%s",argv[2]); |
| 320 + if (!using_positioning) { | 314 + if (!using_positioning) { |
| 321 + if(((fd=open(argv[2],O_CREAT|O_TRUNC|O_WRONLY,0666))<0) || | 315 + if(((fd=open(argv[2],O_CREAT|O_TRUNC|O_WRONLY,0666))<0) || |
| 322 + (write(fd,new,newsize)!=newsize) || (close(fd)==-1)) | 316 + (write(fd,new,newsize)!=newsize) || (close(fd)==-1)) |
| 323 + err(1,"%s",argv[2]); | 317 + err(1,"%s",argv[2]); |
| 324 + } else { | 318 + } else { |
| 325 + PositionedWrite(argv[2], argv[5], new, newsize); | 319 + PositionedWrite(argv[2], argv[5], new, newsize); |
| 326 + } | 320 + } |
| 327 | 321 |
| 328 free(new); | 322 free(new); |
| 329 free(old); | 323 free(old); |
| 330 -- | |
| 331 1.6.4.4 | |
| 332 | |
| OLD | NEW |