Skip to content

Commit 28ec891

Browse files
rtzhourtzhou
authored andcommitted
add bspatch tool
1 parent ece91bf commit 28ec891

30 files changed

+8444
-45
lines changed

BSTools/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/build

BSTools/build.gradle

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
apply plugin: 'com.android.library'
2+
apply plugin: 'com.novoda.bintray-release'
3+
4+
android {
5+
compileSdkVersion 23
6+
buildToolsVersion '25.0.2'
7+
8+
defaultConfig {
9+
minSdkVersion 16
10+
targetSdkVersion 23
11+
versionCode 1
12+
versionName "1.0"
13+
14+
ndk {
15+
moduleName "bspatch"
16+
ldLibs "log", "z", "m"
17+
abiFilters "armeabi", "armeabi-v7a"
18+
}
19+
}
20+
21+
buildTypes {
22+
release {
23+
minifyEnabled false
24+
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
25+
}
26+
}
27+
28+
lintOptions {
29+
abortOnError false
30+
}
31+
}
32+
33+
dependencies {
34+
compile fileTree(dir: 'libs', include: ['*.jar'])
35+
}
36+
37+
tasks.withType(Javadoc).all { enabled = false }
38+
39+
publish {
40+
artifactId = 'android-bspatch-lib'//模块名称
41+
userOrg = "iknow"
42+
groupId = "com.github.iknow4"
43+
uploadName = "AndroidBSPatchLib" //模块上传后所在的文件夹名称
44+
publishVersion = "1.0.0"//模块版本号
45+
desc = "android bspatch tool lib"
46+
licences = ["Apache-2.0"] //模块的licences
47+
}

BSTools/src/main/AndroidManifest.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
package="com.iknow.bspatch" >
4+
</manifest>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.iknow.tool;
2+
3+
/**
4+
* Author:J.Chou
5+
* Date: 2017.01.17 12:15 PM
6+
* Email: who_know_me@163.com
7+
* Describe:
8+
*/
9+
public class BsPatchGenerate {
10+
/**
11+
* 合并
12+
* @param oldfile 老版本的apk文件路劲
13+
* @param newfile 新的apk文件路劲
14+
* @param patchfile 拆分后的文件路劲
15+
*/
16+
public native static void patch(String oldfile, String newfile, String patchfile);
17+
18+
static{
19+
System.loadLibrary("bspatch");
20+
}
21+
}

BSTools/src/main/java/jni/Android.mk

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
LOCAL_PATH := $(call my-dir)
2+
3+
include $(CLEAR_VARS)
4+
5+
LOCAL_MODULE := bspatch
6+
LOCAL_SRC_FILES := bspatch.c
7+
8+
include $(BUILD_SHARED_LIBRARY)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
APP_ABI := armeabi
2+
APP_STL := stlport_static

