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