216 lines · 4.1 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ /* * bsplit - split big binaries (copy-less plan 9 version) */ #include <u.h>#include <libc.h>#include <authsrv.h>		/* for ANAMELEN */ enum {	Stdin,	Sectsiz = 512,	Bufsiz = 256*Sectsiz,}; /* disk address (in bytes or sectors), also type of 2nd arg. to seek */typedef uvlong Daddr; #define BLEN(s)	((s)->wp - (s)->rp)#define BALLOC(s) ((s)->lim - (s)->base) typedef struct {	uchar*	rp;		/* first unconsumed byte */	uchar*	wp;		/* first empty byte */	uchar*	lim;		/* 1 past the end of the buffer */	uchar*	base;		/* start of the buffer */} Buffer; typedef struct {	/* parameters */	Daddr	maxoutsz;	/* maximum size of output file(s) */ 	Daddr	fileout;	/* bytes written to the current output file */	char	*filenm;	int	filesz;		/* size of filenm */	char	*prefix;	long	filenum;	int	outf;		/* open output file */ 	Buffer	buff;} Copy; /* global data */char *argv0; /* private data */static Copy cp = { 512*1024*1024 };	/* default maximum size */static int debug; static voidbufreset(Buffer *bp){	bp->rp = bp->wp = bp->base;} static voidbufinit(Buffer *bp, uchar *block, unsigned size){	bp->base = block;	bp->lim = bp->base + size;	bufreset(bp);} static int eopen(char *file, int mode){	int fd = open(file, mode); 	if (fd < 0)		sysfatal("can't open %s: %r", file);	return fd;} static int ecreate(char *file, int mode){	int fd = create(file, mode, 0666); 	if (fd < 0)		sysfatal("can't create %s: %r", file);	return fd;} static char *filename(Copy *cp){	return cp->filenm;} static int opennext(Copy *cp){	if (cp->outf >= 0)		sysfatal("opennext called with file open");	snprint(cp->filenm, cp->filesz, "%s%5.5ld", cp->prefix, cp->filenum++);	cp->outf = ecreate(cp->filenm, OWRITE);	cp->fileout = 0;	return cp->outf;} static int closeout(Copy *cp){	if (cp->outf >= 0) {		if (close(cp->outf) < 0)			sysfatal("error writing %s: %r", filename(cp));		cp->outf = -1;		cp->fileout = 0;	}	return cp->outf;} /* * process - process input file */static voidprocess(int in, char *inname){	int n = 1;	unsigned avail, tolim, wsz;	Buffer *bp = &cp.buff; 	USED(inname);	do {		if (BLEN(bp) == 0) {			if (bp->lim == bp->wp)				bufreset(bp);			n = read(in, bp->wp, bp->lim - bp->wp);			if (n <= 0)				break;			bp->wp += n;		}		if (cp.outf < 0)			opennext(&cp); 		/*		 * write from buffer's current point to end or enough bytes to		 * reach file-size limit.		 */		avail = BLEN(bp);		tolim = cp.maxoutsz - cp.fileout;		wsz = (tolim < avail? tolim: avail); 		/* try to write full sectors */		if (tolim >= avail && n > 0 && wsz >= Sectsiz)			wsz = (wsz / Sectsiz) * Sectsiz;		if (write(cp.outf, bp->rp, wsz) != wsz)			sysfatal("error writing %s: %r", filename(&cp));		bp->rp += wsz; 		cp.fileout += wsz;		if (cp.fileout >= cp.maxoutsz)			closeout(&cp);	} while (n > 0 || BLEN(bp) != 0);} static voidusage(void){	fprint(2, "usage: %s [-d][-p pfx][-s size] [file...]\n", argv0);	exits("usage");} voidmain(int argc, char **argv){	int i, errflg = 0;	uchar block[Bufsiz]; 	cp.prefix = "bs.";	ARGBEGIN {	case 'd':		debug++;		break;	case 'p':		cp.prefix = EARGF(usage());		break;	case 's':		cp.maxoutsz = atoll(EARGF(usage()));		if (cp.maxoutsz < 1)			errflg++;		break;	default:		errflg++;		break;	} ARGEND	if (errflg || argc < 0)		usage(); 	bufinit(&cp.buff, block, sizeof block);	cp.outf = -1;	cp.filesz = strlen(cp.prefix) + 2*ANAMELEN;	/* 2* is slop */	cp.filenm = malloc(cp.filesz + 1);	if (cp.filenm == nil)		sysfatal("no memory: %r"); 	if (argc == 0)		process(Stdin, "/fd/0");	else		for (i = 0; i < argc; i++) {			int in = eopen(argv[i], OREAD); 			process(in, argv[i]);			close(in);		}	closeout(&cp);	exits(0);}