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