BSTools/src/main/java/jni/bspatch.c

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
#include "com_wy_bsdiffupdate_util_BsPatchNative.h"
2+
#include "bzip2/bzlib.c"
3+
#include "bzip2/crctable.c"
4+
#include "bzip2/compress.c"
5+
#include "bzip2/decompress.c"
6+
#include "bzip2/randtable.c"
7+
#include "bzip2/blocksort.c"
8+
#include "bzip2/huffman.c"
9+
10+
#include <stdlib.h>
11+
#include <stdio.h>
12+
#include <string.h>
13+
#include <err.h>
14+
#include <unistd.h>
15+
#include <fcntl.h>
16+
17+
static off_t offtin(u_char *buf)
18+
{
19+
off_t y;
20+
21+
y=buf[7]&0x7F;
22+
y=y*256;y+=buf[6];
23+
y=y*256;y+=buf[5];
24+
y=y*256;y+=buf[4];
25+
y=y*256;y+=buf[3];
26+
y=y*256;y+=buf[2];
27+
y=y*256;y+=buf[1];
28+
y=y*256;y+=buf[0];
29+
30+
if(buf[7]&0x80) y=-y;
31+
32+
return y;
33+
}
34+
35+
int bspatch_main(int argc,char * argv[])
36+
{
37+
FILE * f, * cpf, * dpf, * epf;
38+
BZFILE * cpfbz2, * dpfbz2, * epfbz2;
39+
int cbz2err, dbz2err, ebz2err;
40+
int fd;
41+
ssize_t oldsize,newsize;
42+
ssize_t bzctrllen,bzdatalen;
43+
u_char header[32],buf[8];
44+
u_char *old, *new;
45+
off_t oldpos,newpos;
46+
off_t ctrl[3];
47+
off_t lenread;
48+
off_t i;
49+
50+
if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]);
51+
52+
/* Open patch file */
53+
if ((f = fopen(argv[3], "r")) == NULL)
54+
err(1, "fopen(%s)", argv[3]);
55+
56+
/*
57+
File format:
58+
0 8 "BSDIFF40"
59+
8 8 X
60+
16 8 Y
61+
24 8 sizeof(newfile)
62+
32 X bzip2(control block)
63+
32+X Y bzip2(diff block)
64+
32+X+Y ??? bzip2(extra block)
65+
with control block a set of triples (x,y,z) meaning "add x bytes
66+
from oldfile to x bytes from the diff block; copy y bytes from the
67+
extra block; seek forwards in oldfile by z bytes".
68+
*/
69+
70+
/* Read header */
71+
if (fread(header, 1, 32, f) < 32) {
72+
if (feof(f))
73+
errx(1, "Corrupt patch\n");
74+
err(1, "fread(%s)", argv[3]);
75+
}
76+
77+
/* Check for appropriate magic */
78+
if (memcmp(header, "BSDIFF40", 8) != 0)
79+
errx(1, "Corrupt patch\n");
80+
81+
/* Read lengths from header */
82+
bzctrllen=offtin(header+8);
83+
bzdatalen=offtin(header+16);
84+
newsize=offtin(header+24);
85+
if((bzctrllen<0) || (bzdatalen<0) || (newsize<0))
86+
errx(1,"Corrupt patch\n");
87+
88+
/* Close patch file and re-open it via libbzip2 at the right places */
89+
if (fclose(f))
90+
err(1, "fclose(%s)", argv[3]);
91+
if ((cpf = fopen(argv[3], "r")) == NULL)
92+
err(1, "fopen(%s)", argv[3]);
93+
if (fseeko(cpf, 32, SEEK_SET))
94+
err(1, "fseeko(%s, %lld)", argv[3],
95+
(long long)32);
96+
if ((cpfbz2 = BZ2_bzReadOpen(&cbz2err, cpf, 0, 0, NULL, 0)) == NULL)
97+
errx(1, "BZ2_bzReadOpen, bz2err = %d", cbz2err);
98+
if ((dpf = fopen(argv[3], "r")) == NULL)
99+
err(1, "fopen(%s)", argv[3]);
100+
if (fseeko(dpf, 32 + bzctrllen, SEEK_SET))
101+
err(1, "fseeko(%s, %lld)", argv[3],
102+
(long long)(32 + bzctrllen));
103+
if ((dpfbz2 = BZ2_bzReadOpen(&dbz2err, dpf, 0, 0, NULL, 0)) == NULL)
104+
errx(1, "BZ2_bzReadOpen, bz2err = %d", dbz2err);
105+
if ((epf = fopen(argv[3], "r")) == NULL)
106+
err(1, "fopen(%s)", argv[3]);
107+
if (fseeko(epf, 32 + bzctrllen + bzdatalen, SEEK_SET))
108+
err(1, "fseeko(%s, %lld)", argv[3],
109+
(long long)(32 + bzctrllen + bzdatalen));
110+
if ((epfbz2 = BZ2_bzReadOpen(&ebz2err, epf, 0, 0, NULL, 0)) == NULL)
111+
errx(1, "BZ2_bzReadOpen, bz2err = %d", ebz2err);
112+
113+
if(((fd=open(argv[1],O_RDONLY,0))<0) ||
114+
((oldsize=lseek(fd,0,SEEK_END))==-1) ||
115+
((old=malloc(oldsize+1))==NULL) ||
116+
(lseek(fd,0,SEEK_SET)!=0) ||
117+
(read(fd,old,oldsize)!=oldsize) ||
118+
(close(fd)==-1)) err(1,"%s",argv[1]);
119+
if((new=malloc(newsize+1))==NULL) err(1,NULL);
120+
121+
oldpos=0;newpos=0;
122+
while(newpos<newsize) {
123+
/* Read control data */
124+
for(i=0;i<=2;i++) {
125+
lenread = BZ2_bzRead(&cbz2err, cpfbz2, buf, 8);
126+
if ((lenread < 8) || ((cbz2err != BZ_OK) &&
127+
(cbz2err != BZ_STREAM_END)))
128+
errx(1, "Corrupt patch\n");
129+
ctrl[i]=offtin(buf);
130+
};
131+
132+
/* Sanity-check */
133+
if(newpos+ctrl[0]>newsize)
134+
errx(1,"Corrupt patch\n");
135+
136+
/* Read diff string */
137+
lenread = BZ2_bzRead(&dbz2err, dpfbz2, new + newpos, ctrl[0]);
138+
if ((lenread < ctrl[0]) ||
139+
((dbz2err != BZ_OK) && (dbz2err != BZ_STREAM_END)))
140+
errx(1, "Corrupt patch\n");
141+
142+
/* Add old data to diff string */
143+
for(i=0;i<ctrl[0];i++)
144+
if((oldpos+i>=0) && (oldpos+i<oldsize))
145+
new[newpos+i]+=old[oldpos+i];
146+
147+
/* Adjust pointers */
148+
newpos+=ctrl[0];
149+
oldpos+=ctrl[0];
150+
151+
/* Sanity-check */
152+
if(newpos+ctrl[1]>newsize)
153+
errx(1,"Corrupt patch\n");
154+
155+
/* Read extra string */
156+
lenread = BZ2_bzRead(&ebz2err, epfbz2, new + newpos, ctrl[1]);
157+
if ((lenread < ctrl[1]) ||
158+
((ebz2err != BZ_OK) && (ebz2err != BZ_STREAM_END)))
159+
errx(1, "Corrupt patch\n");
160+
161+
/* Adjust pointers */
162+
newpos+=ctrl[1];
163+
oldpos+=ctrl[2];
164+
};
165+
166+
/* Clean up the bzip2 reads */
167+
BZ2_bzReadClose(&cbz2err, cpfbz2);
168+
BZ2_bzReadClose(&dbz2err, dpfbz2);
169+
BZ2_bzReadClose(&ebz2err, epfbz2);
170+
if (fclose(cpf) || fclose(dpf) || fclose(epf))
171+
err(1, "fclose(%s)", argv[3]);
172+
173+
/* Write the new file */
174+
if(((fd=open(argv[2],O_CREAT|O_TRUNC|O_WRONLY,0666))<0) ||
175+
(write(fd,new,newsize)!=newsize) || (close(fd)==-1))
176+
err(1,"%s",argv[2]);
177+
178+
free(new);
179+
free(old);
180+
181+
return 0;
182+
}
183+
184+
//合并
185+
JNIEXPORT void JNICALL Java_com_iknow_bspatch_BsPatchNative_patch
186+
(JNIEnv *env, jclass jcls, jstring oldfile_jstr, jstring newfile_jstr, jstring patchfile_jstr){
187+
int argc = 4;
188+
char* oldfile = (char*)(*env)->GetStringUTFChars(env,oldfile_jstr, NULL);
189+
char* newfile = (char*)(*env)->GetStringUTFChars(env,newfile_jstr, NULL);
190+
char* patchfile = (char*)(*env)->GetStringUTFChars(env,patchfile_jstr, NULL);
191+
192+
//参数(第一个参数无效)
193+
char *argv[4];
194+
argv[0] = "bspatch";
195+
argv[1] = oldfile;
196+
argv[2] = newfile;
197+
argv[3] = patchfile;
198+
199+
bspatch_main(argc,argv);
200+
201+
(*env)->ReleaseStringUTFChars(env,oldfile_jstr, oldfile);
202+
(*env)->ReleaseStringUTFChars(env,newfile_jstr, newfile);
203+
(*env)->ReleaseStringUTFChars(env,patchfile_jstr, patchfile);
204+
205+
}
206+
207+

0 commit comments

Comments
 (0)