123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673 |
- #include <u.h>
- #include <libc.h>
- #define BIG ((1UL<<31)-1)
- #define VBIG ((1ULL<<63)-1)
- #define LCASE (1<<0)
- #define UCASE (1<<1)
- #define SWAB (1<<2)
- #define NERR (1<<3)
- #define SYNC (1<<4)
- int cflag;
- int fflag;
- char *string;
- char *ifile;
- char *ofile;
- char *ibuf;
- char *obuf;
- vlong skip;
- vlong oseekn;
- vlong iseekn;
- vlong count;
- long files = 1;
- long ibs = 512;
- long obs = 512;
- long bs;
- long cbs;
- long ibc;
- long obc;
- long cbc;
- long nifr;
- long nipr;
- long nofr;
- long nopr;
- long ntrunc;
- int dotrunc = 1;
- int ibf;
- int obf;
- char *op;
- int nspace;
- uchar etoa[256];
- uchar atoe[256];
- uchar atoibm[256];
- int quiet;
- void flsh(void);
- int match(char *s);
- vlong number(vlong big);
- void cnull(int cc);
- void null(int c);
- void ascii(int cc);
- void unblock(int cc);
- void ebcdic(int cc);
- void ibm(int cc);
- void block(int cc);
- void term(char*);
- void stats(void);
- #define iskey(s) ((key[0] == '-') && (strcmp(key+1, s) == 0))
- int
- main(int argc, char *argv[])
- {
- void (*conv)(int);
- char *ip;
- char *key;
- int a, c;
- conv = null;
- for(c=1; c<argc; c++) {
- key = argv[c++];
- if(c >= argc){
- fprint(2, "dd: arg %s needs a value\n", key);
- exits("arg");
- }
- string = argv[c];
- if(iskey("ibs")) {
- ibs = number(BIG);
- continue;
- }
- if(iskey("obs")) {
- obs = number(BIG);
- continue;
- }
- if(iskey("cbs")) {
- cbs = number(BIG);
- continue;
- }
- if(iskey("bs")) {
- bs = number(BIG);
- continue;
- }
- if(iskey("if")) {
- ifile = string;
- continue;
- }
- if(iskey("of")) {
- ofile = string;
- continue;
- }
- if(iskey("trunc")) {
- dotrunc = number(BIG);
- continue;
- }
- if(iskey("quiet")) {
- quiet = number(BIG);
- continue;
- }
- if(iskey("skip")) {
- skip = number(VBIG);
- continue;
- }
- if(iskey("seek") || iskey("oseek")) {
- oseekn = number(VBIG);
- continue;
- }
- if(iskey("iseek")) {
- iseekn = number(VBIG);
- continue;
- }
- if(iskey("count")) {
- count = number(VBIG);
- continue;
- }
- if(iskey("files")) {
- files = number(BIG);
- continue;
- }
- if(iskey("conv")) {
- cloop:
- if(match(","))
- goto cloop;
- if(*string == '\0')
- continue;
- if(match("ebcdic")) {
- conv = ebcdic;
- goto cloop;
- }
- if(match("ibm")) {
- conv = ibm;
- goto cloop;
- }
- if(match("ascii")) {
- conv = ascii;
- goto cloop;
- }
- if(match("block")) {
- conv = block;
- goto cloop;
- }
- if(match("unblock")) {
- conv = unblock;
- goto cloop;
- }
- if(match("lcase")) {
- cflag |= LCASE;
- goto cloop;
- }
- if(match("ucase")) {
- cflag |= UCASE;
- goto cloop;
- }
- if(match("swab")) {
- cflag |= SWAB;
- goto cloop;
- }
- if(match("noerror")) {
- cflag |= NERR;
- goto cloop;
- }
- if(match("sync")) {
- cflag |= SYNC;
- goto cloop;
- }
- fprint(2, "dd: bad conv %s\n", argv[c]);
- exits("arg");
- }
- fprint(2, "dd: bad arg: %s\n", key);
- exits("arg");
- }
- if(conv == null && cflag&(LCASE|UCASE))
- conv = cnull;
- if(ifile)
- ibf = open(ifile, 0);
- else
- ibf = dup(0, -1);
- if(ibf < 0) {
- fprint(2, "dd: open %s: %r\n", ifile);
- exits("open");
- }
- if(ofile){
- if(dotrunc)
- obf = create(ofile, 1, 0664);
- else
- obf = open(ofile, 1);
- if(obf < 0) {
- fprint(2, "dd: create %s: %r\n", ofile);
- exits("create");
- }
- }else{
- obf = dup(1, -1);
- if(obf < 0) {
- fprint(2, "dd: can't dup file descriptor: %s: %r\n", ofile);
- exits("dup");
- }
- }
- if(bs)
- ibs = obs = bs;
- if(ibs == obs && conv == null)
- fflag++;
- if(ibs == 0 || obs == 0) {
- fprint(2, "dd: counts: cannot be zero\n");
- exits("counts");
- }
- ibuf = sbrk(ibs);
- if(fflag)
- obuf = ibuf;
- else
- obuf = sbrk(obs);
- sbrk(64); /* For good measure */
- if(ibuf == (char *)-1 || obuf == (char *)-1) {
- fprint(2, "dd: not enough memory: %r\n");
- exits("memory");
- }
- ibc = 0;
- obc = 0;
- cbc = 0;
- op = obuf;
- /*
- if(signal(SIGINT, SIG_IGN) != SIG_IGN)
- signal(SIGINT, term);
- */
- seek(obf, obs*oseekn, 1);
- seek(ibf, ibs*iseekn, 1);
- while(skip) {
- read(ibf, ibuf, ibs);
- skip--;
- }
- ip = 0;
- loop:
- if(ibc-- == 0) {
- ibc = 0;
- if(count==0 || nifr+nipr!=count) {
- if(cflag&(NERR|SYNC))
- for(ip=ibuf+ibs; ip>ibuf;)
- *--ip = 0;
- ibc = read(ibf, ibuf, ibs);
- }
- if(ibc == -1) {
- perror("read");
- if((cflag&NERR) == 0) {
- flsh();
- term("errors");
- }
- ibc = 0;
- for(c=0; c<ibs; c++)
- if(ibuf[c] != 0)
- ibc = c+1;
- seek(ibf, ibs, 1);
- stats();
- }else if(ibc == 0 && --files<=0) {
- flsh();
- term(nil);
- }
- if(ibc != ibs) {
- nipr++;
- if(cflag&SYNC)
- ibc = ibs;
- } else
- nifr++;
- ip = ibuf;
- c = (ibc>>1) & ~1;
- if(cflag&SWAB && c)
- do {
- a = *ip++;
- ip[-1] = *ip;
- *ip++ = a;
- } while(--c);
- ip = ibuf;
- if(fflag) {
- obc = ibc;
- flsh();
- ibc = 0;
- }
- goto loop;
- }
- c = 0;
- c |= *ip++;
- c &= 0377;
- (*conv)(c);
- goto loop;
- }
- void
- flsh(void)
- {
- int c;
- if(obc) {
- /* don't perror dregs of previous errors on a short write */
- werrstr("");
- c = write(obf, obuf, obc);
- if(c != obc) {
- if(c > 0)
- ++nopr;
- perror("write");
- term("errors");
- }
- if(obc == obs)
- nofr++;
- else
- nopr++;
- obc = 0;
- }
- }
- int
- match(char *s)
- {
- char *cs;
- cs = string;
- while(*cs++ == *s)
- if(*s++ == '\0')
- goto true;
- if(*s != '\0')
- return 0;
- true:
- cs--;
- string = cs;
- return 1;
- }
- vlong
- number(vlong big)
- {
- char *cs;
- uvlong n;
- cs = string;
- n = 0;
- while(*cs >= '0' && *cs <= '9')
- n = n*10 + *cs++ - '0';
- for(;;)
- switch(*cs++) {
- case 'k':
- n *= 1024;
- continue;
- case 'b':
- n *= 512;
- continue;
- /* case '*':*/
- case 'x':
- string = cs;
- n *= number(VBIG);
- case '\0':
- if(n > big) {
- fprint(2, "dd: argument %llud out of range\n", n);
- exits("range");
- }
- return n;
- }
- /* never gets here */
- }
- void
- cnull(int cc)
- {
- int c;
- c = cc;
- if((cflag&UCASE) && c>='a' && c<='z')
- c += 'A'-'a';
- if((cflag&LCASE) && c>='A' && c<='Z')
- c += 'a'-'A';
- null(c);
- }
- void
- null(int c)
- {
- *op = c;
- op++;
- if(++obc >= obs) {
- flsh();
- op = obuf;
- }
- }
- void
- ascii(int cc)
- {
- int c;
- c = etoa[cc];
- if(cbs == 0) {
- cnull(c);
- return;
- }
- if(c == ' ') {
- nspace++;
- goto out;
- }
- while(nspace > 0) {
- null(' ');
- nspace--;
- }
- cnull(c);
- out:
- if(++cbc >= cbs) {
- null('\n');
- cbc = 0;
- nspace = 0;
- }
- }
- void
- unblock(int cc)
- {
- int c;
- c = cc & 0377;
- if(cbs == 0) {
- cnull(c);
- return;
- }
- if(c == ' ') {
- nspace++;
- goto out;
- }
- while(nspace > 0) {
- null(' ');
- nspace--;
- }
- cnull(c);
- out:
- if(++cbc >= cbs) {
- null('\n');
- cbc = 0;
- nspace = 0;
- }
- }
- void
- ebcdic(int cc)
- {
- int c;
- c = cc;
- if(cflag&UCASE && c>='a' && c<='z')
- c += 'A'-'a';
- if(cflag&LCASE && c>='A' && c<='Z')
- c += 'a'-'A';
- c = atoe[c];
- if(cbs == 0) {
- null(c);
- return;
- }
- if(cc == '\n') {
- while(cbc < cbs) {
- null(atoe[' ']);
- cbc++;
- }
- cbc = 0;
- return;
- }
- if(cbc == cbs)
- ntrunc++;
- cbc++;
- if(cbc <= cbs)
- null(c);
- }
- void
- ibm(int cc)
- {
- int c;
- c = cc;
- if(cflag&UCASE && c>='a' && c<='z')
- c += 'A'-'a';
- if(cflag&LCASE && c>='A' && c<='Z')
- c += 'a'-'A';
- c = atoibm[c] & 0377;
- if(cbs == 0) {
- null(c);
- return;
- }
- if(cc == '\n') {
- while(cbc < cbs) {
- null(atoibm[' ']);
- cbc++;
- }
- cbc = 0;
- return;
- }
- if(cbc == cbs)
- ntrunc++;
- cbc++;
- if(cbc <= cbs)
- null(c);
- }
- void
- block(int cc)
- {
- int c;
- c = cc;
- if(cflag&UCASE && c>='a' && c<='z')
- c += 'A'-'a';
- if(cflag&LCASE && c>='A' && c<='Z')
- c += 'a'-'A';
- c &= 0377;
- if(cbs == 0) {
- null(c);
- return;
- }
- if(cc == '\n') {
- while(cbc < cbs) {
- null(' ');
- cbc++;
- }
- cbc = 0;
- return;
- }
- if(cbc == cbs)
- ntrunc++;
- cbc++;
- if(cbc <= cbs)
- null(c);
- }
- void
- term(char *status)
- {
- stats();
- exits(status);
- }
- void
- stats(void)
- {
- if(quiet)
- return;
- fprint(2, "%lud+%lud records in\n", nifr, nipr);
- fprint(2, "%lud+%lud records out\n", nofr, nopr);
- if(ntrunc)
- fprint(2, "%lud truncated records\n", ntrunc);
- }
- uchar etoa[] =
- {
- 0000,0001,0002,0003,0234,0011,0206,0177,
- 0227,0215,0216,0013,0014,0015,0016,0017,
- 0020,0021,0022,0023,0235,0205,0010,0207,
- 0030,0031,0222,0217,0034,0035,0036,0037,
- 0200,0201,0202,0203,0204,0012,0027,0033,
- 0210,0211,0212,0213,0214,0005,0006,0007,
- 0220,0221,0026,0223,0224,0225,0226,0004,
- 0230,0231,0232,0233,0024,0025,0236,0032,
- 0040,0240,0241,0242,0243,0244,0245,0246,
- 0247,0250,0133,0056,0074,0050,0053,0041,
- 0046,0251,0252,0253,0254,0255,0256,0257,
- 0260,0261,0135,0044,0052,0051,0073,0136,
- 0055,0057,0262,0263,0264,0265,0266,0267,
- 0270,0271,0174,0054,0045,0137,0076,0077,
- 0272,0273,0274,0275,0276,0277,0300,0301,
- 0302,0140,0072,0043,0100,0047,0075,0042,
- 0303,0141,0142,0143,0144,0145,0146,0147,
- 0150,0151,0304,0305,0306,0307,0310,0311,
- 0312,0152,0153,0154,0155,0156,0157,0160,
- 0161,0162,0313,0314,0315,0316,0317,0320,
- 0321,0176,0163,0164,0165,0166,0167,0170,
- 0171,0172,0322,0323,0324,0325,0326,0327,
- 0330,0331,0332,0333,0334,0335,0336,0337,
- 0340,0341,0342,0343,0344,0345,0346,0347,
- 0173,0101,0102,0103,0104,0105,0106,0107,
- 0110,0111,0350,0351,0352,0353,0354,0355,
- 0175,0112,0113,0114,0115,0116,0117,0120,
- 0121,0122,0356,0357,0360,0361,0362,0363,
- 0134,0237,0123,0124,0125,0126,0127,0130,
- 0131,0132,0364,0365,0366,0367,0370,0371,
- 0060,0061,0062,0063,0064,0065,0066,0067,
- 0070,0071,0372,0373,0374,0375,0376,0377,
- };
- uchar atoe[] =
- {
- 0000,0001,0002,0003,0067,0055,0056,0057,
- 0026,0005,0045,0013,0014,0015,0016,0017,
- 0020,0021,0022,0023,0074,0075,0062,0046,
- 0030,0031,0077,0047,0034,0035,0036,0037,
- 0100,0117,0177,0173,0133,0154,0120,0175,
- 0115,0135,0134,0116,0153,0140,0113,0141,
- 0360,0361,0362,0363,0364,0365,0366,0367,
- 0370,0371,0172,0136,0114,0176,0156,0157,
- 0174,0301,0302,0303,0304,0305,0306,0307,
- 0310,0311,0321,0322,0323,0324,0325,0326,
- 0327,0330,0331,0342,0343,0344,0345,0346,
- 0347,0350,0351,0112,0340,0132,0137,0155,
- 0171,0201,0202,0203,0204,0205,0206,0207,
- 0210,0211,0221,0222,0223,0224,0225,0226,
- 0227,0230,0231,0242,0243,0244,0245,0246,
- 0247,0250,0251,0300,0152,0320,0241,0007,
- 0040,0041,0042,0043,0044,0025,0006,0027,
- 0050,0051,0052,0053,0054,0011,0012,0033,
- 0060,0061,0032,0063,0064,0065,0066,0010,
- 0070,0071,0072,0073,0004,0024,0076,0341,
- 0101,0102,0103,0104,0105,0106,0107,0110,
- 0111,0121,0122,0123,0124,0125,0126,0127,
- 0130,0131,0142,0143,0144,0145,0146,0147,
- 0150,0151,0160,0161,0162,0163,0164,0165,
- 0166,0167,0170,0200,0212,0213,0214,0215,
- 0216,0217,0220,0232,0233,0234,0235,0236,
- 0237,0240,0252,0253,0254,0255,0256,0257,
- 0260,0261,0262,0263,0264,0265,0266,0267,
- 0270,0271,0272,0273,0274,0275,0276,0277,
- 0312,0313,0314,0315,0316,0317,0332,0333,
- 0334,0335,0336,0337,0352,0353,0354,0355,
- 0356,0357,0372,0373,0374,0375,0376,0377,
- };
- uchar atoibm[] =
- {
- 0000,0001,0002,0003,0067,0055,0056,0057,
- 0026,0005,0045,0013,0014,0015,0016,0017,
- 0020,0021,0022,0023,0074,0075,0062,0046,
- 0030,0031,0077,0047,0034,0035,0036,0037,
- 0100,0132,0177,0173,0133,0154,0120,0175,
- 0115,0135,0134,0116,0153,0140,0113,0141,
- 0360,0361,0362,0363,0364,0365,0366,0367,
- 0370,0371,0172,0136,0114,0176,0156,0157,
- 0174,0301,0302,0303,0304,0305,0306,0307,
- 0310,0311,0321,0322,0323,0324,0325,0326,
- 0327,0330,0331,0342,0343,0344,0345,0346,
- 0347,0350,0351,0255,0340,0275,0137,0155,
- 0171,0201,0202,0203,0204,0205,0206,0207,
- 0210,0211,0221,0222,0223,0224,0225,0226,
- 0227,0230,0231,0242,0243,0244,0245,0246,
- 0247,0250,0251,0300,0117,0320,0241,0007,
- 0040,0041,0042,0043,0044,0025,0006,0027,
- 0050,0051,0052,0053,0054,0011,0012,0033,
- 0060,0061,0032,0063,0064,0065,0066,0010,
- 0070,0071,0072,0073,0004,0024,0076,0341,
- 0101,0102,0103,0104,0105,0106,0107,0110,
- 0111,0121,0122,0123,0124,0125,0126,0127,
- 0130,0131,0142,0143,0144,0145,0146,0147,
- 0150,0151,0160,0161,0162,0163,0164,0165,
- 0166,0167,0170,0200,0212,0213,0214,0215,
- 0216,0217,0220,0232,0233,0234,0235,0236,
- 0237,0240,0252,0253,0254,0255,0256,0257,
- 0260,0261,0262,0263,0264,0265,0266,0267,
- 0270,0271,0272,0273,0274,0275,0276,0277,
- 0312,0313,0314,0315,0316,0317,0332,0333,
- 0334,0335,0336,0337,0352,0353,0354,0355,
- 0356,0357,0372,0373,0374,0375,0376,0377,
- };
|