dd: update from Plan 9

R=rsc
CC=plan9port.codebot
http://codereview.appspot.com/4850052
This commit is contained in:
David du Colombier 2011-08-16 16:11:39 -04:00 committed by Russ Cox
parent dcdc3af143
commit 11a3ce57b1
2 changed files with 239 additions and 28 deletions

198
man/man1/dd.1 Normal file
View file

@ -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.

View file

@ -1,23 +1,28 @@
#include <u.h>
#include <libc.h>
#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<ibs; c++)
if(ibuf[c] != 0)
ibc = c;
ibc = c+1;
seek(ibf, ibs, 1);
stats();
}
if(ibc == 0 && --files<=0) {
}else if(ibc == 0 && --files<=0) {
flsh();
term();
term(nil);
}
if(ibc != ibs) {
nipr++;
@ -290,12 +306,14 @@ 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();
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)