696 lines · 12.2 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. */ #include <u.h>#include <libc.h> #define	BIG	((1UL<<31)-1)#define VBIG	((1ULL<<63)-1)#define	LCASE	(1<<0)#define	UCASE	(1<<1)#define	SWAB	(1<<2)#define NERR	(1<<3)#define SYNC	(1<<4) int	cflag;int	fflag; char	*string;char	*ifile;char	*ofile;char	*ibuf;char	*obuf; vlong	skip;vlong	oseekn;vlong	iseekn;vlong	oseekb;vlong	iseekb;vlong	count; long	files	= 1;long	ibs	= 512;long	obs	= 512;long	bs;long	cbs;long	ibc;long	obc;long	cbc;long	nifr;long	nipr;long	nofr;long	nopr;long	ntrunc; int dotrunc = 1;int	ibf;int	obf; char	*op;int	nspace; uchar	etoa[256];uchar	atoe[256];uchar	atoibm[256]; int	quiet; void	flsh(void);int	match(char *s);vlong	number(vlong big);void	cnull(int cc);void	null(int c);void	ascii(int cc);void	unblock(int cc);void	ebcdic(int cc);void	ibm(int cc);void	block(int cc);void	term(char*);void	stats(void); #define	iskey(s)	((key[0] == '-') && (strcmp(key+1, s) == 0)) intmain(int argc, char *argv[]){	void (*conv)(int);	char *ip;	char *key;	int a, c; 	conv = null;	for(c=1; c<argc; c++) {		key = argv[c++];		if(c >= argc){			fprint(2, "dd: arg %s needs a value\n", key);			exits("arg");		}		string = argv[c];		if(iskey("ibs")) {			ibs = number(BIG);			continue;		}		if(iskey("obs")) {			obs = number(BIG);			continue;		}		if(iskey("cbs")) {			cbs = number(BIG);			continue;		}		if(iskey("bs")) {			bs = number(BIG);			continue;		}		if(iskey("if")) {			ifile = string;			continue;		}		if(iskey("of")) {			ofile = string;			continue;		}		if(iskey("trunc")) {			dotrunc = number(BIG);			continue;		}		if(iskey("quiet")) {			quiet = number(BIG);			continue;		}		if(iskey("skip")) {			skip = number(VBIG);			continue;		}		if(iskey("seek") || iskey("oseek")) {			oseekn = number(VBIG);			continue;		}		if(iskey("iseek")) {			iseekn = number(VBIG);			continue;		}		if(iskey("iseekb")) {			iseekb = number(VBIG);			continue;		}		if(iskey("oseekb")) {			oseekb = number(VBIG);			continue;		}		if(iskey("count")) {			count = number(VBIG);			continue;		}		if(iskey("files")) {			files = number(BIG);			continue;		}		if(iskey("conv")) {		cloop:			if(match(","))				goto cloop;			if(*string == '\0')				continue;			if(match("ebcdic")) {				conv = ebcdic;				goto cloop;			}			if(match("ibm")) {				conv = ibm;				goto cloop;			}			if(match("ascii")) {				conv = ascii;				goto cloop;			}			if(match("block")) {				conv = block;				goto cloop;			}			if(match("unblock")) {				conv = unblock;				goto cloop;			}			if(match("lcase")) {				cflag |= LCASE;				goto cloop;			}			if(match("ucase")) {				cflag |= UCASE;				goto cloop;			}			if(match("swab")) {				cflag |= SWAB;				goto cloop;			}			if(match("noerror")) {				cflag |= NERR;				goto cloop;			}			if(match("sync")) {				cflag |= SYNC;				goto cloop;			}			fprint(2, "dd: bad conv %s\n", argv[c]);			exits("arg");		}		fprint(2, "dd: bad arg: %s\n", key);		exits("arg");	}	if(conv == null && cflag&(LCASE|UCASE))		conv = cnull;	if(ifile)		ibf = open(ifile, 0);	else		ibf = dup(0, -1);	if(ibf < 0) {		fprint(2, "dd: open %s: %r\n", ifile);		exits("open");	}	if(ofile){		if(dotrunc)			obf = create(ofile, 1, 0664);		else			obf = open(ofile, 1);		if(obf < 0) {			fprint(2, "dd: create %s: %r\n", ofile);			exits("create");		}	}else{		obf = dup(1, -1);		if(obf < 0) {			fprint(2, "dd: can't dup file descriptor: %s: %r\n", ofile);			exits("dup");		}	}	if(bs)		ibs = obs = bs;	if(ibs == obs && conv == null)		fflag++;	if(ibs == 0 || obs == 0) {		fprint(2, "dd: counts: cannot be zero\n");		exits("counts");	}	ibuf = sbrk(ibs);	if(fflag)		obuf = ibuf;	else		obuf = sbrk(obs);	sbrk(64);	/* For good measure */	if(ibuf == (char *)-1 || obuf == (char *)-1) {		fprint(2, "dd: not enough memory: %r\n");		exits("memory");	}	ibc = 0;	obc = 0;	cbc = 0;	op = obuf; /*	if(signal(SIGINT, SIG_IGN) != SIG_IGN)		signal(SIGINT, term);*/	seek(obf, obs*oseekn, 1);	seek(ibf, ibs*iseekn, 1);	if(iseekb)		seek(ibf, iseekb, 0);	if(oseekb)		seek(obf, oseekb, 0);	while(skip) {		read(ibf, ibuf, ibs);		skip--;	} 	ip = 0;loop:	if(ibc-- == 0) {		ibc = 0;		if(count==0 || nifr+nipr!=count) {			if(cflag&(NERR|SYNC))			for(ip=ibuf+ibs; ip>ibuf;)				*--ip = 0;			ibc = read(ibf, ibuf, ibs);		}		if(ibc == -1) {			perror("read");			if((cflag&NERR) == 0) {				flsh();				term("errors");			}			ibc = 0;			for(c=0; c<ibs; c++)				if(ibuf[c] != 0)					ibc = c+1;			seek(ibf, ibs, 1);			stats();		}else if(ibc == 0 && --files<=0) {			flsh();			term(nil);		}		if(ibc != ibs) {			nipr++;			if(cflag&SYNC)				ibc = ibs;		} else			nifr++;		ip = ibuf;		c = (ibc>>1) & ~1;		if(cflag&SWAB && c)		do {			a = *ip++;			ip[-1] = *ip;			*ip++ = a;		} while(--c);		ip = ibuf;		if(fflag) {			obc = ibc;			flsh();			ibc = 0;		}		goto loop;	}	c = 0;	c |= *ip++;	c &= 0377;	(*conv)(c);	goto loop;} voidflsh(void){	int c; 	if(obc) {		/* don't perror dregs of previous errors on a short write */		werrstr("");		c = write(obf, obuf, obc);		if(c != obc) {			if(c > 0)				++nopr;			perror("write");			term("errors");		}		if(obc == obs)			nofr++;		else			nopr++;		obc = 0;	}} intmatch(char *s){	char *cs; 	cs = string;	while(*cs++ == *s)		if(*s++ == '\0')			goto true;	if(*s != '\0')		return 0; true:	cs--;	string = cs;	return 1;} vlongnumber(vlong big){	char *cs;	uvlong n; 	cs = string;	n = 0;	while(*cs >= '0' && *cs <= '9')		n = n*10 + *cs++ - '0';	for(;;)	switch(*cs++) { 	case 'k':		n *= 1024;		continue; 	case 'b':		n *= 512;		continue; /*	case '*':*/	case 'x':		string = cs;		n *= number(VBIG); 	case '\0':		if(n > big) {			fprint(2, "dd: argument %llud out of range\n", n);			exits("range");		}		return n;	}	/* never gets here */} voidcnull(int cc){	int c; 	c = cc;	if((cflag&UCASE) && c>='a' && c<='z')		c += 'A'-'a';	if((cflag&LCASE) && c>='A' && c<='Z')		c += 'a'-'A';	null(c);} voidnull(int c){ 	*op = c;	op++;	if(++obc >= obs) {		flsh();		op = obuf;	}} voidascii(int cc){	int c; 	c = etoa[cc];	if(cbs == 0) {		cnull(c);		return;	}	if(c == ' ') {		nspace++;		goto out;	}	while(nspace > 0) {		null(' ');		nspace--;	}	cnull(c); out:	if(++cbc >= cbs) {		null('\n');		cbc = 0;		nspace = 0;	}} voidunblock(int cc){	int c; 	c = cc & 0377;	if(cbs == 0) {		cnull(c);		return;	}	if(c == ' ') {		nspace++;		goto out;	}	while(nspace > 0) {		null(' ');		nspace--;	}	cnull(c); out:	if(++cbc >= cbs) {		null('\n');		cbc = 0;		nspace = 0;	}} voidebcdic(int cc){	int c; 	c = cc;	if(cflag&UCASE && c>='a' && c<='z')		c += 'A'-'a';	if(cflag&LCASE && c>='A' && c<='Z')		c += 'a'-'A';	c = atoe[c];	if(cbs == 0) {		null(c);		return;	}	if(cc == '\n') {		while(cbc < cbs) {

Lines 1–500 of 696.