Changeset View
Changeset View
Standalone View
Standalone View
usr.bin/bsdiff/bspatch/bspatch.c
Show All 38 Lines | |||||
#endif | #endif | ||||
#include <bzlib.h> | #include <bzlib.h> | ||||
#include <err.h> | #include <err.h> | ||||
#include <errno.h> | #include <errno.h> | ||||
#include <fcntl.h> | #include <fcntl.h> | ||||
#include <libgen.h> | #include <libgen.h> | ||||
#include <limits.h> | #include <limits.h> | ||||
#include <stdint.h> | |||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
#ifndef O_BINARY | #ifndef O_BINARY | ||||
#define O_BINARY 0 | #define O_BINARY 0 | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | int main(int argc, char *argv[]) | ||||
int cbz2err, dbz2err, ebz2err; | int cbz2err, dbz2err, ebz2err; | ||||
int newfd, oldfd; | int newfd, oldfd; | ||||
off_t oldsize, newsize; | off_t oldsize, newsize; | ||||
off_t bzctrllen, bzdatalen; | off_t bzctrllen, bzdatalen; | ||||
u_char header[32], buf[8]; | u_char header[32], buf[8]; | ||||
u_char *old, *new; | u_char *old, *new; | ||||
off_t oldpos, newpos; | off_t oldpos, newpos; | ||||
off_t ctrl[3]; | off_t ctrl[3]; | ||||
off_t lenread; | off_t i, lenread, offset; | ||||
off_t i; | |||||
#ifdef HAVE_CAPSICUM | #ifdef HAVE_CAPSICUM | ||||
cap_rights_t rights_dir, rights_ro, rights_wr; | cap_rights_t rights_dir, rights_ro, rights_wr; | ||||
#endif | #endif | ||||
if (argc != 4) | if (argc != 4) | ||||
usage(); | usage(); | ||||
/* Open patch file */ | /* Open patch file */ | ||||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | File format: | ||||
24 8 sizeof(newfile) | 24 8 sizeof(newfile) | ||||
32 X bzip2(control block) | 32 X bzip2(control block) | ||||
32+X Y bzip2(diff block) | 32+X Y bzip2(diff block) | ||||
32+X+Y ??? bzip2(extra block) | 32+X+Y ??? bzip2(extra block) | ||||
with control block a set of triples (x,y,z) meaning "add x bytes | with control block a set of triples (x,y,z) meaning "add x bytes | ||||
from oldfile to x bytes from the diff block; copy y bytes from the | from oldfile to x bytes from the diff block; copy y bytes from the | ||||
extra block; seek forwards in oldfile by z bytes". | extra block; seek forwards in oldfile by z bytes". | ||||
*/ | */ | ||||
_Static_assert(sizeof(header) == 32, "header size must be 32"); | |||||
/* Read header */ | /* Read header */ | ||||
if (fread(header, 1, 32, f) < 32) { | if (fread(header, 1, sizeof(header), f) < sizeof(header)) { | ||||
if (feof(f)) | if (feof(f)) | ||||
errx(1, "Corrupt patch"); | errx(1, "Corrupt patch"); | ||||
err(1, "fread(%s)", argv[3]); | err(1, "fread(%s)", argv[3]); | ||||
} | } | ||||
/* Check for appropriate magic */ | /* Check for appropriate magic */ | ||||
if (memcmp(header, "BSDIFF40", 8) != 0) | if (memcmp(header, "BSDIFF40", 8) != 0) | ||||
errx(1, "Corrupt patch"); | errx(1, "Corrupt patch"); | ||||
/* Read lengths from header */ | /* Read lengths from header */ | ||||
bzctrllen = offtin(header + 8); | bzctrllen = offtin(header + 8); | ||||
bzdatalen = offtin(header + 16); | bzdatalen = offtin(header + 16); | ||||
newsize = offtin(header + 24); | newsize = offtin(header + 24); | ||||
if (bzctrllen < 0 || bzctrllen > OFF_MAX - 32 || | if (bzctrllen < 0 || | ||||
bzdatalen < 0 || bzctrllen + 32 > OFF_MAX - bzdatalen || | bzctrllen > (off_t)(OFF_MAX - sizeof(header)) || | ||||
bzdatalen < 0 || | |||||
(off_t)(bzctrllen + sizeof(header)) > OFF_MAX - bzdatalen || | |||||
newsize < 0 || newsize > SSIZE_MAX) | newsize < 0 || newsize > SSIZE_MAX) | ||||
errx(1, "Corrupt patch"); | errx(1, "Corrupt patch"); | ||||
/* Close patch file and re-open it via libbzip2 at the right places */ | /* Close patch file and re-open it via libbzip2 at the right places */ | ||||
if (fclose(f)) | if (fclose(f)) | ||||
err(1, "fclose(%s)", argv[3]); | err(1, "fclose(%s)", argv[3]); | ||||
if (fseeko(cpf, 32, SEEK_SET)) | offset = sizeof(header); | ||||
err(1, "fseeko(%s, %lld)", argv[3], | if (fseeko(cpf, offset, SEEK_SET)) | ||||
(long long)32); | err(1, "fseeko(%s, %jd)", argv[3], (intmax_t)offset); | ||||
if ((cpfbz2 = BZ2_bzReadOpen(&cbz2err, cpf, 0, 0, NULL, 0)) == NULL) | if ((cpfbz2 = BZ2_bzReadOpen(&cbz2err, cpf, 0, 0, NULL, 0)) == NULL) | ||||
errx(1, "BZ2_bzReadOpen, bz2err = %d", cbz2err); | errx(1, "BZ2_bzReadOpen, bz2err = %d", cbz2err); | ||||
if (fseeko(dpf, 32 + bzctrllen, SEEK_SET)) | offset += bzctrllen; | ||||
err(1, "fseeko(%s, %lld)", argv[3], | if (fseeko(dpf, offset, SEEK_SET)) | ||||
(long long)(32 + bzctrllen)); | err(1, "fseeko(%s, %jd)", argv[3], (intmax_t)offset); | ||||
if ((dpfbz2 = BZ2_bzReadOpen(&dbz2err, dpf, 0, 0, NULL, 0)) == NULL) | if ((dpfbz2 = BZ2_bzReadOpen(&dbz2err, dpf, 0, 0, NULL, 0)) == NULL) | ||||
errx(1, "BZ2_bzReadOpen, bz2err = %d", dbz2err); | errx(1, "BZ2_bzReadOpen, bz2err = %d", dbz2err); | ||||
if (fseeko(epf, 32 + bzctrllen + bzdatalen, SEEK_SET)) | offset += bzdatalen; | ||||
err(1, "fseeko(%s, %lld)", argv[3], | if (fseeko(epf, offset, SEEK_SET)) | ||||
(long long)(32 + bzctrllen + bzdatalen)); | err(1, "fseeko(%s, %jd)", argv[3], (intmax_t)offset); | ||||
if ((epfbz2 = BZ2_bzReadOpen(&ebz2err, epf, 0, 0, NULL, 0)) == NULL) | if ((epfbz2 = BZ2_bzReadOpen(&ebz2err, epf, 0, 0, NULL, 0)) == NULL) | ||||
errx(1, "BZ2_bzReadOpen, bz2err = %d", ebz2err); | errx(1, "BZ2_bzReadOpen, bz2err = %d", ebz2err); | ||||
if ((oldsize = lseek(oldfd, 0, SEEK_END)) == -1 || | if ((oldsize = lseek(oldfd, 0, SEEK_END)) == -1 || | ||||
oldsize > SSIZE_MAX || | oldsize > SSIZE_MAX || | ||||
(old = malloc(oldsize)) == NULL || | (old = malloc(oldsize)) == NULL || | ||||
lseek(oldfd, 0, SEEK_SET) != 0 || | lseek(oldfd, 0, SEEK_SET) != 0 || | ||||
read(oldfd, old, oldsize) != oldsize || | read(oldfd, old, oldsize) != oldsize || | ||||
▲ Show 20 Lines • Show All 74 Lines • Show Last 20 Lines |