/src/ostree/bsdiff/bspatch.c
Line | Count | Source (jump to first uncovered line) |
1 | | /*- |
2 | | * Copyright 2003-2005 Colin Percival |
3 | | * Copyright 2012 Matthew Endsley |
4 | | * All rights reserved |
5 | | * |
6 | | * Redistribution and use in source and binary forms, with or without |
7 | | * modification, are permitted providing that the following conditions |
8 | | * are met: |
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. |
14 | | * |
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. |
26 | | */ |
27 | | |
28 | | #include <limits.h> |
29 | | #include "bspatch.h" |
30 | | |
31 | | static int64_t offtin(uint8_t *buf) |
32 | 0 | { |
33 | 0 | int64_t y; |
34 | |
|
35 | 0 | y=buf[7]&0x7F; |
36 | 0 | y=y*256;y+=buf[6]; |
37 | 0 | y=y*256;y+=buf[5]; |
38 | 0 | y=y*256;y+=buf[4]; |
39 | 0 | y=y*256;y+=buf[3]; |
40 | 0 | y=y*256;y+=buf[2]; |
41 | 0 | y=y*256;y+=buf[1]; |
42 | 0 | y=y*256;y+=buf[0]; |
43 | |
|
44 | 0 | if(buf[7]&0x80) y=-y; |
45 | |
|
46 | 0 | return y; |
47 | 0 | } |
48 | | |
49 | | int bspatch(const uint8_t* old, int64_t oldsize, uint8_t* new, int64_t newsize, struct bspatch_stream* stream) |
50 | 0 | { |
51 | 0 | uint8_t buf[8]; |
52 | 0 | int64_t oldpos,newpos; |
53 | 0 | int64_t ctrl[3]; |
54 | 0 | int64_t i; |
55 | |
|
56 | 0 | oldpos=0;newpos=0; |
57 | 0 | while(newpos<newsize) { |
58 | | /* Read control data */ |
59 | 0 | for(i=0;i<=2;i++) { |
60 | 0 | if (stream->read(stream, buf, 8)) |
61 | 0 | return -1; |
62 | 0 | ctrl[i]=offtin(buf); |
63 | 0 | }; |
64 | | |
65 | | /* Sanity-check */ |
66 | 0 | if (ctrl[0]<0 || ctrl[0]>INT_MAX || |
67 | 0 | ctrl[1]<0 || ctrl[1]>INT_MAX || |
68 | 0 | newpos+ctrl[0]>newsize) |
69 | 0 | return -1; |
70 | | |
71 | | /* Read diff string */ |
72 | 0 | if (stream->read(stream, new + newpos, ctrl[0])) |
73 | 0 | return -1; |
74 | | |
75 | | /* Add old data to diff string */ |
76 | 0 | for(i=0;i<ctrl[0];i++) |
77 | 0 | if((oldpos+i>=0) && (oldpos+i<oldsize)) |
78 | 0 | new[newpos+i]+=old[oldpos+i]; |
79 | | |
80 | | /* Adjust pointers */ |
81 | 0 | newpos+=ctrl[0]; |
82 | 0 | oldpos+=ctrl[0]; |
83 | | |
84 | | /* Sanity-check */ |
85 | 0 | if(newpos+ctrl[1]>newsize) |
86 | 0 | return -1; |
87 | | |
88 | | /* Read extra string */ |
89 | 0 | if (stream->read(stream, new + newpos, ctrl[1])) |
90 | 0 | return -1; |
91 | | |
92 | | /* Adjust pointers */ |
93 | 0 | newpos+=ctrl[1]; |
94 | 0 | oldpos+=ctrl[2]; |
95 | 0 | }; |
96 | |
|
97 | 0 | return 0; |
98 | 0 | } |
99 | | |
100 | | #if defined(BSPATCH_EXECUTABLE) |
101 | | |
102 | | #include <bzlib.h> |
103 | | #include <stdlib.h> |
104 | | #include <stdint.h> |
105 | | #include <stdio.h> |
106 | | #include <string.h> |
107 | | #include <err.h> |
108 | | #include <sys/types.h> |
109 | | #include <sys/stat.h> |
110 | | #include <unistd.h> |
111 | | #include <fcntl.h> |
112 | | |
113 | | static int bz2_read(const struct bspatch_stream* stream, void* buffer, int length) |
114 | | { |
115 | | int n; |
116 | | int bz2err; |
117 | | BZFILE* bz2; |
118 | | |
119 | | bz2 = (BZFILE*)stream->opaque; |
120 | | n = BZ2_bzRead(&bz2err, bz2, buffer, length); |
121 | | if (n != length) |
122 | | return -1; |
123 | | |
124 | | return 0; |
125 | | } |
126 | | |
127 | | int main(int argc,char * argv[]) |
128 | | { |
129 | | FILE * f; |
130 | | int fd; |
131 | | int bz2err; |
132 | | uint8_t header[24]; |
133 | | uint8_t *old, *new; |
134 | | int64_t oldsize, newsize; |
135 | | BZFILE* bz2; |
136 | | struct bspatch_stream stream; |
137 | | struct stat sb; |
138 | | |
139 | | if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]); |
140 | | |
141 | | /* Open patch file */ |
142 | | if ((f = fopen(argv[3], "r")) == NULL) |
143 | | err(1, "fopen(%s)", argv[3]); |
144 | | |
145 | | /* Read header */ |
146 | | if (fread(header, 1, 24, f) != 24) { |
147 | | if (feof(f)) |
148 | | errx(1, "Corrupt patch\n"); |
149 | | err(1, "fread(%s)", argv[3]); |
150 | | } |
151 | | |
152 | | /* Check for appropriate magic */ |
153 | | if (memcmp(header, "ENDSLEY/BSDIFF43", 16) != 0) |
154 | | errx(1, "Corrupt patch\n"); |
155 | | |
156 | | /* Read lengths from header */ |
157 | | newsize=offtin(header+16); |
158 | | if(newsize<0) |
159 | | errx(1,"Corrupt patch\n"); |
160 | | |
161 | | /* Close patch file and re-open it via libbzip2 at the right places */ |
162 | | if(((fd=open(argv[1],O_RDONLY,0))<0) || |
163 | | ((oldsize=lseek(fd,0,SEEK_END))==-1) || |
164 | | ((old=malloc(oldsize+1))==NULL) || |
165 | | (lseek(fd,0,SEEK_SET)!=0) || |
166 | | (read(fd,old,oldsize)!=oldsize) || |
167 | | (fstat(fd, &sb)) || |
168 | | (close(fd)==-1)) err(1,"%s",argv[1]); |
169 | | if((new=malloc(newsize+1))==NULL) err(1,NULL); |
170 | | |
171 | | if (NULL == (bz2 = BZ2_bzReadOpen(&bz2err, f, 0, 0, NULL, 0))) |
172 | | errx(1, "BZ2_bzReadOpen, bz2err=%d", bz2err); |
173 | | |
174 | | stream.read = bz2_read; |
175 | | stream.opaque = bz2; |
176 | | if (bspatch(old, oldsize, new, newsize, &stream)) |
177 | | errx(1, "bspatch"); |
178 | | |
179 | | /* Clean up the bzip2 reads */ |
180 | | BZ2_bzReadClose(&bz2err, bz2); |
181 | | fclose(f); |
182 | | |
183 | | /* Write the new file */ |
184 | | if(((fd=open(argv[2],O_CREAT|O_TRUNC|O_WRONLY,sb.st_mode))<0) || |
185 | | (write(fd,new,newsize)!=newsize) || (close(fd)==-1)) |
186 | | err(1,"%s",argv[2]); |
187 | | |
188 | | free(new); |
189 | | free(old); |
190 | | |
191 | | return 0; |
192 | | } |
193 | | |
194 | | #endif |