Blob


1 #include <u.h>
2 #include <libc.h>
4 #define BIG 2147483647
5 #define LCASE (1<<0)
6 #define UCASE (1<<1)
7 #define SWAB (1<<2)
8 #define NERR (1<<3)
9 #define SYNC (1<<4)
10 int cflag;
11 int fflag;
12 char *string;
13 char *ifile;
14 char *ofile;
15 char *ibuf;
16 char *obuf;
17 vlong skip;
18 vlong oseekn;
19 vlong iseekn;
20 vlong count;
21 long files = 1;
22 long ibs = 512;
23 long obs = 512;
24 long bs;
25 long cbs;
26 long ibc;
27 long obc;
28 long cbc;
29 long nifr;
30 long nipr;
31 long nofr;
32 long nopr;
33 long ntrunc;
34 int dotrunc = 1;
35 int ibf;
36 int obf;
37 char *op;
38 int nspace;
39 uchar etoa[256];
40 uchar atoe[256];
41 uchar atoibm[256];
43 void flsh(void);
44 int match(char *s);
45 vlong number(long big);
46 void cnull(int cc);
47 void null(int c);
48 void ascii(int cc);
49 void unblock(int cc);
50 void ebcdic(int cc);
51 void ibm(int cc);
52 void block(int cc);
53 void term(void);
54 void stats(void);
56 #define iskey(s) ((key[0] == '-') && (strcmp(key+1, s) == 0))
58 void
59 main(int argc, char *argv[])
60 {
61 void (*conv)(int);
62 char *ip;
63 char *key;
64 int a, c;
66 conv = null;
67 for(c=1; c<argc; c++) {
68 key = argv[c++];
69 if(c >= argc){
70 fprint(2, "dd: arg %s needs a value\n", key);
71 exits("arg");
72 }
73 string = argv[c];
74 if(iskey("ibs")) {
75 ibs = number(BIG);
76 continue;
77 }
78 if(iskey("obs")) {
79 obs = number(BIG);
80 continue;
81 }
82 if(iskey("cbs")) {
83 cbs = number(BIG);
84 continue;
85 }
86 if(iskey("bs")) {
87 bs = number(BIG);
88 continue;
89 }
90 if(iskey("if")) {
91 ifile = string;
92 continue;
93 }
94 if(iskey("of")) {
95 ofile = string;
96 continue;
97 }
98 if(iskey("trunc")) {
99 dotrunc = number(BIG);
100 continue;
102 if(iskey("skip")) {
103 skip = number(BIG);
104 continue;
106 if(iskey("seek") || iskey("oseek")) {
107 oseekn = number(BIG);
108 continue;
110 if(iskey("iseek")) {
111 iseekn = number(BIG);
112 continue;
114 if(iskey("count")) {
115 count = number(BIG);
116 continue;
118 if(iskey("files")) {
119 files = number(BIG);
120 continue;
122 if(iskey("conv")) {
123 cloop:
124 if(match(","))
125 goto cloop;
126 if(*string == '\0')
127 continue;
128 if(match("ebcdic")) {
129 conv = ebcdic;
130 goto cloop;
132 if(match("ibm")) {
133 conv = ibm;
134 goto cloop;
136 if(match("ascii")) {
137 conv = ascii;
138 goto cloop;
140 if(match("block")) {
141 conv = block;
142 goto cloop;
144 if(match("unblock")) {
145 conv = unblock;
146 goto cloop;
148 if(match("lcase")) {
149 cflag |= LCASE;
150 goto cloop;
152 if(match("ucase")) {
153 cflag |= UCASE;
154 goto cloop;
156 if(match("swab")) {
157 cflag |= SWAB;
158 goto cloop;
160 if(match("noerror")) {
161 cflag |= NERR;
162 goto cloop;
164 if(match("sync")) {
165 cflag |= SYNC;
166 goto cloop;
169 fprint(2, "dd: bad arg: %s\n", key);
170 exits("arg");
172 if(conv == null && cflag&(LCASE|UCASE))
173 conv = cnull;
174 if(ifile)
175 ibf = open(ifile, 0);
176 else
177 ibf = dup(0, -1);
178 if(ibf < 0) {
179 fprint(2, "dd: open %s: %r\n", ifile);
180 exits("open");
182 if(ofile){
183 if(dotrunc)
184 obf = create(ofile, 1, 0664);
185 else
186 obf = open(ofile, 1);
187 if(obf < 0) {
188 fprint(2, "dd: create %s: %r\n", ofile);
189 exits("create");
191 }else{
192 obf = dup(1, -1);
193 if(obf < 0) {
194 fprint(2, "dd: can't dup file descriptor: %s: %r\n", ofile);
195 exits("dup");
198 if(bs)
199 ibs = obs = bs;
200 if(ibs == obs && conv == null)
201 fflag++;
202 if(ibs == 0 || obs == 0) {
203 fprint(2, "dd: counts: cannot be zero\n");
204 exits("counts");
206 ibuf = sbrk(ibs);
207 if(fflag)
208 obuf = ibuf;
209 else
210 obuf = sbrk(obs);
211 sbrk(64); /* For good measure */
212 if(ibuf == (char *)-1 || obuf == (char *)-1) {
213 fprint(2, "dd: not enough memory: %r\n");
214 exits("memory");
216 ibc = 0;
217 obc = 0;
218 cbc = 0;
219 op = obuf;
221 /*
222 if(signal(SIGINT, SIG_IGN) != SIG_IGN)
223 signal(SIGINT, term);
224 */
225 seek(obf, obs*oseekn, 1);
226 seek(ibf, ibs*iseekn, 1);
227 while(skip) {
228 read(ibf, ibuf, ibs);
229 skip--;
232 ip = 0;
233 loop:
234 if(ibc-- == 0) {
235 ibc = 0;
236 if(count==0 || nifr+nipr!=count) {
237 if(cflag&(NERR|SYNC))
238 for(ip=ibuf+ibs; ip>ibuf;)
239 *--ip = 0;
240 ibc = read(ibf, ibuf, ibs);
242 if(ibc == -1) {
243 perror("read");
244 if((cflag&NERR) == 0) {
245 flsh();
246 term();
248 ibc = 0;
249 for(c=0; c<ibs; c++)
250 if(ibuf[c] != 0)
251 ibc = c;
252 stats();
254 if(ibc == 0 && --files<=0) {
255 flsh();
256 term();
258 if(ibc != ibs) {
259 nipr++;
260 if(cflag&SYNC)
261 ibc = ibs;
262 } else
263 nifr++;
264 ip = ibuf;
265 c = (ibc>>1) & ~1;
266 if(cflag&SWAB && c)
267 do {
268 a = *ip++;
269 ip[-1] = *ip;
270 *ip++ = a;
271 } while(--c);
272 ip = ibuf;
273 if(fflag) {
274 obc = ibc;
275 flsh();
276 ibc = 0;
278 goto loop;
280 c = 0;
281 c |= *ip++;
282 c &= 0377;
283 (*conv)(c);
284 goto loop;
287 void
288 flsh(void)
290 int c;
292 if(obc) {
293 c = write(obf, obuf, obc);
294 if(c != obc) {
295 if(c > 0)
296 ++nopr;
297 perror("write");
298 term();
300 if(obc == obs)
301 nofr++;
302 else
303 nopr++;
304 obc = 0;
308 int
309 match(char *s)
311 char *cs;
313 cs = string;
314 while(*cs++ == *s)
315 if(*s++ == '\0')
316 goto true;
317 if(*s != '\0')
318 return 0;
320 true:
321 cs--;
322 string = cs;
323 return 1;
326 vlong
327 number(long big)
329 char *cs;
330 vlong n;
332 cs = string;
333 n = 0;
334 while(*cs >= '0' && *cs <= '9')
335 n = n*10 + *cs++ - '0';
336 for(;;)
337 switch(*cs++) {
339 case 'k':
340 n *= 1024;
341 continue;
343 /* case 'w':
344 n *= sizeof(int);
345 continue;
346 */
348 case 'b':
349 n *= 512;
350 continue;
352 /* case '*':*/
353 case 'x':
354 string = cs;
355 n *= number(BIG);
357 case '\0':
358 if(n>=big || n<0) {
359 fprint(2, "dd: argument %lld out of range\n", n);
360 exits("range");
362 return n;
364 /* never gets here */
367 void
368 cnull(int cc)
370 int c;
372 c = cc;
373 if((cflag&UCASE) && c>='a' && c<='z')
374 c += 'A'-'a';
375 if((cflag&LCASE) && c>='A' && c<='Z')
376 c += 'a'-'A';
377 null(c);
380 void
381 null(int c)
384 *op = c;
385 op++;
386 if(++obc >= obs) {
387 flsh();
388 op = obuf;
392 void
393 ascii(int cc)
395 int c;
397 c = etoa[cc];
398 if(cbs == 0) {
399 cnull(c);
400 return;
402 if(c == ' ') {
403 nspace++;
404 goto out;
406 while(nspace > 0) {
407 null(' ');
408 nspace--;
410 cnull(c);
412 out:
413 if(++cbc >= cbs) {
414 null('\n');
415 cbc = 0;
416 nspace = 0;
420 void
421 unblock(int cc)
423 int c;
425 c = cc & 0377;
426 if(cbs == 0) {
427 cnull(c);
428 return;
430 if(c == ' ') {
431 nspace++;
432 goto out;
434 while(nspace > 0) {
435 null(' ');
436 nspace--;
438 cnull(c);
440 out:
441 if(++cbc >= cbs) {
442 null('\n');
443 cbc = 0;
444 nspace = 0;
448 void
449 ebcdic(int cc)
451 int c;
453 c = cc;
454 if(cflag&UCASE && c>='a' && c<='z')
455 c += 'A'-'a';
456 if(cflag&LCASE && c>='A' && c<='Z')
457 c += 'a'-'A';
458 c = atoe[c];
459 if(cbs == 0) {
460 null(c);
461 return;
463 if(cc == '\n') {
464 while(cbc < cbs) {
465 null(atoe[' ']);
466 cbc++;
468 cbc = 0;
469 return;
471 if(cbc == cbs)
472 ntrunc++;
473 cbc++;
474 if(cbc <= cbs)
475 null(c);
478 void
479 ibm(int cc)
481 int c;
483 c = cc;
484 if(cflag&UCASE && c>='a' && c<='z')
485 c += 'A'-'a';
486 if(cflag&LCASE && c>='A' && c<='Z')
487 c += 'a'-'A';
488 c = atoibm[c] & 0377;
489 if(cbs == 0) {
490 null(c);
491 return;
493 if(cc == '\n') {
494 while(cbc < cbs) {
495 null(atoibm[' ']);
496 cbc++;
498 cbc = 0;
499 return;
501 if(cbc == cbs)
502 ntrunc++;
503 cbc++;
504 if(cbc <= cbs)
505 null(c);
508 void
509 block(int cc)
511 int c;
513 c = cc;
514 if(cflag&UCASE && c>='a' && c<='z')
515 c += 'A'-'a';
516 if(cflag&LCASE && c>='A' && c<='Z')
517 c += 'a'-'A';
518 c &= 0377;
519 if(cbs == 0) {
520 null(c);
521 return;
523 if(cc == '\n') {
524 while(cbc < cbs) {
525 null(' ');
526 cbc++;
528 cbc = 0;
529 return;
531 if(cbc == cbs)
532 ntrunc++;
533 cbc++;
534 if(cbc <= cbs)
535 null(c);
538 void
539 term(void)
542 stats();
543 exits(0);
546 void
547 stats(void)
550 fprint(2, "%lud+%lud records in\n", nifr, nipr);
551 fprint(2, "%lud+%lud records out\n", nofr, nopr);
552 if(ntrunc)
553 fprint(2, "%lud truncated records\n", ntrunc);
556 uchar etoa[] =
558 0000,0001,0002,0003,0234,0011,0206,0177,
559 0227,0215,0216,0013,0014,0015,0016,0017,
560 0020,0021,0022,0023,0235,0205,0010,0207,
561 0030,0031,0222,0217,0034,0035,0036,0037,
562 0200,0201,0202,0203,0204,0012,0027,0033,
563 0210,0211,0212,0213,0214,0005,0006,0007,
564 0220,0221,0026,0223,0224,0225,0226,0004,
565 0230,0231,0232,0233,0024,0025,0236,0032,
566 0040,0240,0241,0242,0243,0244,0245,0246,
567 0247,0250,0133,0056,0074,0050,0053,0041,
568 0046,0251,0252,0253,0254,0255,0256,0257,
569 0260,0261,0135,0044,0052,0051,0073,0136,
570 0055,0057,0262,0263,0264,0265,0266,0267,
571 0270,0271,0174,0054,0045,0137,0076,0077,
572 0272,0273,0274,0275,0276,0277,0300,0301,
573 0302,0140,0072,0043,0100,0047,0075,0042,
574 0303,0141,0142,0143,0144,0145,0146,0147,
575 0150,0151,0304,0305,0306,0307,0310,0311,
576 0312,0152,0153,0154,0155,0156,0157,0160,
577 0161,0162,0313,0314,0315,0316,0317,0320,
578 0321,0176,0163,0164,0165,0166,0167,0170,
579 0171,0172,0322,0323,0324,0325,0326,0327,
580 0330,0331,0332,0333,0334,0335,0336,0337,
581 0340,0341,0342,0343,0344,0345,0346,0347,
582 0173,0101,0102,0103,0104,0105,0106,0107,
583 0110,0111,0350,0351,0352,0353,0354,0355,
584 0175,0112,0113,0114,0115,0116,0117,0120,
585 0121,0122,0356,0357,0360,0361,0362,0363,
586 0134,0237,0123,0124,0125,0126,0127,0130,
587 0131,0132,0364,0365,0366,0367,0370,0371,
588 0060,0061,0062,0063,0064,0065,0066,0067,
589 0070,0071,0372,0373,0374,0375,0376,0377,
590 };
591 uchar atoe[] =
593 0000,0001,0002,0003,0067,0055,0056,0057,
594 0026,0005,0045,0013,0014,0015,0016,0017,
595 0020,0021,0022,0023,0074,0075,0062,0046,
596 0030,0031,0077,0047,0034,0035,0036,0037,
597 0100,0117,0177,0173,0133,0154,0120,0175,
598 0115,0135,0134,0116,0153,0140,0113,0141,
599 0360,0361,0362,0363,0364,0365,0366,0367,
600 0370,0371,0172,0136,0114,0176,0156,0157,
601 0174,0301,0302,0303,0304,0305,0306,0307,
602 0310,0311,0321,0322,0323,0324,0325,0326,
603 0327,0330,0331,0342,0343,0344,0345,0346,
604 0347,0350,0351,0112,0340,0132,0137,0155,
605 0171,0201,0202,0203,0204,0205,0206,0207,
606 0210,0211,0221,0222,0223,0224,0225,0226,
607 0227,0230,0231,0242,0243,0244,0245,0246,
608 0247,0250,0251,0300,0152,0320,0241,0007,
609 0040,0041,0042,0043,0044,0025,0006,0027,
610 0050,0051,0052,0053,0054,0011,0012,0033,
611 0060,0061,0032,0063,0064,0065,0066,0010,
612 0070,0071,0072,0073,0004,0024,0076,0341,
613 0101,0102,0103,0104,0105,0106,0107,0110,
614 0111,0121,0122,0123,0124,0125,0126,0127,
615 0130,0131,0142,0143,0144,0145,0146,0147,
616 0150,0151,0160,0161,0162,0163,0164,0165,
617 0166,0167,0170,0200,0212,0213,0214,0215,
618 0216,0217,0220,0232,0233,0234,0235,0236,
619 0237,0240,0252,0253,0254,0255,0256,0257,
620 0260,0261,0262,0263,0264,0265,0266,0267,
621 0270,0271,0272,0273,0274,0275,0276,0277,
622 0312,0313,0314,0315,0316,0317,0332,0333,
623 0334,0335,0336,0337,0352,0353,0354,0355,
624 0356,0357,0372,0373,0374,0375,0376,0377,
625 };
626 uchar atoibm[] =
628 0000,0001,0002,0003,0067,0055,0056,0057,
629 0026,0005,0045,0013,0014,0015,0016,0017,
630 0020,0021,0022,0023,0074,0075,0062,0046,
631 0030,0031,0077,0047,0034,0035,0036,0037,
632 0100,0132,0177,0173,0133,0154,0120,0175,
633 0115,0135,0134,0116,0153,0140,0113,0141,
634 0360,0361,0362,0363,0364,0365,0366,0367,
635 0370,0371,0172,0136,0114,0176,0156,0157,
636 0174,0301,0302,0303,0304,0305,0306,0307,
637 0310,0311,0321,0322,0323,0324,0325,0326,
638 0327,0330,0331,0342,0343,0344,0345,0346,
639 0347,0350,0351,0255,0340,0275,0137,0155,
640 0171,0201,0202,0203,0204,0205,0206,0207,
641 0210,0211,0221,0222,0223,0224,0225,0226,
642 0227,0230,0231,0242,0243,0244,0245,0246,
643 0247,0250,0251,0300,0117,0320,0241,0007,
644 0040,0041,0042,0043,0044,0025,0006,0027,
645 0050,0051,0052,0053,0054,0011,0012,0033,
646 0060,0061,0032,0063,0064,0065,0066,0010,
647 0070,0071,0072,0073,0004,0024,0076,0341,
648 0101,0102,0103,0104,0105,0106,0107,0110,
649 0111,0121,0122,0123,0124,0125,0126,0127,
650 0130,0131,0142,0143,0144,0145,0146,0147,
651 0150,0151,0160,0161,0162,0163,0164,0165,
652 0166,0167,0170,0200,0212,0213,0214,0215,
653 0216,0217,0220,0232,0233,0234,0235,0236,
654 0237,0240,0252,0253,0254,0255,0256,0257,
655 0260,0261,0262,0263,0264,0265,0266,0267,
656 0270,0271,0272,0273,0274,0275,0276,0277,
657 0312,0313,0314,0315,0316,0317,0332,0333,
658 0334,0335,0336,0337,0352,0353,0354,0355,
659 0356,0357,0372,0373,0374,0375,0376,0377,
660 };