From 11a3ce57b1bb19192acd653ccee5039159f7727e Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 16 Aug 2011 16:11:39 -0400 Subject: dd: update from Plan 9 R=rsc CC=plan9port.codebot http://codereview.appspot.com/4850052 --- man/man1/dd.1 | 198 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/cmd/dd.c | 69 +++++++++++--------- 2 files changed, 239 insertions(+), 28 deletions(-) create mode 100644 man/man1/dd.1 diff --git a/man/man1/dd.1 b/man/man1/dd.1 new file mode 100644 index 00000000..63b35e14 --- /dev/null +++ b/man/man1/dd.1 @@ -0,0 +1,198 @@ +.TH DD 1 +.SH NAME +dd \- convert and copy a file +.SH SYNOPSIS +.B dd +[ +.I option value +] +\&... +.SH DESCRIPTION +.I Dd\^ +copies the specified input file +to the specified output with +possible conversions. +The standard input and output are used by default. +The input and output block size may be +specified to take advantage of raw physical I/O. +The options are +.TF "quiet\ \ \fIn +.PD +.TP +.BI -if\ f +Open file +.I f +for input. +.TP +.BI -of\ f +Open file +.I f +for output. +.TP +.BI -ibs\ n\^ +Set input block size to +.I n\^ +bytes (default 512). +.TP +.BI -obs\ n\^ +Set output block size (default 512). +.TP +.BI -bs\ n\^ +Set both input and output block size, +superseding +.I ibs\^ +and +.IR obs . +If no conversion is specified, +preserve the input block size instead of packing short blocks +into the output buffer. +This is particularly efficient since no in-core copy need be done. +.TP +.BI -cbs\ n\^ +Set conversion buffer size. +.TP +.BI -skip\ n\^ +Skip +.I n +input records before copying. +.TP +.BI -iseek\ n\^ +Seek +.I n +records forward on input file +before copying. +.TP +.BI -files\ n\^ +Catenate +.I n +input files (useful only for magnetic tape or similar input device). +.TP +.BI -oseek\ n\^ +Seek +.I n\^ +records from beginning of output file before copying. +.TP +.BI -count\ n\^ +Copy only +.I n +input records. +.TP +.BI -trunc\ n\^ +By default, +.I dd +truncates the output file when it opens it; +.B -trunc +.B 0 +opens it without truncation. +.TP +.BI -quiet\ n\^ +By default, +.I dd +prints the number of blocks read and written +once it is finished. +.B -quiet +.B 1 +silences this summary. +.HP +\fL-conv\ ascii\ \ \ \ \fRConvert +.SM EBCDIC +to +.SM ASCII. +.PD0 +.RS "\w'\fLconv\ \fP'u" +.TP "\w'\fLunblock\ \ \fP'u" +.B ebcdic +Convert +.SM ASCII +to +.SM EBCDIC. +.TP +.B ibm +Like +.B ebcdic +but with a slightly different character map. +.TP +.B block +Convert variable length +.SM ASCII +records to fixed length. +.TP +.B unblock +Convert fixed length +.SM ASCII +records to variable length. +.TP +.B lcase +Map alphabetics to lower case. +.TP +.B ucase +Map alphabetics to upper case. +.TP +.B swab +Swap every pair of bytes. +.TP +.B noerror +Do not stop processing on an error. +.TP +.B sync +Pad every input record to +.I ibs\^ +bytes. +.RE +.PD +.PP +.fi +Where sizes are specified, +a number of bytes is expected. +A number may end with +.L k +or +.LR b +to specify multiplication by +1024 or 512 respectively; +a pair of numbers may be separated by +.L x +to indicate a product. +Multiple conversions may be specified in the style: +.LR "-conv ebcdic,ucase" . +.PP +.L Cbs\^ +is used only if +.LR ascii\^ , +.LR unblock\^ , +.LR ebcdic\^ , +.LR ibm\^ , +or +.L block\^ +conversion is specified. +In the first two cases, +.I n +characters are copied into the conversion buffer, any specified +character mapping is done, +trailing blanks are trimmed and new-line is added +before sending the line to the output. +In the latter three cases, characters are read into the +conversion buffer and blanks are added to make up an +output record of size +.IR n . +If +.L cbs\^ +is unspecified or zero, the +.LR ascii\^ , +.LR ebcdic\^ , +and +.L ibm\^ +options convert the character set without changing the block +structure of the input file; the +.L unblock\^ +and +.L block\^ +options become a simple file copy. +.SH SOURCE +.B \*9/src/cmd/dd.c +.SH "SEE ALSO" +.IR cp (1) +.SH DIAGNOSTICS +.I Dd +reports the number of full + partial input and output +blocks handled. diff --git a/src/cmd/dd.c b/src/cmd/dd.c index 15599145..ad433d8e 100644 --- a/src/cmd/dd.c +++ b/src/cmd/dd.c @@ -1,23 +1,28 @@ #include #include -#define BIG 2147483647 +#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; @@ -31,18 +36,23 @@ 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(long big); +vlong number(vlong big); void cnull(int cc); void null(int c); void ascii(int cc); @@ -50,12 +60,12 @@ void unblock(int cc); void ebcdic(int cc); void ibm(int cc); void block(int cc); -void term(void); +void term(char*); void stats(void); #define iskey(s) ((key[0] == '-') && (strcmp(key+1, s) == 0)) -void +int main(int argc, char *argv[]) { void (*conv)(int); @@ -99,20 +109,24 @@ main(int argc, char *argv[]) dotrunc = number(BIG); continue; } + if(iskey("quiet")) { + quiet = number(BIG); + continue; + } if(iskey("skip")) { - skip = number(BIG); + skip = number(VBIG); continue; } if(iskey("seek") || iskey("oseek")) { - oseekn = number(BIG); + oseekn = number(VBIG); continue; } if(iskey("iseek")) { - iseekn = number(BIG); + iseekn = number(VBIG); continue; } if(iskey("count")) { - count = number(BIG); + count = number(VBIG); continue; } if(iskey("files")) { @@ -165,6 +179,8 @@ main(int argc, char *argv[]) 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"); @@ -243,17 +259,17 @@ loop: perror("read"); if((cflag&NERR) == 0) { flsh(); - term(); + term("errors"); } ibc = 0; for(c=0; c 0) ++nopr; perror("write"); - term(); + term("errors"); } if(obc == obs) nofr++; @@ -324,10 +342,10 @@ true: } vlong -number(long big) +number(vlong big) { char *cs; - vlong n; + uvlong n; cs = string; n = 0; @@ -340,11 +358,6 @@ number(long big) n *= 1024; continue; -/* case 'w': - n *= sizeof(int); - continue; -*/ - case 'b': n *= 512; continue; @@ -352,11 +365,11 @@ number(long big) /* case '*':*/ case 'x': string = cs; - n *= number(BIG); + n *= number(VBIG); case '\0': - if(n>=big || n<0) { - fprint(2, "dd: argument %lld out of range\n", n); + if(n > big) { + fprint(2, "dd: argument %llud out of range\n", n); exits("range"); } return n; @@ -536,17 +549,17 @@ block(int cc) } void -term(void) +term(char *status) { - stats(); - exits(0); + 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) -- cgit v1.2.3