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 = 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");
231 ibc = 0;
232 obc = 0;
233 cbc = 0;
234 op = obuf;
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--;
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);
257 if(ibc == -1) {
258 perror("read");
259 if((cflag&NERR) == 0) {
260 flsh();
261 term("errors");
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);
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;
293 goto loop;
295 c = 0;
296 c |= *ip++;
297 c &= 0377;
298 (*conv)(c);
299 goto loop;
301 return 0; // shut up apple gcc
304 void
305 flsh(void)
307 int c;
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");
319 if(obc == obs)
320 nofr++;
321 else
322 nopr++;
323 obc = 0;
327 int
328 match(char *s)
330 char *cs;
332 cs = string;
333 while(*cs++ == *s)
334 if(*s++ == '\0')
335 goto true;
336 if(*s != '\0')
337 return 0;
339 true:
340 cs--;
341 string = cs;
342 return 1;
345 vlong
346 number(vlong big)
348 char *cs;
349 uvlong n;
351 cs = string;
352 n = 0;
353 while(*cs >= '0' && *cs <= '9')
354 n = n*10 + *cs++ - '0';
355 for(;;)
356 switch(*cs++) {
358 case 'k':
359 n *= 1024;
360 continue;
362 case 'b':
363 n *= 512;
364 continue;
366 /* case '*':*/
367 case 'x':
368 string = cs;
369 n *= number(VBIG);
371 case '\0':
372 if(n > big) {
373 fprint(2, "dd: argument %llud out of range\n", n);
374 exits("range");
376 return n;
378 /* never gets here */
381 void
382 cnull(int cc)
384 int c;
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);
394 void
395 null(int c)
398 *op = c;
399 op++;
400 if(++obc >= obs) {
401 flsh();
402 op = obuf;
406 void
407 ascii(int cc)
409 int c;
411 c = etoa[cc];
412 if(cbs == 0) {
413 cnull(c);
414 return;
416 if(c == ' ') {
417 nspace++;
418 goto out;
420 while(nspace > 0) {
421 null(' ');
422 nspace--;
424 cnull(c);
426 out:
427 if(++cbc >= cbs) {
428 null('\n');
429 cbc = 0;
430 nspace = 0;
434 void
435 unblock(int cc)
437 int c;
439 c = cc & 0377;
440 if(cbs == 0) {
441 cnull(c);
442 return;
444 if(c == ' ') {
445 nspace++;
446 goto out;
448 while(nspace > 0) {
449 null(' ');
450 nspace--;
452 cnull(c);
454 out:
455 if(++cbc >= cbs) {
456 null('\n');
457 cbc = 0;
458 nspace = 0;
462 void
463 ebcdic(int cc)
465 int c;
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;
477 if(cc == '\n') {
478 while(cbc < cbs) {
479 null(atoe[' ']);
480 cbc++;
482 cbc = 0;
483 return;
485 if(cbc == cbs)
486 ntrunc++;
487 cbc++;
488 if(cbc <= cbs)
489 null(c);
492 void
493 ibm(int cc)
495 int c;
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;
507 if(cc == '\n') {
508 while(cbc < cbs) {
509 null(atoibm[' ']);
510 cbc++;
512 cbc = 0;
513 return;
515 if(cbc == cbs)
516 ntrunc++;
517 cbc++;
518 if(cbc <= cbs)
519 null(c);
522 void
523 block(int cc)
525 int c;
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;
537 if(cc == '\n') {
538 while(cbc < cbs) {
539 null(' ');
540 cbc++;
542 cbc = 0;
543 return;
545 if(cbc == cbs)
546 ntrunc++;
547 cbc++;
548 if(cbc <= cbs)
549 null(c);
552 void
553 term(char *status)
555 stats();
556 exits(status);
559 void
560 stats(void)
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);
570 uchar etoa[] =
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[] =
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[] =
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 };