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