Changeset View
Changeset View
Standalone View
Standalone View
head/usr.bin/bsdiff/bspatch/bspatch.c
Show All 36 Lines | |||||
#define HAVE_CAPSICUM | #define HAVE_CAPSICUM | ||||
#endif | #endif | ||||
#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 <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 | ||||
static char *newfile; | |||||
static int dirfd = -1; | |||||
static void | |||||
exit_cleanup(void) | |||||
{ | |||||
if (dirfd != -1 && newfile != NULL) | |||||
if (unlinkat(dirfd, newfile, 0)) | |||||
warn("unlinkat"); | |||||
} | |||||
static off_t offtin(u_char *buf) | static off_t offtin(u_char *buf) | ||||
{ | { | ||||
off_t y; | off_t y; | ||||
y = buf[7] & 0x7F; | y = buf[7] & 0x7F; | ||||
y = y * 256; y += buf[6]; | y = y * 256; y += buf[6]; | ||||
y = y * 256; y += buf[5]; | y = y * 256; y += buf[5]; | ||||
y = y * 256; y += buf[4]; | y = y * 256; y += buf[4]; | ||||
Show All 15 Lines | usage(void) | ||||
fprintf(stderr, "usage: bspatch oldfile newfile patchfile\n"); | fprintf(stderr, "usage: bspatch oldfile newfile patchfile\n"); | ||||
exit(1); | exit(1); | ||||
} | } | ||||
int main(int argc, char *argv[]) | int main(int argc, char *argv[]) | ||||
{ | { | ||||
FILE *f, *cpf, *dpf, *epf; | FILE *f, *cpf, *dpf, *epf; | ||||
BZFILE *cpfbz2, *dpfbz2, *epfbz2; | BZFILE *cpfbz2, *dpfbz2, *epfbz2; | ||||
char *directory, *namebuf; | |||||
int cbz2err, dbz2err, ebz2err; | int cbz2err, dbz2err, ebz2err; | ||||
int newfd, oldfd; | int newfd, oldfd; | ||||
ssize_t oldsize, newsize; | ssize_t oldsize, newsize; | ||||
ssize_t bzctrllen, bzdatalen; | ssize_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 lenread; | ||||
off_t i; | off_t i; | ||||
#ifdef HAVE_CAPSICUM | #ifdef HAVE_CAPSICUM | ||||
cap_rights_t 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 */ | ||||
if ((f = fopen(argv[3], "rb")) == NULL) | if ((f = fopen(argv[3], "rb")) == NULL) | ||||
err(1, "fopen(%s)", argv[3]); | err(1, "fopen(%s)", argv[3]); | ||||
/* Open patch file for control block */ | /* Open patch file for control block */ | ||||
if ((cpf = fopen(argv[3], "rb")) == NULL) | if ((cpf = fopen(argv[3], "rb")) == NULL) | ||||
err(1, "fopen(%s)", argv[3]); | err(1, "fopen(%s)", argv[3]); | ||||
/* open patch file for diff block */ | /* open patch file for diff block */ | ||||
if ((dpf = fopen(argv[3], "rb")) == NULL) | if ((dpf = fopen(argv[3], "rb")) == NULL) | ||||
err(1, "fopen(%s)", argv[3]); | err(1, "fopen(%s)", argv[3]); | ||||
/* open patch file for extra block */ | /* open patch file for extra block */ | ||||
if ((epf = fopen(argv[3], "rb")) == NULL) | if ((epf = fopen(argv[3], "rb")) == NULL) | ||||
err(1, "fopen(%s)", argv[3]); | err(1, "fopen(%s)", argv[3]); | ||||
/* open oldfile */ | /* open oldfile */ | ||||
if ((oldfd = open(argv[1], O_RDONLY | O_BINARY, 0)) < 0) | if ((oldfd = open(argv[1], O_RDONLY | O_BINARY, 0)) < 0) | ||||
err(1, "open(%s)", argv[1]); | err(1, "open(%s)", argv[1]); | ||||
/* open directory where we'll write newfile */ | |||||
if ((namebuf = strdup(argv[2])) == NULL || | |||||
(directory = dirname(namebuf)) == NULL || | |||||
(dirfd = open(directory, O_DIRECTORY)) < 0) | |||||
err(1, "open %s", argv[2]); | |||||
free(namebuf); | |||||
if ((newfile = basename(argv[2])) == NULL) | |||||
err(1, "basename"); | |||||
/* open newfile */ | /* open newfile */ | ||||
if ((newfd = open(argv[2], O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, | if ((newfd = openat(dirfd, newfile, | ||||
0666)) < 0) | O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0666)) < 0) | ||||
err(1, "open(%s)", argv[2]); | err(1, "open(%s)", argv[2]); | ||||
atexit(exit_cleanup); | |||||
#ifdef HAVE_CAPSICUM | #ifdef HAVE_CAPSICUM | ||||
if (cap_enter() < 0) { | if (cap_enter() < 0) { | ||||
/* Failed to sandbox, fatal if CAPABILITY_MODE enabled */ | /* Failed to sandbox, fatal if CAPABILITY_MODE enabled */ | ||||
if (errno != ENOSYS) | if (errno != ENOSYS) | ||||
err(1, "failed to enter security sandbox"); | err(1, "failed to enter security sandbox"); | ||||
} else { | } else { | ||||
/* Capsicum Available */ | /* Capsicum Available */ | ||||
cap_rights_init(&rights_ro, CAP_READ, CAP_FSTAT, CAP_SEEK); | cap_rights_init(&rights_ro, CAP_READ, CAP_FSTAT, CAP_SEEK); | ||||
cap_rights_init(&rights_wr, CAP_WRITE); | cap_rights_init(&rights_wr, CAP_WRITE); | ||||
cap_rights_init(&rights_dir, CAP_UNLINKAT); | |||||
if (cap_rights_limit(fileno(f), &rights_ro) < 0 || | if (cap_rights_limit(fileno(f), &rights_ro) < 0 || | ||||
cap_rights_limit(fileno(cpf), &rights_ro) < 0 || | cap_rights_limit(fileno(cpf), &rights_ro) < 0 || | ||||
cap_rights_limit(fileno(dpf), &rights_ro) < 0 || | cap_rights_limit(fileno(dpf), &rights_ro) < 0 || | ||||
cap_rights_limit(fileno(epf), &rights_ro) < 0 || | cap_rights_limit(fileno(epf), &rights_ro) < 0 || | ||||
cap_rights_limit(oldfd, &rights_ro) < 0 || | cap_rights_limit(oldfd, &rights_ro) < 0 || | ||||
cap_rights_limit(newfd, &rights_wr) < 0) | cap_rights_limit(newfd, &rights_wr) < 0 || | ||||
cap_rights_limit(dirfd, &rights_dir) < 0) | |||||
err(1, "cap_rights_limit() failed, could not restrict" | err(1, "cap_rights_limit() failed, could not restrict" | ||||
" capabilities"); | " capabilities"); | ||||
} | } | ||||
#endif | #endif | ||||
/* | /* | ||||
File format: | File format: | ||||
0 8 "BSDIFF40" | 0 8 "BSDIFF40" | ||||
▲ Show 20 Lines • Show All 109 Lines • ▼ Show 20 Lines | #endif | ||||
BZ2_bzReadClose(&dbz2err, dpfbz2); | BZ2_bzReadClose(&dbz2err, dpfbz2); | ||||
BZ2_bzReadClose(&ebz2err, epfbz2); | BZ2_bzReadClose(&ebz2err, epfbz2); | ||||
if (fclose(cpf) || fclose(dpf) || fclose(epf)) | if (fclose(cpf) || fclose(dpf) || fclose(epf)) | ||||
err(1, "fclose(%s)", argv[3]); | err(1, "fclose(%s)", argv[3]); | ||||
/* Write the new file */ | /* Write the new file */ | ||||
if (write(newfd, new, newsize) != newsize || close(newfd) == -1) | if (write(newfd, new, newsize) != newsize || close(newfd) == -1) | ||||
err(1, "%s", argv[2]); | err(1, "%s", argv[2]); | ||||
/* Disable atexit cleanup */ | |||||
newfile = NULL; | |||||
free(new); | free(new); | ||||
free(old); | free(old); | ||||
return (0); | return (0); | ||||
} | } |