ApplyPatch.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. /*-
  2. * Parts of this code are 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. #if 0
  27. __FBSDID("$FreeBSD: src/usr.bin/bsdiff/bspatch/bspatch.c,v 1.1 2005/08/06 01:59:06 cperciva Exp $");
  28. #endif
  29. #include "MemoryCompressor.h"
  30. #include <bzlib.h>
  31. #include <stdlib.h>
  32. #include <stdio.h>
  33. #include <string.h>
  34. #ifndef _WIN32
  35. // KevinJ - Windows compatibility
  36. #include <err.h>
  37. #include <unistd.h>
  38. #else
  39. typedef int ssize_t;
  40. #include <wchar.h>
  41. #include <io.h>
  42. #define fseeko fseek
  43. static void err(int i, ...)
  44. {
  45. exit(i);
  46. }
  47. static void errx(int i, ...)
  48. {
  49. exit(i);
  50. }
  51. #endif
  52. #include <fcntl.h>
  53. #ifndef _O_BINARY
  54. #define _O_BINARY 0
  55. #endif
  56. #ifndef O_BINARY
  57. #define O_BINARY _O_BINARY
  58. #endif
  59. static off_t offtin(unsigned char *buf)
  60. {
  61. off_t y;
  62. y=buf[7]&0x7F;
  63. y=y*256;y+=buf[6];
  64. y=y*256;y+=buf[5];
  65. y=y*256;y+=buf[4];
  66. y=y*256;y+=buf[3];
  67. y=y*256;y+=buf[2];
  68. y=y*256;y+=buf[1];
  69. y=y*256;y+=buf[0];
  70. if(buf[7]&0x80) y=-y;
  71. return y;
  72. }
  73. // This function modifies the main() function included in bspatch.c of bsdiff-4.3 found at http://www.daemonology.net/bsdiff/
  74. // It is changed to be a standalone function, to work entirely in memory, and to use my class MemoryDecompressor as an interface to BZip
  75. // Up to the caller to deallocate new
  76. bool ApplyPatch(char *old, unsigned int oldsize, char **_new, unsigned int *newsize, char *patch, unsigned int patchsize )
  77. {
  78. // FILE * f, * cpf, * dpf, * epf;
  79. // BZFILE * cpfbz2, * dpfbz2, * epfbz2;
  80. // int cbz2err, dbz2err, ebz2err;
  81. // int fd;
  82. // ssize_t oldsize,newsize;
  83. ssize_t bzctrllen,bzdatalen;
  84. //unsigned char header[32];
  85. unsigned char buf[8];
  86. // unsigned char *old, *_new;
  87. off_t oldpos,newpos;
  88. off_t ctrl[3];
  89. // off_t lenread;
  90. off_t i;
  91. MemoryDecompressor decompress;
  92. unsigned int coff, doff, eoff;
  93. // if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]);
  94. /* Open patch file */
  95. // if ((f = fopen(argv[3], "rb")) == NULL)
  96. // err(1, "fopen(%s)", argv[3]);
  97. /*
  98. File format:
  99. 0 8 "BSDIFF40"
  100. 8 8 X
  101. 16 8 Y
  102. 24 8 sizeof(newfile)
  103. 32 X bzip2(control block)
  104. 32+X Y bzip2(diff block)
  105. 32+X+Y ??? bzip2(extra block)
  106. with control block a set of triples (x,y,z) meaning "add x bytes
  107. from oldfile to x bytes from the diff block; copy y bytes from the
  108. extra block; seek forwards in oldfile by z bytes".
  109. */
  110. /* Read header */
  111. // if (fread(header, 1, 32, f) < 32) {
  112. // if (feof(f))
  113. // errx(1, "Corrupt patch\n",0);
  114. // err(1, "fread(%s)", argv[3]);
  115. // }
  116. // memcpy(header, patch, 32);
  117. /* Check for appropriate magic */
  118. if (memcmp(patch, "BSDIFF40", 8) != 0)
  119. // errx(1, "Corrupt patch\n",0);
  120. return false;
  121. /* Read lengths from header */
  122. bzctrllen=offtin((unsigned char*)patch+8);
  123. bzdatalen=offtin((unsigned char*)patch+16);
  124. *newsize=offtin((unsigned char*)patch+24);
  125. if((bzctrllen<0) || (bzdatalen<0) || (*newsize<0))
  126. // errx(1,"Corrupt patch\n",0);
  127. return false;
  128. /* Close patch file and re-open it via libbzip2 at the right places */
  129. // if (fclose(f))
  130. // err(1, "fclose(%s)", argv[3]);
  131. // if ((cpf = fopen(argv[3], "rb")) == NULL)
  132. // err(1, "fopen(%s)", argv[3]);
  133. // if (fseeko(cpf, 32, SEEK_SET))
  134. // err(1, "fseeko(%s, %lld)", argv[3],
  135. // (long long)32);
  136. // if ((cpfbz2 = BZ2_bzReadOpen(&cbz2err, cpf, 0, 0, NULL, 0)) == NULL)
  137. // errx(1, "BZ2_bzReadOpen, bz2err = %d", cbz2err);
  138. // if ((dpf = fopen(argv[3], "rb")) == NULL)
  139. // err(1, "fopen(%s)", argv[3]);
  140. // if (fseeko(dpf, 32 + bzctrllen, SEEK_SET))
  141. // err(1, "fseeko(%s, %lld)", argv[3],
  142. // (long long)(32 + bzctrllen));
  143. // if ((dpfbz2 = BZ2_bzReadOpen(&dbz2err, dpf, 0, 0, NULL, 0)) == NULL)
  144. // errx(1, "BZ2_bzReadOpen, bz2err = %d", dbz2err);
  145. // if ((epf = fopen(argv[3], "rb")) == NULL)
  146. // err(1, "fopen(%s)", argv[3]);
  147. // if (fseeko(epf, 32 + bzctrllen + bzdatalen, SEEK_SET))
  148. // err(1, "fseeko(%s, %lld)", argv[3],
  149. // (long long)(32 + bzctrllen + bzdatalen));
  150. // if ((epfbz2 = BZ2_bzReadOpen(&ebz2err, epf, 0, 0, NULL, 0)) == NULL)
  151. // errx(1, "BZ2_bzReadOpen, bz2err = %d", ebz2err);
  152. // decompress.Decompress((char*)patch+32, patchsize-32, true);
  153. coff=0;
  154. if (decompress.Decompress((char*)patch+32, bzctrllen, false)==false)
  155. return false;
  156. doff=decompress.GetTotalOutputSize();
  157. if (decompress.Decompress((char*)patch+32+bzctrllen, bzdatalen, false)==false)
  158. return false;
  159. eoff=decompress.GetTotalOutputSize();
  160. if (decompress.Decompress((char*)patch+32+bzctrllen+bzdatalen, patchsize-(32+bzctrllen+bzdatalen), true)==false)
  161. return false;
  162. // if(((fd=open(argv[1],O_RDONLY | _O_BINARY,0))<0) ||
  163. // ((oldsize=lseek(fd,0,SEEK_END))==-1) ||
  164. // ((old=(unsigned char*)malloc(oldsize+1))==NULL) ||
  165. // (lseek(fd,0,SEEK_SET)!=0) ||
  166. // (read(fd,old,oldsize)!=oldsize) ||
  167. // (close(fd)==-1)) err(1,"%s",argv[1]);
  168. // if((_new=(unsigned char*)malloc(newsize+1))==NULL) err(1,NULL);
  169. *_new = new char[*newsize+1];
  170. oldpos=0;newpos=0;
  171. while(newpos<(off_t)*newsize) {
  172. /* Read control data */
  173. for(i=0;i<=2;i++) {
  174. // lenread = BZ2_bzRead(&cbz2err, cpfbz2, buf, 8);
  175. // if ((lenread < 8) || ((cbz2err != BZ_OK) &&
  176. // (cbz2err != BZ_STREAM_END)))
  177. // errx(1, "Corrupt patch\n");
  178. memcpy(buf, decompress.GetOutput()+coff, 8);
  179. coff+=8;
  180. ctrl[i]=offtin(buf);
  181. };
  182. /* Sanity-check */
  183. if(newpos+ctrl[0]>(off_t)*newsize)
  184. {
  185. delete [] (*_new);
  186. return false;
  187. }
  188. /* Read diff string */
  189. //lenread = BZ2_bzRead(&dbz2err, dpfbz2, _new + newpos, ctrl[0]);
  190. //if ((lenread < ctrl[0]) ||
  191. // ((dbz2err != BZ_OK) && (dbz2err != BZ_STREAM_END)))
  192. // errx(1, "Corrupt patch\n");
  193. memcpy(*_new + newpos, decompress.GetOutput()+doff, ctrl[0]);
  194. doff+=ctrl[0];
  195. /* Add old data to diff string */
  196. for(i=0;i<ctrl[0];i++)
  197. if((oldpos+i>=0) && (oldpos+i<(off_t)oldsize))
  198. (*_new)[newpos+i]+=old[oldpos+i];
  199. /* Adjust pointers */
  200. newpos+=ctrl[0];
  201. oldpos+=ctrl[0];
  202. /* Sanity-check */
  203. if(newpos+ctrl[1]>(off_t)*newsize)
  204. {
  205. delete [] (*_new);
  206. return false;
  207. }
  208. /* Read extra string */
  209. //lenread = BZ2_bzRead(&ebz2err, epfbz2, _new + newpos, ctrl[1]);
  210. //if ((lenread < ctrl[1]) ||
  211. // ((ebz2err != BZ_OK) && (ebz2err != BZ_STREAM_END)))
  212. // errx(1, "Corrupt patch\n");
  213. memcpy(*_new + newpos, decompress.GetOutput()+eoff, ctrl[1]);
  214. eoff+=ctrl[1];
  215. /* Adjust pointers */
  216. newpos+=ctrl[1];
  217. oldpos+=ctrl[2];
  218. };
  219. /* Clean up the bzip2 reads */
  220. // BZ2_bzReadClose(&cbz2err, cpfbz2);
  221. // BZ2_bzReadClose(&dbz2err, dpfbz2);
  222. // BZ2_bzReadClose(&ebz2err, epfbz2);
  223. // if (fclose(cpf) || fclose(dpf) || fclose(epf))
  224. // err(1, "fclose(%s)", argv[3]);
  225. /* Write the new file */
  226. // if(((fd=open(argv[2],O_CREAT|O_TRUNC|O_WRONLY,0666))<0) ||
  227. // (write(fd,_new,newsize)!=newsize) || (close(fd)==-1))
  228. // err(1,"%s",argv[2]);
  229. // free(_new);
  230. // free(old);
  231. return true;
  232. }
  233. int TestPatchInMemory(int argc,char *argv[])
  234. {
  235. FILE *patchFile, *newFile, *oldFile;
  236. char *patch,*_new,*old;
  237. unsigned patchSize, oldSize;
  238. unsigned int newSize;
  239. int res;
  240. if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]);
  241. patchFile=fopen(argv[3], "rb");
  242. newFile=fopen(argv[2], "wb");
  243. oldFile=fopen(argv[1], "rb");
  244. fseeko(patchFile, 0, SEEK_END);
  245. fseeko(oldFile, 0, SEEK_END);
  246. patchSize=ftell(patchFile);
  247. oldSize=ftell(oldFile);
  248. fseeko(patchFile, 0, SEEK_SET);
  249. fseeko(oldFile, 0, SEEK_SET);
  250. patch = new char [patchSize];
  251. old = new char [oldSize];
  252. fread(patch, patchSize, 1, patchFile);
  253. fread(old, oldSize, 1, oldFile);
  254. res = ApplyPatch( old, oldSize, &_new, &newSize,patch, patchSize);
  255. fwrite(_new, newSize, 1, newFile);
  256. fclose(patchFile);
  257. fclose(newFile);
  258. fclose(oldFile);
  259. return res;
  260. }
  261. int PATCH_main(int argc,char * argv[])
  262. {
  263. FILE * f, * cpf, * dpf, * epf;
  264. BZFILE * cpfbz2, * dpfbz2, * epfbz2;
  265. int cbz2err, dbz2err, ebz2err;
  266. int fd;
  267. ssize_t oldsize,newsize;
  268. ssize_t bzctrllen,bzdatalen;
  269. unsigned char header[32],buf[8];
  270. unsigned char *old, *_new;
  271. off_t oldpos,newpos;
  272. off_t ctrl[3];
  273. off_t lenread;
  274. off_t i;
  275. unsigned bytesRead=0;
  276. if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]);
  277. /* Open patch file */
  278. if ((f = fopen(argv[3], "rb")) == NULL)
  279. err(1, "fopen(%s)", argv[3]);
  280. /*
  281. File format:
  282. 0 8 "BSDIFF40"
  283. 8 8 X
  284. 16 8 Y
  285. 24 8 sizeof(newfile)
  286. 32 X bzip2(control block)
  287. 32+X Y bzip2(diff block)
  288. 32+X+Y ??? bzip2(extra block)
  289. with control block a set of triples (x,y,z) meaning "add x bytes
  290. from oldfile to x bytes from the diff block; copy y bytes from the
  291. extra block; seek forwards in oldfile by z bytes".
  292. */
  293. /* Read header */
  294. if (fread(header, 1, 32, f) < 32) {
  295. if (feof(f))
  296. errx(1, "Corrupt patch\n");
  297. err(1, "fread(%s)", argv[3]);
  298. }
  299. /* Check for appropriate magic */
  300. if (memcmp(header, "BSDIFF40", 8) != 0)
  301. errx(1, "Corrupt patch\n");
  302. /* Read lengths from header */
  303. bzctrllen=offtin(header+8);
  304. bzdatalen=offtin(header+16);
  305. newsize=offtin(header+24);
  306. if((bzctrllen<0) || (bzdatalen<0) || (newsize<0))
  307. errx(1,"Corrupt patch\n");
  308. /* Close patch file and re-open it via libbzip2 at the right places */
  309. if (fclose(f))
  310. err(1, "fclose(%s)", argv[3]);
  311. if ((cpf = fopen(argv[3], "rb")) == NULL)
  312. err(1, "fopen(%s)", argv[3]);
  313. if (fseeko(cpf, 32, SEEK_SET))
  314. err(1, "fseeko(%s, %lld)", argv[3],
  315. (long long)32);
  316. if ((cpfbz2 = BZ2_bzReadOpen(&cbz2err, cpf, 0, 0, NULL, 0)) == NULL)
  317. errx(1, "BZ2_bzReadOpen, bz2err = %d", cbz2err);
  318. if ((dpf = fopen(argv[3], "rb")) == NULL)
  319. err(1, "fopen(%s)", argv[3]);
  320. if (fseeko(dpf, 32 + bzctrllen, SEEK_SET))
  321. err(1, "fseeko(%s, %lld)", argv[3],
  322. (long long)(32 + bzctrllen));
  323. if ((dpfbz2 = BZ2_bzReadOpen(&dbz2err, dpf, 0, 0, NULL, 0)) == NULL)
  324. errx(1, "BZ2_bzReadOpen, bz2err = %d", dbz2err);
  325. if ((epf = fopen(argv[3], "rb")) == NULL)
  326. err(1, "fopen(%s)", argv[3]);
  327. if (fseeko(epf, 32 + bzctrllen + bzdatalen, SEEK_SET))
  328. err(1, "fseeko(%s, %lld)", argv[3],
  329. (long long)(32 + bzctrllen + bzdatalen));
  330. if ((epfbz2 = BZ2_bzReadOpen(&ebz2err, epf, 0, 0, NULL, 0)) == NULL)
  331. errx(1, "BZ2_bzReadOpen, bz2err = %d", ebz2err);
  332. if(((fd=open(argv[1],O_RDONLY|O_BINARY,0))<0) ||
  333. ((oldsize=lseek(fd,0,SEEK_END))==-1) ||
  334. ((old=(unsigned char*)malloc(oldsize+1))==NULL) ||
  335. (lseek(fd,0,SEEK_SET)!=0) ||
  336. (read(fd,old,oldsize)!=oldsize) ||
  337. (close(fd)==-1)) err(1,"%s",argv[1]);
  338. if((_new=(unsigned char*)malloc(newsize+1))==NULL) err(1,NULL);
  339. oldpos=0;newpos=0;
  340. while(newpos<newsize) {
  341. /* Read control data */
  342. for(i=0;i<=2;i++) {
  343. lenread = BZ2_bzRead(&cbz2err, cpfbz2, buf, 8);
  344. if ((lenread < 8) || ((cbz2err != BZ_OK) &&
  345. (cbz2err != BZ_STREAM_END)))
  346. errx(1, "Corrupt patch\n");
  347. bytesRead+=8;
  348. //printf("cbz2err cpfbz2 %i %i\n", 8, bytesRead);
  349. ctrl[i]=offtin(buf);
  350. };
  351. /* Sanity-check */
  352. if(newpos+ctrl[0]>newsize)
  353. errx(1,"Corrupt patch\n");
  354. /* Read diff string */
  355. lenread = BZ2_bzRead(&dbz2err, dpfbz2, _new + newpos, ctrl[0]);
  356. bytesRead+=8;
  357. // printf("dbz2err dpfbz2 %i %i\n", ctrl[0], bytesRead);
  358. if ((lenread < ctrl[0]) ||
  359. ((dbz2err != BZ_OK) && (dbz2err != BZ_STREAM_END)))
  360. errx(1, "Corrupt patch\n");
  361. /* Add old data to diff string */
  362. for(i=0;i<ctrl[0];i++)
  363. if((oldpos+i>=0) && (oldpos+i<oldsize))
  364. _new[newpos+i]+=old[oldpos+i];
  365. /* Adjust pointers */
  366. newpos+=ctrl[0];
  367. oldpos+=ctrl[0];
  368. /* Sanity-check */
  369. if(newpos+ctrl[1]>newsize)
  370. errx(1,"Corrupt patch\n");
  371. /* Read extra string */
  372. lenread = BZ2_bzRead(&ebz2err, epfbz2, _new + newpos, ctrl[1]);
  373. bytesRead+=8;
  374. // printf("ebz2err epfbz2 %i %i\n", ctrl[1], bytesRead);
  375. if ((lenread < ctrl[1]) ||
  376. ((ebz2err != BZ_OK) && (ebz2err != BZ_STREAM_END)))
  377. errx(1, "Corrupt patch\n");
  378. /* Adjust pointers */
  379. newpos+=ctrl[1];
  380. oldpos+=ctrl[2];
  381. };
  382. /* Clean up the bzip2 reads */
  383. BZ2_bzReadClose(&cbz2err, cpfbz2);
  384. BZ2_bzReadClose(&dbz2err, dpfbz2);
  385. BZ2_bzReadClose(&ebz2err, epfbz2);
  386. if (fclose(cpf) || fclose(dpf) || fclose(epf))
  387. err(1, "fclose(%s)", argv[3]);
  388. /* Write the new file */
  389. if(((fd=open(argv[2],O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,0666))<0) ||
  390. (write(fd,_new,newsize)!=newsize) || (close(fd)==-1))
  391. err(1,"%s",argv[2]);
  392. free(_new);
  393. free(old);
  394. return 0;
  395. }
粤ICP备19079148号