Blob


1 #include <u.h>
2 #include <libc.h>
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)
12 int cflag;
13 int fflag;
15 char *string;
16 char *ifile;
17 char *ofile;
18 char *ibuf;
19 char *obuf;
21 vlong skip;
22 vlong oseekn;
23 vlong iseekn;
24 vlong count;
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;
40 int dotrunc = 1;
41 int ibf;
42 int obf;
44 char *op;
45 int nspace;
47 uchar etoa[256];
48 uchar atoe[256];
49 uchar atoibm[256];
51 int quiet;
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);
66 #define iskey(s) ((key[0] == '-') && (strcmp(key+1, s) == 0))
68 int
69 main(int argc, char *argv[])
70 {
71 void (*conv)(int);
72 char *ip;
73 char *key;
74 int a, c;
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;
104 if(iskey("of")) {
105 ofile = string;
106 continue;
108 if(iskey("trunc")) {
109 dotrunc = number(BIG);
110 continue;
112 if(iskey("quiet")) {
113 quiet = number(BIG);
114 continue;
116 if(iskey("skip")) {
117 skip = number(VBIG);
118 continue;
120 if(iskey("seek") || iskey("oseek")) {
121 oseekn = number(VBIG);
122 continue;
124 if(iskey("iseek")) {
125 iseekn = number(VBIG);
126 continue;
128 if(iskey("count")) {
129 count = number(VBIG);
130 continue;
132 if(iskey("files")) {
133 files = number(BIG);
134 continue;
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;
146 if(match("ibm")) {
147 conv = ibm;
148 goto cloop;
150 if(match("ascii")) {
151 conv = ascii;
152 goto cloop;
154 if(match("block")) {
155 conv = block;
156 goto cloop;
158 if(match("unblock")) {
159 conv = unblock;
160 goto cloop;
162 if(match("lcase")) {
163 cflag |= LCASE;
164 goto cloop;
166 if(match("ucase")) {
167 cflag |= UCASE;
168 goto cloop;
170 if(match("swab")) {
171 cflag |= SWAB;
172 goto cloop;
174 if(match("noerror")) {
175 cflag |= NERR;
176 goto cloop;
178 if(match("sync")) {
179 cflag |= SYNC;
180 goto cloop;
182 fprint(2, "dd: bad conv %s\n", argv[c]);
183 exits("arg");
185 fprint(2, "dd: bad arg: %s\n", key);
186 exits("arg");
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");
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");
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");
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");
222 ibuf = sbrk(ibs);
223 if(fflag)
224 obuf = ibuf;
225 else
226 obuf = sbrk(obs);
227 sbrk(64); /* For good measure */
228 if(ibuf == (char *)-1 || obuf == (char *)-1) {
229 fprint(2, "dd: not enough memory: %r\n");
230 exits("memory");
232 ibc = 0;
233 obc = 0;
234 cbc = 0;
235 op = obuf;
237 /*
238 if(signal(SIGINT, SIG_IGN) != SIG_IGN)
239 signal(SIGINT, term);
240 */
241 seek(obf, obs*oseekn, 1);
242 seek(ibf, ibs*iseekn, 1);
243 while(skip) {
244 read(ibf, ibuf, ibs);
245 skip--;
248 ip = 0;
249 loop:
250 if(ibc-- == 0) {
251 ibc = 0;
252 if(count==0 || nifr+nipr!=count) {
253 if(cflag&(NERR|SYNC))
254 for(ip=ibuf+ibs; ip>ibuf;)
255 *--ip = 0;
256 ibc = read(ibf, ibuf, ibs);
258 if(ibc == -1) {
259 perror("read");
260 if((cflag&NERR) == 0) {
261 flsh();
262 term("errors");
264 ibc = 0;
265 for(c=0; c<ibs; c++)
266 if(ibuf[c] != 0)
267 ibc = c+1;
268 seek(ibf, ibs, 1);
269 stats();
270 }else if(ibc == 0 && --files<=0) {
271 flsh();
272 term(nil);
274 if(ibc != ibs) {
275 nipr++;
276 if(cflag&SYNC)
277 ibc = ibs;
278 } else
279 nifr++;
280 ip = ibuf;
281 c = (ibc>>1) & ~1;
282 if(cflag&SWAB && c)
283 do {
284 a = *ip++;
285 ip[-1] = *ip;
286 *ip++ = a;
287 } while(--c);
288 ip = ibuf;
289 if(fflag) {
290 obc = ibc;
291 flsh();
292 ibc = 0;
294 goto loop;
296 c = 0;
297 c |= *ip++;
298 c &= 0377;
299 (*conv)(c);
300 goto loop;
302 return 0; // shut up apple gcc
305 void
306 flsh(void)
308 int c;
310 if(obc) {
311 /* don't perror dregs of previous errors on a short write */
312 werrstr("");
313 c = write(obf, obuf, obc);
314 if(c != obc) {
315 if(c > 0)
316 ++nopr;
317 perror("write");
318 term("errors");
320 if(obc == obs)
321 nofr++;
322 else
323 nopr++;
324 obc = 0;
328 int
329 match(char *s)
331 char *cs;
333 cs = string;
334 while(*cs++ == *s)
335 if(*s++ == '\0')
336 goto true;
337 if(*s != '\0')
338 return 0;
340 true:
341 cs--;
342 string = cs;
343 return 1;
346 vlong
347 number(vlong big)
349 char *cs;
350 uvlong n;
352 cs = string;
353 n = 0;
354 while(*cs >= '0' && *cs <= '9')
355 n = n*10 + *cs++ - '0';
356 for(;;)
357 switch(*cs++) {
359 case 'k':
360 n *= 1024;
361 continue;
363 case 'b':
364 n *= 512;
365 continue;
367 /* case '*':*/
368 case 'x':
369 string = cs;
370 n *= number(VBIG);
372 case '\0':
373 if(n > big) {
374 fprint(2, "dd: argument %llud out of range\n", n);
375 exits("range");
377 return n;
379 /* never gets here */
382 void
383 cnull(int cc)
385 int c;
387 c = cc;
388 if((cflag&UCASE) && c>='a' && c<='z')
389 c += 'A'-'a';
390 if((cflag&LCASE) && c>='A' && c<='Z')
391 c += 'a'-'A';
392 null(c);
395 void
396 null(int c)
399 *op = c;
400 op++;
401 if(++obc >= obs) {
402 flsh();
403 op = obuf;
407 void
408 ascii(int cc)
410 int c;
412 c = etoa[cc];
413 if(cbs == 0) {
414 cnull(c);
415 return;
417 if(c == ' ') {
418 nspace++;
419 goto out;
421 while(nspace > 0) {
422 null(' ');
423 nspace--;
425 cnull(c);
427 out:
428 if(++cbc >= cbs) {
429 null('\n');
430 cbc = 0;
431 nspace = 0;
435 void
436 unblock(int cc)
438 int c;
440 c = cc & 0377;
441 if(cbs == 0) {
442 cnull(c);
443 return;
445 if(c == ' ') {
446 nspace++;
447 goto out;
449 while(nspace > 0) {
450 null(' ');
451 nspace--;
453 cnull(c);
455 out:
456 if(++cbc >= cbs) {
457 null('\n');
458 cbc = 0;
459 nspace = 0;
463 void
464 ebcdic(int cc)
466 int c;
468 c = cc;
469 if(cflag&UCASE && c>='a' && c<='z')
470 c += 'A'-'a';
471 if(cflag&LCASE && c>='A' && c<='Z')
472 c += 'a'-'A';
473 c = atoe[c];
474 if(cbs == 0) {
475 null(c);
476 return;
478 if(cc == '\n') {
479 while(cbc < cbs) {
480 null(atoe[' ']);
481 cbc++;
483 cbc = 0;
484 return;
486 if(cbc == cbs)
487 ntrunc++;
488 cbc++;
489 if(cbc <= cbs)
490 null(c);
493 void
494 ibm(int cc)
496 int c;
498 c = cc;
499 if(cflag&UCASE && c>='a' && c<='z')
500 c += 'A'-'a';
501 if(cflag&LCASE && c>='A' && c<='Z')
502 c += 'a'-'A';
503 c = atoibm[c] & 0377;
504 if(cbs == 0) {
505 null(c);
506 return;
508 if(cc == '\n') {
509 while(cbc < cbs) {
510 null(atoibm[' ']);
511 cbc++;
513 cbc = 0;
514 return;
516 if(cbc == cbs)
517 ntrunc++;
518 cbc++;
519 if(cbc <= cbs)
520 null(c);
523 void
524 block(int cc)
526 int c;
528 c = cc;
529 if(cflag&UCASE && c>='a' && c<='z')
530 c += 'A'-'a';
531 if(cflag&LCASE && c>='A' && c<='Z')
532 c += 'a'-'A';
533 c &= 0377;
534 if(cbs == 0) {
535 null(c);
536 return;
538 if(cc == '\n') {
539 while(cbc < cbs) {
540 null(' ');
541 cbc++;
543 cbc = 0;
544 return;
546 if(cbc == cbs)
547 ntrunc++;
548 cbc++;
549 if(cbc <= cbs)
550 null(c);
553 void
554 term(char *status)
556 stats();
557 exits(status);
560 void
561 stats(void)
563 if(quiet)
564 return;
565 fprint(2, "%lud+%lud records in\n", nifr, nipr);
566 fprint(2, "%lud+%lud records out\n", nofr, nopr);
567 if(ntrunc)
568 fprint(2, "%lud truncated records\n", ntrunc);
571 uchar etoa[] =
573 0000,0001,0002,0003,0234,0011,0206,0177,
574 0227,0215,0216,0013,0014,0015,0016,0017,
575 0020,0021,0022,0023,0235,0205,0010,0207,
576 0030,0031,0222,0217,0034,0035,0036,0037,
577 0200,0201,0202,0203,0204,0012,0027,0033,
578 0210,0211,0212,0213,0214,0005,0006,0007,
579 0220,0221,0026,0223,0224,0225,0226,0004,
580 0230,0231,0232,0233,0024,0025,0236,0032,
581 0040,0240,0241,0242,0243,0244,0245,0246,
582 0247,0250,0133,0056,0074,0050,0053,0041,
583 0046,0251,0252,0253,0254,0255,0256,0257,
584 0260,0261,0135,0044,0052,0051,0073,0136,
585 0055,0057,0262,0263,0264,0265,0266,0267,
586 0270,0271,0174,0054,0045,0137,0076,0077,
587 0272,0273,0274,0275,0276,0277,0300,0301,
588 0302,0140,0072,0043,0100,0047,0075,0042,
589 0303,0141,0142,0143,0144,0145,0146,0147,
590 0150,0151,0304,0305,0306,0307,0310,0311,
591 0312,0152,0153,0154,0155,0156,0157,0160,
592 0161,0162,0313,0314,0315,0316,0317,0320,
593 0321,0176,0163,0164,0165,0166,0167,0170,
594 0171,0172,0322,0323,0324,0325,0326,0327,
595 0330,0331,0332,0333,0334,0335,0336,0337,
596 0340,0341,0342,0343,0344,0345,0346,0347,
597 0173,0101,0102,0103,0104,0105,0106,0107,
598 0110,0111,0350,0351,0352,0353,0354,0355,
599 0175,0112,0113,0114,0115,0116,0117,0120,
600 0121,0122,0356,0357,0360,0361,0362,0363,
601 0134,0237,0123,0124,0125,0126,0127,0130,
602 0131,0132,0364,0365,0366,0367,0370,0371,
603 0060,0061,0062,0063,0064,0065,0066,0067,
604 0070,0071,0372,0373,0374,0375,0376,0377,
605 };
606 uchar atoe[] =
608 0000,0001,0002,0003,0067,0055,0056,0057,
609 0026,0005,0045,0013,0014,0015,0016,0017,
610 0020,0021,0022,0023,0074,0075,0062,0046,
611 0030,0031,0077,0047,0034,0035,0036,0037,
612 0100,0117,0177,0173,0133,0154,0120,0175,
613 0115,0135,0134,0116,0153,0140,0113,0141,
614 0360,0361,0362,0363,0364,0365,0366,0367,
615 0370,0371,0172,0136,0114,0176,0156,0157,
616 0174,0301,0302,0303,0304,0305,0306,0307,
617 0310,0311,0321,0322,0323,0324,0325,0326,
618 0327,0330,0331,0342,0343,0344,0345,0346,
619 0347,0350,0351,0112,0340,0132,0137,0155,
620 0171,0201,0202,0203,0204,0205,0206,0207,
621 0210,0211,0221,0222,0223,0224,0225,0226,
622 0227,0230,0231,0242,0243,0244,0245,0246,
623 0247,0250,0251,0300,0152,0320,0241,0007,
624 0040,0041,0042,0043,0044,0025,0006,0027,
625 0050,0051,0052,0053,0054,0011,0012,0033,
626 0060,0061,0032,0063,0064,0065,0066,0010,
627 0070,0071,0072,0073,0004,0024,0076,0341,
628 0101,0102,0103,0104,0105,0106,0107,0110,
629 0111,0121,0122,0123,0124,0125,0126,0127,
630 0130,0131,0142,0143,0144,0145,0146,0147,
631 0150,0151,0160,0161,0162,0163,0164,0165,
632 0166,0167,0170,0200,0212,0213,0214,0215,
633 0216,0217,0220,0232,0233,0234,0235,0236,
634 0237,0240,0252,0253,0254,0255,0256,0257,
635 0260,0261,0262,0263,0264,0265,0266,0267,
636 0270,0271,0272,0273,0274,0275,0276,0277,
637 0312,0313,0314,0315,0316,0317,0332,0333,
638 0334,0335,0336,0337,0352,0353,0354,0355,
639 0356,0357,0372,0373,0374,0375,0376,0377,
640 };
641 uchar atoibm[] =
643 0000,0001,0002,0003,0067,0055,0056,0057,
644 0026,0005,0045,0013,0014,0015,0016,0017,
645 0020,0021,0022,0023,0074,0075,0062,0046,
646 0030,0031,0077,0047,0034,0035,0036,0037,
647 0100,0132,0177,0173,0133,0154,0120,0175,
648 0115,0135,0134,0116,0153,0140,0113,0141,
649 0360,0361,0362,0363,0364,0365,0366,0367,
650 0370,0371,0172,0136,0114,0176,0156,0157,
651 0174,0301,0302,0303,0304,0305,0306,0307,
652 0310,0311,0321,0322,0323,0324,0325,0326,
653 0327,0330,0331,0342,0343,0344,0345,0346,
654 0347,0350,0351,0255,0340,0275,0137,0155,
655 0171,0201,0202,0203,0204,0205,0206,0207,
656 0210,0211,0221,0222,0223,0224,0225,0226,
657 0227,0230,0231,0242,0243,0244,0245,0246,
658 0247,0250,0251,0300,0117,0320,0241,0007,
659 0040,0041,0042,0043,0044,0025,0006,0027,
660 0050,0051,0052,0053,0054,0011,0012,0033,
661 0060,0061,0032,0063,0064,0065,0066,0010,
662 0070,0071,0072,0073,0004,0024,0076,0341,
663 0101,0102,0103,0104,0105,0106,0107,0110,
664 0111,0121,0122,0123,0124,0125,0126,0127,
665 0130,0131,0142,0143,0144,0145,0146,0147,
666 0150,0151,0160,0161,0162,0163,0164,0165,
667 0166,0167,0170,0200,0212,0213,0214,0215,
668 0216,0217,0220,0232,0233,0234,0235,0236,
669 0237,0240,0252,0253,0254,0255,0256,0257,
670 0260,0261,0262,0263,0264,0265,0266,0267,
671 0270,0271,0272,0273,0274,0275,0276,0277,
672 0312,0313,0314,0315,0316,0317,0332,0333,
673 0334,0335,0336,0337,0352,0353,0354,0355,
674 0356,0357,0372,0373,0374,0375,0376,0377,
675 };