plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

dd.c (11887B)


      1 #include <u.h>
      2 #include <libc.h>
      3 
      4 #define	BIG	((1UL<<31)-1)
      5 #define VBIG	((1ULL<<63)-1)
      6 #define	LCASE	(1<<0)
      7 #define	UCASE	(1<<1)
      8 #define	SWAB	(1<<2)
      9 #define NERR	(1<<3)
     10 #define SYNC	(1<<4)
     11 
     12 int	cflag;
     13 int	fflag;
     14 
     15 char	*string;
     16 char	*ifile;
     17 char	*ofile;
     18 char	*ibuf;
     19 char	*obuf;
     20 
     21 vlong	skip;
     22 vlong	oseekn;
     23 vlong	iseekn;
     24 vlong	count;
     25 
     26 long	files	= 1;
     27 long	ibs	= 512;
     28 long	obs	= 512;
     29 long	bs;
     30 long	cbs;
     31 long	ibc;
     32 long	obc;
     33 long	cbc;
     34 long	nifr;
     35 long	nipr;
     36 long	nofr;
     37 long	nopr;
     38 long	ntrunc;
     39 
     40 int dotrunc = 1;
     41 int	ibf;
     42 int	obf;
     43 
     44 char	*op;
     45 int	nspace;
     46 
     47 uchar	etoa[256];
     48 uchar	atoe[256];
     49 uchar	atoibm[256];
     50 
     51 int	quiet;
     52 
     53 void	flsh(void);
     54 int	match(char *s);
     55 vlong	number(vlong big);
     56 void	cnull(int cc);
     57 void	null(int c);
     58 void	ascii(int cc);
     59 void	unblock(int cc);
     60 void	ebcdic(int cc);
     61 void	ibm(int cc);
     62 void	block(int cc);
     63 void	term(char*);
     64 void	stats(void);
     65 
     66 #define	iskey(s)	((key[0] == '-') && (strcmp(key+1, s) == 0))
     67 
     68 int
     69 main(int argc, char *argv[])
     70 {
     71 	void (*conv)(int);
     72 	char *ip;
     73 	char *key;
     74 	int a, c;
     75 
     76 	conv = null;
     77 	for(c=1; c<argc; c++) {
     78 		key = argv[c++];
     79 		if(c >= argc){
     80 			fprint(2, "dd: arg %s needs a value\n", key);
     81 			exits("arg");
     82 		}
     83 		string = argv[c];
     84 		if(iskey("ibs")) {
     85 			ibs = number(BIG);
     86 			continue;
     87 		}
     88 		if(iskey("obs")) {
     89 			obs = number(BIG);
     90 			continue;
     91 		}
     92 		if(iskey("cbs")) {
     93 			cbs = number(BIG);
     94 			continue;
     95 		}
     96 		if(iskey("bs")) {
     97 			bs = number(BIG);
     98 			continue;
     99 		}
    100 		if(iskey("if")) {
    101 			ifile = string;
    102 			continue;
    103 		}
    104 		if(iskey("of")) {
    105 			ofile = string;
    106 			continue;
    107 		}
    108 		if(iskey("trunc")) {
    109 			dotrunc = number(BIG);
    110 			continue;
    111 		}
    112 		if(iskey("quiet")) {
    113 			quiet = number(BIG);
    114 			continue;
    115 		}
    116 		if(iskey("skip")) {
    117 			skip = number(VBIG);
    118 			continue;
    119 		}
    120 		if(iskey("seek") || iskey("oseek")) {
    121 			oseekn = number(VBIG);
    122 			continue;
    123 		}
    124 		if(iskey("iseek")) {
    125 			iseekn = number(VBIG);
    126 			continue;
    127 		}
    128 		if(iskey("count")) {
    129 			count = number(VBIG);
    130 			continue;
    131 		}
    132 		if(iskey("files")) {
    133 			files = number(BIG);
    134 			continue;
    135 		}
    136 		if(iskey("conv")) {
    137 		cloop:
    138 			if(match(","))
    139 				goto cloop;
    140 			if(*string == '\0')
    141 				continue;
    142 			if(match("ebcdic")) {
    143 				conv = ebcdic;
    144 				goto cloop;
    145 			}
    146 			if(match("ibm")) {
    147 				conv = ibm;
    148 				goto cloop;
    149 			}
    150 			if(match("ascii")) {
    151 				conv = ascii;
    152 				goto cloop;
    153 			}
    154 			if(match("block")) {
    155 				conv = block;
    156 				goto cloop;
    157 			}
    158 			if(match("unblock")) {
    159 				conv = unblock;
    160 				goto cloop;
    161 			}
    162 			if(match("lcase")) {
    163 				cflag |= LCASE;
    164 				goto cloop;
    165 			}
    166 			if(match("ucase")) {
    167 				cflag |= UCASE;
    168 				goto cloop;
    169 			}
    170 			if(match("swab")) {
    171 				cflag |= SWAB;
    172 				goto cloop;
    173 			}
    174 			if(match("noerror")) {
    175 				cflag |= NERR;
    176 				goto cloop;
    177 			}
    178 			if(match("sync")) {
    179 				cflag |= SYNC;
    180 				goto cloop;
    181 			}
    182 			fprint(2, "dd: bad conv %s\n", argv[c]);
    183 			exits("arg");
    184 		}
    185 		fprint(2, "dd: bad arg: %s\n", key);
    186 		exits("arg");
    187 	}
    188 	if(conv == null && cflag&(LCASE|UCASE))
    189 		conv = cnull;
    190 	if(ifile)
    191 		ibf = open(ifile, 0);
    192 	else
    193 		ibf = dup(0, -1);
    194 	if(ibf < 0) {
    195 		fprint(2, "dd: open %s: %r\n", ifile);
    196 		exits("open");
    197 	}
    198 	if(ofile){
    199 		if(dotrunc)
    200 			obf = create(ofile, 1, 0664);
    201 		else
    202 			obf = open(ofile, 1);
    203 		if(obf < 0) {
    204 			fprint(2, "dd: create %s: %r\n", ofile);
    205 			exits("create");
    206 		}
    207 	}else{
    208 		obf = dup(1, -1);
    209 		if(obf < 0) {
    210 			fprint(2, "dd: can't dup file descriptor: %s: %r\n", ofile);
    211 			exits("dup");
    212 		}
    213 	}
    214 	if(bs)
    215 		ibs = obs = bs;
    216 	if(ibs == obs && conv == null)
    217 		fflag++;
    218 	if(ibs == 0 || obs == 0) {
    219 		fprint(2, "dd: counts: cannot be zero\n");
    220 		exits("counts");
    221 	}
    222 	ibuf = malloc(ibs);
    223 	if(fflag)
    224 		obuf = ibuf;
    225 	else
    226 		obuf = malloc(obs);
    227 	if(ibuf == (char *)0 || obuf == (char *)0) {
    228 		fprint(2, "dd: not enough memory: %r\n");
    229 		exits("memory");
    230 	}
    231 	ibc = 0;
    232 	obc = 0;
    233 	cbc = 0;
    234 	op = obuf;
    235 
    236 /*
    237 	if(signal(SIGINT, SIG_IGN) != SIG_IGN)
    238 		signal(SIGINT, term);
    239 */
    240 	seek(obf, obs*oseekn, 1);
    241 	seek(ibf, ibs*iseekn, 1);
    242 	while(skip) {
    243 		read(ibf, ibuf, ibs);
    244 		skip--;
    245 	}
    246 
    247 	ip = 0;
    248 loop:
    249 	if(ibc-- == 0) {
    250 		ibc = 0;
    251 		if(count==0 || nifr+nipr!=count) {
    252 			if(cflag&(NERR|SYNC))
    253 			for(ip=ibuf+ibs; ip>ibuf;)
    254 				*--ip = 0;
    255 			ibc = read(ibf, ibuf, ibs);
    256 		}
    257 		if(ibc == -1) {
    258 			perror("read");
    259 			if((cflag&NERR) == 0) {
    260 				flsh();
    261 				term("errors");
    262 			}
    263 			ibc = 0;
    264 			for(c=0; c<ibs; c++)
    265 				if(ibuf[c] != 0)
    266 					ibc = c+1;
    267 			seek(ibf, ibs, 1);
    268 			stats();
    269 		}else if(ibc == 0 && --files<=0) {
    270 			flsh();
    271 			term(nil);
    272 		}
    273 		if(ibc != ibs) {
    274 			nipr++;
    275 			if(cflag&SYNC)
    276 				ibc = ibs;
    277 		} else
    278 			nifr++;
    279 		ip = ibuf;
    280 		c = (ibc>>1) & ~1;
    281 		if(cflag&SWAB && c)
    282 		do {
    283 			a = *ip++;
    284 			ip[-1] = *ip;
    285 			*ip++ = a;
    286 		} while(--c);
    287 		ip = ibuf;
    288 		if(fflag) {
    289 			obc = ibc;
    290 			flsh();
    291 			ibc = 0;
    292 		}
    293 		goto loop;
    294 	}
    295 	c = 0;
    296 	c |= *ip++;
    297 	c &= 0377;
    298 	(*conv)(c);
    299 	goto loop;
    300 
    301 	return 0;  // shut up apple gcc
    302 }
    303 
    304 void
    305 flsh(void)
    306 {
    307 	int c;
    308 
    309 	if(obc) {
    310 		/* don't perror dregs of previous errors on a short write */
    311 		werrstr("");
    312 		c = write(obf, obuf, obc);
    313 		if(c != obc) {
    314 			if(c > 0)
    315 				++nopr;
    316 			perror("write");
    317 			term("errors");
    318 		}
    319 		if(obc == obs)
    320 			nofr++;
    321 		else
    322 			nopr++;
    323 		obc = 0;
    324 	}
    325 }
    326 
    327 int
    328 match(char *s)
    329 {
    330 	char *cs;
    331 
    332 	cs = string;
    333 	while(*cs++ == *s)
    334 		if(*s++ == '\0')
    335 			goto true;
    336 	if(*s != '\0')
    337 		return 0;
    338 
    339 true:
    340 	cs--;
    341 	string = cs;
    342 	return 1;
    343 }
    344 
    345 vlong
    346 number(vlong big)
    347 {
    348 	char *cs;
    349 	uvlong n;
    350 
    351 	cs = string;
    352 	n = 0;
    353 	while(*cs >= '0' && *cs <= '9')
    354 		n = n*10 + *cs++ - '0';
    355 	for(;;)
    356 	switch(*cs++) {
    357 
    358 	case 'k':
    359 		n *= 1024;
    360 		continue;
    361 
    362 	case 'b':
    363 		n *= 512;
    364 		continue;
    365 
    366 /*	case '*':*/
    367 	case 'x':
    368 		string = cs;
    369 		n *= number(VBIG);
    370 
    371 	case '\0':
    372 		if(n > big) {
    373 			fprint(2, "dd: argument %llud out of range\n", n);
    374 			exits("range");
    375 		}
    376 		return n;
    377 	}
    378 	/* never gets here */
    379 }
    380 
    381 void
    382 cnull(int cc)
    383 {
    384 	int c;
    385 
    386 	c = cc;
    387 	if((cflag&UCASE) && c>='a' && c<='z')
    388 		c += 'A'-'a';
    389 	if((cflag&LCASE) && c>='A' && c<='Z')
    390 		c += 'a'-'A';
    391 	null(c);
    392 }
    393 
    394 void
    395 null(int c)
    396 {
    397 
    398 	*op = c;
    399 	op++;
    400 	if(++obc >= obs) {
    401 		flsh();
    402 		op = obuf;
    403 	}
    404 }
    405 
    406 void
    407 ascii(int cc)
    408 {
    409 	int c;
    410 
    411 	c = etoa[cc];
    412 	if(cbs == 0) {
    413 		cnull(c);
    414 		return;
    415 	}
    416 	if(c == ' ') {
    417 		nspace++;
    418 		goto out;
    419 	}
    420 	while(nspace > 0) {
    421 		null(' ');
    422 		nspace--;
    423 	}
    424 	cnull(c);
    425 
    426 out:
    427 	if(++cbc >= cbs) {
    428 		null('\n');
    429 		cbc = 0;
    430 		nspace = 0;
    431 	}
    432 }
    433 
    434 void
    435 unblock(int cc)
    436 {
    437 	int c;
    438 
    439 	c = cc & 0377;
    440 	if(cbs == 0) {
    441 		cnull(c);
    442 		return;
    443 	}
    444 	if(c == ' ') {
    445 		nspace++;
    446 		goto out;
    447 	}
    448 	while(nspace > 0) {
    449 		null(' ');
    450 		nspace--;
    451 	}
    452 	cnull(c);
    453 
    454 out:
    455 	if(++cbc >= cbs) {
    456 		null('\n');
    457 		cbc = 0;
    458 		nspace = 0;
    459 	}
    460 }
    461 
    462 void
    463 ebcdic(int cc)
    464 {
    465 	int c;
    466 
    467 	c = cc;
    468 	if(cflag&UCASE && c>='a' && c<='z')
    469 		c += 'A'-'a';
    470 	if(cflag&LCASE && c>='A' && c<='Z')
    471 		c += 'a'-'A';
    472 	c = atoe[c];
    473 	if(cbs == 0) {
    474 		null(c);
    475 		return;
    476 	}
    477 	if(cc == '\n') {
    478 		while(cbc < cbs) {
    479 			null(atoe[' ']);
    480 			cbc++;
    481 		}
    482 		cbc = 0;
    483 		return;
    484 	}
    485 	if(cbc == cbs)
    486 		ntrunc++;
    487 	cbc++;
    488 	if(cbc <= cbs)
    489 		null(c);
    490 }
    491 
    492 void
    493 ibm(int cc)
    494 {
    495 	int c;
    496 
    497 	c = cc;
    498 	if(cflag&UCASE && c>='a' && c<='z')
    499 		c += 'A'-'a';
    500 	if(cflag&LCASE && c>='A' && c<='Z')
    501 		c += 'a'-'A';
    502 	c = atoibm[c] & 0377;
    503 	if(cbs == 0) {
    504 		null(c);
    505 		return;
    506 	}
    507 	if(cc == '\n') {
    508 		while(cbc < cbs) {
    509 			null(atoibm[' ']);
    510 			cbc++;
    511 		}
    512 		cbc = 0;
    513 		return;
    514 	}
    515 	if(cbc == cbs)
    516 		ntrunc++;
    517 	cbc++;
    518 	if(cbc <= cbs)
    519 		null(c);
    520 }
    521 
    522 void
    523 block(int cc)
    524 {
    525 	int c;
    526 
    527 	c = cc;
    528 	if(cflag&UCASE && c>='a' && c<='z')
    529 		c += 'A'-'a';
    530 	if(cflag&LCASE && c>='A' && c<='Z')
    531 		c += 'a'-'A';
    532 	c &= 0377;
    533 	if(cbs == 0) {
    534 		null(c);
    535 		return;
    536 	}
    537 	if(cc == '\n') {
    538 		while(cbc < cbs) {
    539 			null(' ');
    540 			cbc++;
    541 		}
    542 		cbc = 0;
    543 		return;
    544 	}
    545 	if(cbc == cbs)
    546 		ntrunc++;
    547 	cbc++;
    548 	if(cbc <= cbs)
    549 		null(c);
    550 }
    551 
    552 void
    553 term(char *status)
    554 {
    555 	stats();
    556 	exits(status);
    557 }
    558 
    559 void
    560 stats(void)
    561 {
    562 	if(quiet)
    563 		return;
    564 	fprint(2, "%lud+%lud records in\n", nifr, nipr);
    565 	fprint(2, "%lud+%lud records out\n", nofr, nopr);
    566 	if(ntrunc)
    567 		fprint(2, "%lud truncated records\n", ntrunc);
    568 }
    569 
    570 uchar	etoa[] =
    571 {
    572 	0000,0001,0002,0003,0234,0011,0206,0177,
    573 	0227,0215,0216,0013,0014,0015,0016,0017,
    574 	0020,0021,0022,0023,0235,0205,0010,0207,
    575 	0030,0031,0222,0217,0034,0035,0036,0037,
    576 	0200,0201,0202,0203,0204,0012,0027,0033,
    577 	0210,0211,0212,0213,0214,0005,0006,0007,
    578 	0220,0221,0026,0223,0224,0225,0226,0004,
    579 	0230,0231,0232,0233,0024,0025,0236,0032,
    580 	0040,0240,0241,0242,0243,0244,0245,0246,
    581 	0247,0250,0133,0056,0074,0050,0053,0041,
    582 	0046,0251,0252,0253,0254,0255,0256,0257,
    583 	0260,0261,0135,0044,0052,0051,0073,0136,
    584 	0055,0057,0262,0263,0264,0265,0266,0267,
    585 	0270,0271,0174,0054,0045,0137,0076,0077,
    586 	0272,0273,0274,0275,0276,0277,0300,0301,
    587 	0302,0140,0072,0043,0100,0047,0075,0042,
    588 	0303,0141,0142,0143,0144,0145,0146,0147,
    589 	0150,0151,0304,0305,0306,0307,0310,0311,
    590 	0312,0152,0153,0154,0155,0156,0157,0160,
    591 	0161,0162,0313,0314,0315,0316,0317,0320,
    592 	0321,0176,0163,0164,0165,0166,0167,0170,
    593 	0171,0172,0322,0323,0324,0325,0326,0327,
    594 	0330,0331,0332,0333,0334,0335,0336,0337,
    595 	0340,0341,0342,0343,0344,0345,0346,0347,
    596 	0173,0101,0102,0103,0104,0105,0106,0107,
    597 	0110,0111,0350,0351,0352,0353,0354,0355,
    598 	0175,0112,0113,0114,0115,0116,0117,0120,
    599 	0121,0122,0356,0357,0360,0361,0362,0363,
    600 	0134,0237,0123,0124,0125,0126,0127,0130,
    601 	0131,0132,0364,0365,0366,0367,0370,0371,
    602 	0060,0061,0062,0063,0064,0065,0066,0067,
    603 	0070,0071,0372,0373,0374,0375,0376,0377,
    604 };
    605 uchar	atoe[] =
    606 {
    607 	0000,0001,0002,0003,0067,0055,0056,0057,
    608 	0026,0005,0045,0013,0014,0015,0016,0017,
    609 	0020,0021,0022,0023,0074,0075,0062,0046,
    610 	0030,0031,0077,0047,0034,0035,0036,0037,
    611 	0100,0117,0177,0173,0133,0154,0120,0175,
    612 	0115,0135,0134,0116,0153,0140,0113,0141,
    613 	0360,0361,0362,0363,0364,0365,0366,0367,
    614 	0370,0371,0172,0136,0114,0176,0156,0157,
    615 	0174,0301,0302,0303,0304,0305,0306,0307,
    616 	0310,0311,0321,0322,0323,0324,0325,0326,
    617 	0327,0330,0331,0342,0343,0344,0345,0346,
    618 	0347,0350,0351,0112,0340,0132,0137,0155,
    619 	0171,0201,0202,0203,0204,0205,0206,0207,
    620 	0210,0211,0221,0222,0223,0224,0225,0226,
    621 	0227,0230,0231,0242,0243,0244,0245,0246,
    622 	0247,0250,0251,0300,0152,0320,0241,0007,
    623 	0040,0041,0042,0043,0044,0025,0006,0027,
    624 	0050,0051,0052,0053,0054,0011,0012,0033,
    625 	0060,0061,0032,0063,0064,0065,0066,0010,
    626 	0070,0071,0072,0073,0004,0024,0076,0341,
    627 	0101,0102,0103,0104,0105,0106,0107,0110,
    628 	0111,0121,0122,0123,0124,0125,0126,0127,
    629 	0130,0131,0142,0143,0144,0145,0146,0147,
    630 	0150,0151,0160,0161,0162,0163,0164,0165,
    631 	0166,0167,0170,0200,0212,0213,0214,0215,
    632 	0216,0217,0220,0232,0233,0234,0235,0236,
    633 	0237,0240,0252,0253,0254,0255,0256,0257,
    634 	0260,0261,0262,0263,0264,0265,0266,0267,
    635 	0270,0271,0272,0273,0274,0275,0276,0277,
    636 	0312,0313,0314,0315,0316,0317,0332,0333,
    637 	0334,0335,0336,0337,0352,0353,0354,0355,
    638 	0356,0357,0372,0373,0374,0375,0376,0377,
    639 };
    640 uchar	atoibm[] =
    641 {
    642 	0000,0001,0002,0003,0067,0055,0056,0057,
    643 	0026,0005,0045,0013,0014,0015,0016,0017,
    644 	0020,0021,0022,0023,0074,0075,0062,0046,
    645 	0030,0031,0077,0047,0034,0035,0036,0037,
    646 	0100,0132,0177,0173,0133,0154,0120,0175,
    647 	0115,0135,0134,0116,0153,0140,0113,0141,
    648 	0360,0361,0362,0363,0364,0365,0366,0367,
    649 	0370,0371,0172,0136,0114,0176,0156,0157,
    650 	0174,0301,0302,0303,0304,0305,0306,0307,
    651 	0310,0311,0321,0322,0323,0324,0325,0326,
    652 	0327,0330,0331,0342,0343,0344,0345,0346,
    653 	0347,0350,0351,0255,0340,0275,0137,0155,
    654 	0171,0201,0202,0203,0204,0205,0206,0207,
    655 	0210,0211,0221,0222,0223,0224,0225,0226,
    656 	0227,0230,0231,0242,0243,0244,0245,0246,
    657 	0247,0250,0251,0300,0117,0320,0241,0007,
    658 	0040,0041,0042,0043,0044,0025,0006,0027,
    659 	0050,0051,0052,0053,0054,0011,0012,0033,
    660 	0060,0061,0032,0063,0064,0065,0066,0010,
    661 	0070,0071,0072,0073,0004,0024,0076,0341,
    662 	0101,0102,0103,0104,0105,0106,0107,0110,
    663 	0111,0121,0122,0123,0124,0125,0126,0127,
    664 	0130,0131,0142,0143,0144,0145,0146,0147,
    665 	0150,0151,0160,0161,0162,0163,0164,0165,
    666 	0166,0167,0170,0200,0212,0213,0214,0215,
    667 	0216,0217,0220,0232,0233,0234,0235,0236,
    668 	0237,0240,0252,0253,0254,0255,0256,0257,
    669 	0260,0261,0262,0263,0264,0265,0266,0267,
    670 	0270,0271,0272,0273,0274,0275,0276,0277,
    671 	0312,0313,0314,0315,0316,0317,0332,0333,
    672 	0334,0335,0336,0337,0352,0353,0354,0355,
    673 	0356,0357,0372,0373,0374,0375,0376,0377,
    674 };