bsdiff 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2ae292190ee6672795acaac25b95ba9a25a4d6e66f6972f39b8d0a9cad3e655c
4
+ data.tar.gz: 65b10f9f9ab26f77759f9b5d1cf669f4b9effbb53b4f23735373934c312ff8f6
5
+ SHA512:
6
+ metadata.gz: 2c30f9d40454d3798f3b2474dd8d7e0a3dbb68c9e7e26a7b46935d508e34dba614eba9c4ead4c3677e77fdd06913a28b8dd87f8f964f394ef860bba87198aa45
7
+ data.tar.gz: 0dbded5d77c184e86b8370069c77c21714fe4508ba90c4f07f0a6f3e48c60896f83b905fb580c07e4e68dc5b5f7aa9433a5c2f8bceefde9c4839046fec07b664
data/.rubocop.yml ADDED
@@ -0,0 +1,19 @@
1
+ ---
2
+ require:
3
+ - rubocop-minitest
4
+ - rubocop-performance
5
+ - rubocop-rake
6
+
7
+ AllCops:
8
+ TargetRubyVersion: 3.1
9
+ NewCops: enable
10
+
11
+ Minitest/TestMethodName:
12
+ Enabled: true
13
+
14
+ Minitest/AssertTruthy:
15
+ Enabled: false
16
+
17
+ Style/HashSyntax:
18
+ Enabled: false # yuk Ruby 3.1
19
+
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.0.0] - 2024-10-08
4
+
5
+ - Initial release
data/LICENSE.txt ADDED
@@ -0,0 +1,23 @@
1
+ Copyright 2003-2005 Colin Percival
2
+ * All rights reserved
3
+ *
4
+ * Redistribution and use in source and binary forms, with or without
5
+ * modification, are permitted providing that the following conditions
6
+ * are met:
7
+ * 1. Redistributions of source code must retain the above copyright
8
+ * notice, this list of conditions and the following disclaimer.
9
+ * 2. Redistributions in binary form must reproduce the above copyright
10
+ * notice, this list of conditions and the following disclaimer in the
11
+ * documentation and/or other materials provided with the distribution.
12
+ *
13
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
17
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
21
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
22
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
23
+ * POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,48 @@
1
+ [![Gem Version](https://badge.fury.io/rb/bsdiff.svg)](https://badge.fury.io/rb/bsdiff)
2
+ [![Ruby Style Guide](https://img.shields.io/badge/code_style-rubocop-brightgreen.svg)](https://github.com/rubocop/rubocop)
3
+
4
+ # Bsdiff - the binary diff/patch tool
5
+
6
+ Ruby bindings for Colin Percival's excellent [bsdiff/bspatch](https://www.daemonology.net/bsdiff) binary patching tool.
7
+
8
+ ## Installation
9
+
10
+ Bsdiff requires the bzip2 library. If you don't already have it, install `libbz2-dev` via your package manager.
11
+
12
+ Install the gem and add it to the application's Gemfile by executing:
13
+
14
+ ```bash
15
+ bundle add bsdiff
16
+ ```
17
+
18
+ If bundler is not being used to manage dependencies, install the gem by executing:
19
+
20
+ ```bash
21
+ gem install bsdiff
22
+ ```
23
+ The original source archive is located in dir `src` and diffs to show changes made in creatign the bindings are in dir `diffs`. Both are verified in the [tests](https://gitlab.com/matzfan/bsdiff/-/blob/master/test/test_bsdiff.rb).
24
+
25
+ ## Usage
26
+ ```ruby
27
+ require 'bsdiff'
28
+
29
+ # generate a patch for oldfile to newfile
30
+ Bsdiff.diff '/path/to/oldfile', '/path/to/newfile', '/path/to/patchfile.patch' # patchfile is created
31
+
32
+ # apply the patch to create newfile from oldfile and the patchfile
33
+ Bsdiff.patch '/path/to/oldfile', '/path/to/newfile', '/path/to/patchfile.patch' # newfile is created
34
+ ```
35
+
36
+ ## Development
37
+
38
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
39
+
40
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
41
+
42
+ ## Contributing
43
+
44
+ Bug reports and pull requests are welcome on GitHub at https://gitlab.com/matzfan/bsdiff.
45
+
46
+ ## License
47
+
48
+ The gem is available as open source under the terms of the [FreeBSD License](https://opensource.org/license/bsd-2-clause).
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'minitest/test_task'
5
+ require 'rake/extensiontask'
6
+
7
+ Minitest::TestTask.create
8
+
9
+ require 'rubocop/rake_task'
10
+
11
+ RuboCop::RakeTask.new
12
+ Rake::ExtensionTask.new('bsdiff') { |ext| ext.lib_dir = 'lib/bsdiff' } # puts bsdiff.so in this dir
13
+
14
+ task default: %i[clobber compile test rubocop]
15
+
16
+ CLEAN.add('{ext,lib}/**/*.{o,so}', 'pkg')
@@ -0,0 +1,40 @@
1
+ 40a41,42
2
+ > #include <ruby.h>
3
+ >
4
+ 196c198
5
+ < int main(int argc,char *argv[])
6
+ ---
7
+ > int diff(const char *oldfile, const char *newfile, const char *patchfile)
8
+ 216,217d217
9
+ < if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]);
10
+ <
11
+ 220c220
12
+ < if(((fd=open(argv[1],O_RDONLY,0))<0) ||
13
+ ---
14
+ > if(((fd=open(oldfile,O_RDONLY,0))<0) ||
15
+ 225c225
16
+ < (close(fd)==-1)) err(1,"%s",argv[1]);
17
+ ---
18
+ > (close(fd)==-1)) err(1,"%s",oldfile);
19
+ 236c236
20
+ < if(((fd=open(argv[2],O_RDONLY,0))<0) ||
21
+ ---
22
+ > if(((fd=open(newfile,O_RDONLY,0))<0) ||
23
+ 241c241
24
+ < (close(fd)==-1)) err(1,"%s",argv[2]);
25
+ ---
26
+ > (close(fd)==-1)) err(1,"%s",newfile);
27
+ 249,250c249,250
28
+ < if ((pf = fopen(argv[3], "w")) == NULL)
29
+ < err(1, "%s", argv[3]);
30
+ ---
31
+ > if ((pf = fopen(patchfile, "w")) == NULL)
32
+ > err(1, "%s", patchfile);
33
+ 267c267
34
+ < err(1, "fwrite(%s)", argv[3]);
35
+ ---
36
+ > err(1, "fwrite(%s)", patchfile);
37
+ 392c392
38
+ < err(1, "fwrite(%s)", argv[3]);
39
+ ---
40
+ > err(1, "fwrite(%s)", patchfile);
@@ -0,0 +1,72 @@
1
+ 38a39,40
2
+ > #include <ruby.h>
3
+ >
4
+ 57c59
5
+ < int main(int argc,char * argv[])
6
+ ---
7
+ > int patch(const char *oldfile, const char *newfile, const char *patchfile)
8
+ 72,73d73
9
+ < if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]);
10
+ <
11
+ 75,76c75,76
12
+ < if ((f = fopen(argv[3], "r")) == NULL)
13
+ < err(1, "fopen(%s)", argv[3]);
14
+ ---
15
+ > if ((f = fopen(patchfile, "r")) == NULL)
16
+ > err(1, "fopen(%s)", patchfile);
17
+ 96c96
18
+ < err(1, "fread(%s)", argv[3]);
19
+ ---
20
+ > err(1, "fread(%s)", patchfile);
21
+ 112,114c112,114
22
+ < err(1, "fclose(%s)", argv[3]);
23
+ < if ((cpf = fopen(argv[3], "r")) == NULL)
24
+ < err(1, "fopen(%s)", argv[3]);
25
+ ---
26
+ > err(1, "fclose(%s)", patchfile);
27
+ > if ((cpf = fopen(patchfile, "r")) == NULL)
28
+ > err(1, "fopen(%s)", patchfile);
29
+ 116c116
30
+ < err(1, "fseeko(%s, %lld)", argv[3],
31
+ ---
32
+ > err(1, "fseeko(%s, %lld)", patchfile,
33
+ 120,121c120,121
34
+ < if ((dpf = fopen(argv[3], "r")) == NULL)
35
+ < err(1, "fopen(%s)", argv[3]);
36
+ ---
37
+ > if ((dpf = fopen(patchfile, "r")) == NULL)
38
+ > err(1, "fopen(%s)", patchfile);
39
+ 123c123
40
+ < err(1, "fseeko(%s, %lld)", argv[3],
41
+ ---
42
+ > err(1, "fseeko(%s, %lld)", patchfile,
43
+ 127,128c127,128
44
+ < if ((epf = fopen(argv[3], "r")) == NULL)
45
+ < err(1, "fopen(%s)", argv[3]);
46
+ ---
47
+ > if ((epf = fopen(patchfile, "r")) == NULL)
48
+ > err(1, "fopen(%s)", patchfile);
49
+ 130c130
50
+ < err(1, "fseeko(%s, %lld)", argv[3],
51
+ ---
52
+ > err(1, "fseeko(%s, %lld)", patchfile,
53
+ 135c135
54
+ < if(((fd=open(argv[1],O_RDONLY,0))<0) ||
55
+ ---
56
+ > if(((fd=open(oldfile,O_RDONLY,0))<0) ||
57
+ 140c140
58
+ < (close(fd)==-1)) err(1,"%s",argv[1]);
59
+ ---
60
+ > (close(fd)==-1)) err(1,"%s",oldfile);
61
+ 193c193
62
+ < err(1, "fclose(%s)", argv[3]);
63
+ ---
64
+ > err(1, "fclose(%s)", patchfile);
65
+ 196c196
66
+ < if(((fd=open(argv[2],O_CREAT|O_TRUNC|O_WRONLY,0666))<0) ||
67
+ ---
68
+ > if(((fd=open(newfile,O_CREAT|O_TRUNC|O_WRONLY,0666))<0) ||
69
+ 198c198
70
+ < err(1,"%s",argv[2]);
71
+ ---
72
+ > err(1,"%s",newfile);
@@ -0,0 +1,404 @@
1
+ /*-
2
+ * Copyright 2003-2005 Colin Percival
3
+ * All rights reserved
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted providing that the following conditions
7
+ * are met:
8
+ * 1. Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * 2. Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ *
14
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
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
24
+ * POSSIBILITY OF SUCH DAMAGE.
25
+ */
26
+
27
+ #if 0
28
+ __FBSDID("$FreeBSD: src/usr.bin/bsdiff/bsdiff/bsdiff.c,v 1.1 2005/08/06 01:59:05 cperciva Exp $");
29
+ #endif
30
+
31
+ #include <sys/types.h>
32
+
33
+ #include <bzlib.h>
34
+ #include <err.h>
35
+ #include <fcntl.h>
36
+ #include <stdio.h>
37
+ #include <stdlib.h>
38
+ #include <string.h>
39
+ #include <unistd.h>
40
+
41
+ #include <ruby.h>
42
+
43
+ #define MIN(x,y) (((x)<(y)) ? (x) : (y))
44
+
45
+ static void split(off_t *I,off_t *V,off_t start,off_t len,off_t h)
46
+ {
47
+ off_t i,j,k,x,tmp,jj,kk;
48
+
49
+ if(len<16) {
50
+ for(k=start;k<start+len;k+=j) {
51
+ j=1;x=V[I[k]+h];
52
+ for(i=1;k+i<start+len;i++) {
53
+ if(V[I[k+i]+h]<x) {
54
+ x=V[I[k+i]+h];
55
+ j=0;
56
+ };
57
+ if(V[I[k+i]+h]==x) {
58
+ tmp=I[k+j];I[k+j]=I[k+i];I[k+i]=tmp;
59
+ j++;
60
+ };
61
+ };
62
+ for(i=0;i<j;i++) V[I[k+i]]=k+j-1;
63
+ if(j==1) I[k]=-1;
64
+ };
65
+ return;
66
+ };
67
+
68
+ x=V[I[start+len/2]+h];
69
+ jj=0;kk=0;
70
+ for(i=start;i<start+len;i++) {
71
+ if(V[I[i]+h]<x) jj++;
72
+ if(V[I[i]+h]==x) kk++;
73
+ };
74
+ jj+=start;kk+=jj;
75
+
76
+ i=start;j=0;k=0;
77
+ while(i<jj) {
78
+ if(V[I[i]+h]<x) {
79
+ i++;
80
+ } else if(V[I[i]+h]==x) {
81
+ tmp=I[i];I[i]=I[jj+j];I[jj+j]=tmp;
82
+ j++;
83
+ } else {
84
+ tmp=I[i];I[i]=I[kk+k];I[kk+k]=tmp;
85
+ k++;
86
+ };
87
+ };
88
+
89
+ while(jj+j<kk) {
90
+ if(V[I[jj+j]+h]==x) {
91
+ j++;
92
+ } else {
93
+ tmp=I[jj+j];I[jj+j]=I[kk+k];I[kk+k]=tmp;
94
+ k++;
95
+ };
96
+ };
97
+
98
+ if(jj>start) split(I,V,start,jj-start,h);
99
+
100
+ for(i=0;i<kk-jj;i++) V[I[jj+i]]=kk-1;
101
+ if(jj==kk-1) I[jj]=-1;
102
+
103
+ if(start+len>kk) split(I,V,kk,start+len-kk,h);
104
+ }
105
+
106
+ static void qsufsort(off_t *I,off_t *V,u_char *old,off_t oldsize)
107
+ {
108
+ off_t buckets[256];
109
+ off_t i,h,len;
110
+
111
+ for(i=0;i<256;i++) buckets[i]=0;
112
+ for(i=0;i<oldsize;i++) buckets[old[i]]++;
113
+ for(i=1;i<256;i++) buckets[i]+=buckets[i-1];
114
+ for(i=255;i>0;i--) buckets[i]=buckets[i-1];
115
+ buckets[0]=0;
116
+
117
+ for(i=0;i<oldsize;i++) I[++buckets[old[i]]]=i;
118
+ I[0]=oldsize;
119
+ for(i=0;i<oldsize;i++) V[i]=buckets[old[i]];
120
+ V[oldsize]=0;
121
+ for(i=1;i<256;i++) if(buckets[i]==buckets[i-1]+1) I[buckets[i]]=-1;
122
+ I[0]=-1;
123
+
124
+ for(h=1;I[0]!=-(oldsize+1);h+=h) {
125
+ len=0;
126
+ for(i=0;i<oldsize+1;) {
127
+ if(I[i]<0) {
128
+ len-=I[i];
129
+ i-=I[i];
130
+ } else {
131
+ if(len) I[i-len]=-len;
132
+ len=V[I[i]]+1-i;
133
+ split(I,V,i,len,h);
134
+ i+=len;
135
+ len=0;
136
+ };
137
+ };
138
+ if(len) I[i-len]=-len;
139
+ };
140
+
141
+ for(i=0;i<oldsize+1;i++) I[V[i]]=i;
142
+ }
143
+
144
+ static off_t matchlen(u_char *old,off_t oldsize,u_char *new,off_t newsize)
145
+ {
146
+ off_t i;
147
+
148
+ for(i=0;(i<oldsize)&&(i<newsize);i++)
149
+ if(old[i]!=new[i]) break;
150
+
151
+ return i;
152
+ }
153
+
154
+ static off_t search(off_t *I,u_char *old,off_t oldsize,
155
+ u_char *new,off_t newsize,off_t st,off_t en,off_t *pos)
156
+ {
157
+ off_t x,y;
158
+
159
+ if(en-st<2) {
160
+ x=matchlen(old+I[st],oldsize-I[st],new,newsize);
161
+ y=matchlen(old+I[en],oldsize-I[en],new,newsize);
162
+
163
+ if(x>y) {
164
+ *pos=I[st];
165
+ return x;
166
+ } else {
167
+ *pos=I[en];
168
+ return y;
169
+ }
170
+ };
171
+
172
+ x=st+(en-st)/2;
173
+ if(memcmp(old+I[x],new,MIN(oldsize-I[x],newsize))<0) {
174
+ return search(I,old,oldsize,new,newsize,x,en,pos);
175
+ } else {
176
+ return search(I,old,oldsize,new,newsize,st,x,pos);
177
+ };
178
+ }
179
+
180
+ static void offtout(off_t x,u_char *buf)
181
+ {
182
+ off_t y;
183
+
184
+ if(x<0) y=-x; else y=x;
185
+
186
+ buf[0]=y%256;y-=buf[0];
187
+ y=y/256;buf[1]=y%256;y-=buf[1];
188
+ y=y/256;buf[2]=y%256;y-=buf[2];
189
+ y=y/256;buf[3]=y%256;y-=buf[3];
190
+ y=y/256;buf[4]=y%256;y-=buf[4];
191
+ y=y/256;buf[5]=y%256;y-=buf[5];
192
+ y=y/256;buf[6]=y%256;y-=buf[6];
193
+ y=y/256;buf[7]=y%256;
194
+
195
+ if(x<0) buf[7]|=0x80;
196
+ }
197
+
198
+ int diff(const char *oldfile, const char *newfile, const char *patchfile)
199
+ {
200
+ int fd;
201
+ u_char *old,*new;
202
+ off_t oldsize,newsize;
203
+ off_t *I,*V;
204
+ off_t scan,pos,len;
205
+ off_t lastscan,lastpos,lastoffset;
206
+ off_t oldscore,scsc;
207
+ off_t s,Sf,lenf,Sb,lenb;
208
+ off_t overlap,Ss,lens;
209
+ off_t i;
210
+ off_t dblen,eblen;
211
+ u_char *db,*eb;
212
+ u_char buf[8];
213
+ u_char header[32];
214
+ FILE * pf;
215
+ BZFILE * pfbz2;
216
+ int bz2err;
217
+
218
+ /* Allocate oldsize+1 bytes instead of oldsize bytes to ensure
219
+ that we never try to malloc(0) and get a NULL pointer */
220
+ if(((fd=open(oldfile,O_RDONLY,0))<0) ||
221
+ ((oldsize=lseek(fd,0,SEEK_END))==-1) ||
222
+ ((old=malloc(oldsize+1))==NULL) ||
223
+ (lseek(fd,0,SEEK_SET)!=0) ||
224
+ (read(fd,old,oldsize)!=oldsize) ||
225
+ (close(fd)==-1)) err(1,"%s",oldfile);
226
+
227
+ if(((I=malloc((oldsize+1)*sizeof(off_t)))==NULL) ||
228
+ ((V=malloc((oldsize+1)*sizeof(off_t)))==NULL)) err(1,NULL);
229
+
230
+ qsufsort(I,V,old,oldsize);
231
+
232
+ free(V);
233
+
234
+ /* Allocate newsize+1 bytes instead of newsize bytes to ensure
235
+ that we never try to malloc(0) and get a NULL pointer */
236
+ if(((fd=open(newfile,O_RDONLY,0))<0) ||
237
+ ((newsize=lseek(fd,0,SEEK_END))==-1) ||
238
+ ((new=malloc(newsize+1))==NULL) ||
239
+ (lseek(fd,0,SEEK_SET)!=0) ||
240
+ (read(fd,new,newsize)!=newsize) ||
241
+ (close(fd)==-1)) err(1,"%s",newfile);
242
+
243
+ if(((db=malloc(newsize+1))==NULL) ||
244
+ ((eb=malloc(newsize+1))==NULL)) err(1,NULL);
245
+ dblen=0;
246
+ eblen=0;
247
+
248
+ /* Create the patch file */
249
+ if ((pf = fopen(patchfile, "w")) == NULL)
250
+ err(1, "%s", patchfile);
251
+
252
+ /* Header is
253
+ 0 8 "BSDIFF40"
254
+ 8 8 length of bzip2ed ctrl block
255
+ 16 8 length of bzip2ed diff block
256
+ 24 8 length of new file */
257
+ /* File is
258
+ 0 32 Header
259
+ 32 ?? Bzip2ed ctrl block
260
+ ?? ?? Bzip2ed diff block
261
+ ?? ?? Bzip2ed extra block */
262
+ memcpy(header,"BSDIFF40",8);
263
+ offtout(0, header + 8);
264
+ offtout(0, header + 16);
265
+ offtout(newsize, header + 24);
266
+ if (fwrite(header, 32, 1, pf) != 1)
267
+ err(1, "fwrite(%s)", patchfile);
268
+
269
+ /* Compute the differences, writing ctrl as we go */
270
+ if ((pfbz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)) == NULL)
271
+ errx(1, "BZ2_bzWriteOpen, bz2err = %d", bz2err);
272
+ scan=0;len=0;
273
+ lastscan=0;lastpos=0;lastoffset=0;
274
+ while(scan<newsize) {
275
+ oldscore=0;
276
+
277
+ for(scsc=scan+=len;scan<newsize;scan++) {
278
+ len=search(I,old,oldsize,new+scan,newsize-scan,
279
+ 0,oldsize,&pos);
280
+
281
+ for(;scsc<scan+len;scsc++)
282
+ if((scsc+lastoffset<oldsize) &&
283
+ (old[scsc+lastoffset] == new[scsc]))
284
+ oldscore++;
285
+
286
+ if(((len==oldscore) && (len!=0)) ||
287
+ (len>oldscore+8)) break;
288
+
289
+ if((scan+lastoffset<oldsize) &&
290
+ (old[scan+lastoffset] == new[scan]))
291
+ oldscore--;
292
+ };
293
+
294
+ if((len!=oldscore) || (scan==newsize)) {
295
+ s=0;Sf=0;lenf=0;
296
+ for(i=0;(lastscan+i<scan)&&(lastpos+i<oldsize);) {
297
+ if(old[lastpos+i]==new[lastscan+i]) s++;
298
+ i++;
299
+ if(s*2-i>Sf*2-lenf) { Sf=s; lenf=i; };
300
+ };
301
+
302
+ lenb=0;
303
+ if(scan<newsize) {
304
+ s=0;Sb=0;
305
+ for(i=1;(scan>=lastscan+i)&&(pos>=i);i++) {
306
+ if(old[pos-i]==new[scan-i]) s++;
307
+ if(s*2-i>Sb*2-lenb) { Sb=s; lenb=i; };
308
+ };
309
+ };
310
+
311
+ if(lastscan+lenf>scan-lenb) {
312
+ overlap=(lastscan+lenf)-(scan-lenb);
313
+ s=0;Ss=0;lens=0;
314
+ for(i=0;i<overlap;i++) {
315
+ if(new[lastscan+lenf-overlap+i]==
316
+ old[lastpos+lenf-overlap+i]) s++;
317
+ if(new[scan-lenb+i]==
318
+ old[pos-lenb+i]) s--;
319
+ if(s>Ss) { Ss=s; lens=i+1; };
320
+ };
321
+
322
+ lenf+=lens-overlap;
323
+ lenb-=lens;
324
+ };
325
+
326
+ for(i=0;i<lenf;i++)
327
+ db[dblen+i]=new[lastscan+i]-old[lastpos+i];
328
+ for(i=0;i<(scan-lenb)-(lastscan+lenf);i++)
329
+ eb[eblen+i]=new[lastscan+lenf+i];
330
+
331
+ dblen+=lenf;
332
+ eblen+=(scan-lenb)-(lastscan+lenf);
333
+
334
+ offtout(lenf,buf);
335
+ BZ2_bzWrite(&bz2err, pfbz2, buf, 8);
336
+ if (bz2err != BZ_OK)
337
+ errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
338
+
339
+ offtout((scan-lenb)-(lastscan+lenf),buf);
340
+ BZ2_bzWrite(&bz2err, pfbz2, buf, 8);
341
+ if (bz2err != BZ_OK)
342
+ errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
343
+
344
+ offtout((pos-lenb)-(lastpos+lenf),buf);
345
+ BZ2_bzWrite(&bz2err, pfbz2, buf, 8);
346
+ if (bz2err != BZ_OK)
347
+ errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
348
+
349
+ lastscan=scan-lenb;
350
+ lastpos=pos-lenb;
351
+ lastoffset=pos-scan;
352
+ };
353
+ };
354
+ BZ2_bzWriteClose(&bz2err, pfbz2, 0, NULL, NULL);
355
+ if (bz2err != BZ_OK)
356
+ errx(1, "BZ2_bzWriteClose, bz2err = %d", bz2err);
357
+
358
+ /* Compute size of compressed ctrl data */
359
+ if ((len = ftello(pf)) == -1)
360
+ err(1, "ftello");
361
+ offtout(len-32, header + 8);
362
+
363
+ /* Write compressed diff data */
364
+ if ((pfbz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)) == NULL)
365
+ errx(1, "BZ2_bzWriteOpen, bz2err = %d", bz2err);
366
+ BZ2_bzWrite(&bz2err, pfbz2, db, dblen);
367
+ if (bz2err != BZ_OK)
368
+ errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
369
+ BZ2_bzWriteClose(&bz2err, pfbz2, 0, NULL, NULL);
370
+ if (bz2err != BZ_OK)
371
+ errx(1, "BZ2_bzWriteClose, bz2err = %d", bz2err);
372
+
373
+ /* Compute size of compressed diff data */
374
+ if ((newsize = ftello(pf)) == -1)
375
+ err(1, "ftello");
376
+ offtout(newsize - len, header + 16);
377
+
378
+ /* Write compressed extra data */
379
+ if ((pfbz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)) == NULL)
380
+ errx(1, "BZ2_bzWriteOpen, bz2err = %d", bz2err);
381
+ BZ2_bzWrite(&bz2err, pfbz2, eb, eblen);
382
+ if (bz2err != BZ_OK)
383
+ errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
384
+ BZ2_bzWriteClose(&bz2err, pfbz2, 0, NULL, NULL);
385
+ if (bz2err != BZ_OK)
386
+ errx(1, "BZ2_bzWriteClose, bz2err = %d", bz2err);
387
+
388
+ /* Seek to the beginning, write the header, and close the file */
389
+ if (fseeko(pf, 0, SEEK_SET))
390
+ err(1, "fseeko");
391
+ if (fwrite(header, 32, 1, pf) != 1)
392
+ err(1, "fwrite(%s)", patchfile);
393
+ if (fclose(pf))
394
+ err(1, "fclose");
395
+
396
+ /* Free the memory we used */
397
+ free(db);
398
+ free(eb);
399
+ free(I);
400
+ free(old);
401
+ free(new);
402
+
403
+ return 0;
404
+ }
@@ -0,0 +1,6 @@
1
+ #ifndef BSDIFF_H
2
+ #define BSDIFF_H 1
3
+
4
+ int diff(const char *oldfile, const char *newfile, const char *patchfile);
5
+
6
+ #endif /* BSDIFF_H */
@@ -0,0 +1,204 @@
1
+ /*-
2
+ * Copyright 2003-2005 Colin Percival
3
+ * All rights reserved
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted providing that the following conditions
7
+ * are met:
8
+ * 1. Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * 2. Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ *
14
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
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
24
+ * POSSIBILITY OF SUCH DAMAGE.
25
+ */
26
+
27
+ #if 0
28
+ __FBSDID("$FreeBSD: src/usr.bin/bsdiff/bspatch/bspatch.c,v 1.1 2005/08/06 01:59:06 cperciva Exp $");
29
+ #endif
30
+
31
+ #include <bzlib.h>
32
+ #include <stdlib.h>
33
+ #include <stdio.h>
34
+ #include <string.h>
35
+ #include <err.h>
36
+ #include <unistd.h>
37
+ #include <fcntl.h>
38
+
39
+ #include <ruby.h>
40
+
41
+ static off_t offtin(u_char *buf)
42
+ {
43
+ off_t y;
44
+
45
+ y=buf[7]&0x7F;
46
+ y=y*256;y+=buf[6];
47
+ y=y*256;y+=buf[5];
48
+ y=y*256;y+=buf[4];
49
+ y=y*256;y+=buf[3];
50
+ y=y*256;y+=buf[2];
51
+ y=y*256;y+=buf[1];
52
+ y=y*256;y+=buf[0];
53
+
54
+ if(buf[7]&0x80) y=-y;
55
+
56
+ return y;
57
+ }
58
+
59
+ int patch(const char *oldfile, const char *newfile, const char *patchfile)
60
+ {
61
+ FILE * f, * cpf, * dpf, * epf;
62
+ BZFILE * cpfbz2, * dpfbz2, * epfbz2;
63
+ int cbz2err, dbz2err, ebz2err;
64
+ int fd;
65
+ ssize_t oldsize,newsize;
66
+ ssize_t bzctrllen,bzdatalen;
67
+ u_char header[32],buf[8];
68
+ u_char *old, *new;
69
+ off_t oldpos,newpos;
70
+ off_t ctrl[3];
71
+ off_t lenread;
72
+ off_t i;
73
+
74
+ /* Open patch file */
75
+ if ((f = fopen(patchfile, "r")) == NULL)
76
+ err(1, "fopen(%s)", patchfile);
77
+
78
+ /*
79
+ File format:
80
+ 0 8 "BSDIFF40"
81
+ 8 8 X
82
+ 16 8 Y
83
+ 24 8 sizeof(newfile)
84
+ 32 X bzip2(control block)
85
+ 32+X Y bzip2(diff block)
86
+ 32+X+Y ??? bzip2(extra block)
87
+ with control block 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
89
+ extra block; seek forwards in oldfile by z bytes".
90
+ */
91
+
92
+ /* Read header */
93
+ if (fread(header, 1, 32, f) < 32) {
94
+ if (feof(f))
95
+ errx(1, "Corrupt patch\n");
96
+ err(1, "fread(%s)", patchfile);
97
+ }
98
+
99
+ /* Check for appropriate magic */
100
+ if (memcmp(header, "BSDIFF40", 8) != 0)
101
+ errx(1, "Corrupt patch\n");
102
+
103
+ /* Read lengths from header */
104
+ bzctrllen=offtin(header+8);
105
+ bzdatalen=offtin(header+16);
106
+ newsize=offtin(header+24);
107
+ if((bzctrllen<0) || (bzdatalen<0) || (newsize<0))
108
+ errx(1,"Corrupt patch\n");
109
+
110
+ /* Close patch file and re-open it via libbzip2 at the right places */
111
+ if (fclose(f))
112
+ err(1, "fclose(%s)", patchfile);
113
+ if ((cpf = fopen(patchfile, "r")) == NULL)
114
+ err(1, "fopen(%s)", patchfile);
115
+ if (fseeko(cpf, 32, SEEK_SET))
116
+ err(1, "fseeko(%s, %lld)", patchfile,
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(patchfile, "r")) == NULL)
121
+ err(1, "fopen(%s)", patchfile);
122
+ if (fseeko(dpf, 32 + bzctrllen, SEEK_SET))
123
+ err(1, "fseeko(%s, %lld)", patchfile,
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(patchfile, "r")) == NULL)
128
+ err(1, "fopen(%s)", patchfile);
129
+ if (fseeko(epf, 32 + bzctrllen + bzdatalen, SEEK_SET))
130
+ err(1, "fseeko(%s, %lld)", patchfile,
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
+
135
+ if(((fd=open(oldfile,O_RDONLY,0))<0) ||
136
+ ((oldsize=lseek(fd,0,SEEK_END))==-1) ||
137
+ ((old=malloc(oldsize+1))==NULL) ||
138
+ (lseek(fd,0,SEEK_SET)!=0) ||
139
+ (read(fd,old,oldsize)!=oldsize) ||
140
+ (close(fd)==-1)) err(1,"%s",oldfile);
141
+ if((new=malloc(newsize+1))==NULL) err(1,NULL);
142
+
143
+ oldpos=0;newpos=0;
144
+ while(newpos<newsize) {
145
+ /* Read control data */
146
+ for(i=0;i<=2;i++) {
147
+ lenread = BZ2_bzRead(&cbz2err, cpfbz2, 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);
152
+ };
153
+
154
+ /* Sanity-check */
155
+ if(newpos+ctrl[0]>newsize)
156
+ errx(1,"Corrupt patch\n");
157
+
158
+ /* Read diff string */
159
+ lenread = BZ2_bzRead(&dbz2err, dpfbz2, new + newpos, ctrl[0]);
160
+ if ((lenread < ctrl[0]) ||
161
+ ((dbz2err != BZ_OK) && (dbz2err != BZ_STREAM_END)))
162
+ errx(1, "Corrupt patch\n");
163
+
164
+ /* Add old data to diff string */
165
+ for(i=0;i<ctrl[0];i++)
166
+ if((oldpos+i>=0) && (oldpos+i<oldsize))
167
+ new[newpos+i]+=old[oldpos+i];
168
+
169
+ /* Adjust pointers */
170
+ newpos+=ctrl[0];
171
+ oldpos+=ctrl[0];
172
+
173
+ /* Sanity-check */
174
+ if(newpos+ctrl[1]>newsize)
175
+ errx(1,"Corrupt patch\n");
176
+
177
+ /* Read extra string */
178
+ lenread = BZ2_bzRead(&ebz2err, epfbz2, new + newpos, ctrl[1]);
179
+ if ((lenread < ctrl[1]) ||
180
+ ((ebz2err != BZ_OK) && (ebz2err != BZ_STREAM_END)))
181
+ errx(1, "Corrupt patch\n");
182
+
183
+ /* Adjust pointers */
184
+ newpos+=ctrl[1];
185
+ oldpos+=ctrl[2];
186
+ };
187
+
188
+ /* Clean up the bzip2 reads */
189
+ BZ2_bzReadClose(&cbz2err, cpfbz2);
190
+ BZ2_bzReadClose(&dbz2err, dpfbz2);
191
+ BZ2_bzReadClose(&ebz2err, epfbz2);
192
+ if (fclose(cpf) || fclose(dpf) || fclose(epf))
193
+ err(1, "fclose(%s)", patchfile);
194
+
195
+ /* Write the new file */
196
+ if(((fd=open(newfile,O_CREAT|O_TRUNC|O_WRONLY,0666))<0) ||
197
+ (write(fd,new,newsize)!=newsize) || (close(fd)==-1))
198
+ err(1,"%s",newfile);
199
+
200
+ free(new);
201
+ free(old);
202
+
203
+ return 0;
204
+ }
@@ -0,0 +1,6 @@
1
+ #ifndef BSPATCH_H
2
+ #define BSPATCH_H 1
3
+
4
+ int patch(const char *oldfile, const char *newfile, const char *patchfile);
5
+
6
+ #endif /* BSPATCH_H */
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mkmf'
4
+
5
+ dir_config 'bsdiff'
6
+
7
+ # bzip2 dependency
8
+ abort 'could not find library bz2 - is libbz2-dev installed?' unless have_library 'bz2' # -lbz2 cflag
9
+
10
+ create_header # default name is extconf.h
11
+ create_makefile('bsdiff') # target bsdiff.so
@@ -0,0 +1,31 @@
1
+ #include <ruby.h>
2
+ #include "bsdiff.h"
3
+ #include "bspatch.h"
4
+
5
+ VALUE Bsdiff;
6
+
7
+ static VALUE
8
+ bsdiff_diff(VALUE self, VALUE oldfile, VALUE newfile, VALUE patchfile)
9
+ {
10
+ if(diff(StringValueCStr(oldfile), StringValueCStr(newfile), StringValueCStr(patchfile))) {
11
+ return Qtrue;
12
+ }
13
+ return Qfalse;
14
+ }
15
+
16
+ static VALUE
17
+ bsdiff_patch(VALUE self, VALUE oldfile, VALUE newfile, VALUE patchfile)
18
+ {
19
+ if(patch(StringValueCStr(oldfile), StringValueCStr(newfile), StringValueCStr(patchfile))) {
20
+ return Qtrue;
21
+ }
22
+ return Qfalse;
23
+ }
24
+
25
+ void
26
+ Init_bsdiff(void)
27
+ {
28
+ Bsdiff = rb_define_module("Bsdiff");
29
+ rb_define_singleton_method(Bsdiff, "diff", bsdiff_diff, 3);
30
+ rb_define_singleton_method(Bsdiff, "patch", bsdiff_patch, 3);
31
+ }
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bsdiff
4
+ VERSION = '0.0.0'
5
+ end
data/lib/bsdiff.rb ADDED
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'bsdiff/version'
4
+ begin
5
+ require_relative 'bsdiff/bsdiff.so'
6
+ rescue LoadError => e
7
+ e.message << "\n\nbsdiff.so not found, did you run `rake compile`?"
8
+ raise e
9
+ end
data/sig/bsdiff.rbs ADDED
@@ -0,0 +1,4 @@
1
+ module Bsdiff
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
Binary file
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bsdiff
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - MatzFan
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 2024-10-08 00:00:00.000000000 Z
11
+ dependencies: []
12
+ description: Ruby bindings for bsdiff and bspatch
13
+ executables: []
14
+ extensions: []
15
+ extra_rdoc_files: []
16
+ files:
17
+ - ".rubocop.yml"
18
+ - CHANGELOG.md
19
+ - LICENSE.txt
20
+ - README.md
21
+ - Rakefile
22
+ - diffs/bsdiff.c.diff
23
+ - diffs/bspatch.c.diff
24
+ - ext/bsdiff/bsdiff.c
25
+ - ext/bsdiff/bsdiff.h
26
+ - ext/bsdiff/bspatch.c
27
+ - ext/bsdiff/bspatch.h
28
+ - ext/bsdiff/extconf.rb
29
+ - ext/bsdiff/rb_bsdiff.c
30
+ - lib/bsdiff.rb
31
+ - lib/bsdiff/version.rb
32
+ - sig/bsdiff.rbs
33
+ - src/bsdiff_4.3.orig.tar.gz
34
+ homepage: https://gitlab.com/matzfan/bsdiff
35
+ licenses:
36
+ - BSD-2-Clause
37
+ metadata:
38
+ source_code_uri: https://gitlab.com/matzfan/bsdiff
39
+ changelog_uri: https://gitlab.com/matzfan/bsdiff/-/blob/master/CHANGELOG.md
40
+ rubygems_mfa_required: 'true'
41
+ rdoc_options: []
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: 3.1.0
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ requirements: []
55
+ rubygems_version: 3.6.0.dev
56
+ specification_version: 4
57
+ summary: Ruby bindings for the bsdiff binary patch tool
58
+ test_files: []