dd: update from Plan 9
R=rsc CC=plan9port.codebot http://codereview.appspot.com/4850052
This commit is contained in:
parent
dcdc3af143
commit
11a3ce57b1
2 changed files with 239 additions and 28 deletions
198
man/man1/dd.1
Normal file
198
man/man1/dd.1
Normal 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.
|
||||||
69
src/cmd/dd.c
69
src/cmd/dd.c
|
|
@ -1,23 +1,28 @@
|
||||||
#include <u.h>
|
#include <u.h>
|
||||||
#include <libc.h>
|
#include <libc.h>
|
||||||
|
|
||||||
#define BIG 2147483647
|
#define BIG ((1UL<<31)-1)
|
||||||
|
#define VBIG ((1ULL<<63)-1)
|
||||||
#define LCASE (1<<0)
|
#define LCASE (1<<0)
|
||||||
#define UCASE (1<<1)
|
#define UCASE (1<<1)
|
||||||
#define SWAB (1<<2)
|
#define SWAB (1<<2)
|
||||||
#define NERR (1<<3)
|
#define NERR (1<<3)
|
||||||
#define SYNC (1<<4)
|
#define SYNC (1<<4)
|
||||||
|
|
||||||
int cflag;
|
int cflag;
|
||||||
int fflag;
|
int fflag;
|
||||||
|
|
||||||
char *string;
|
char *string;
|
||||||
char *ifile;
|
char *ifile;
|
||||||
char *ofile;
|
char *ofile;
|
||||||
char *ibuf;
|
char *ibuf;
|
||||||
char *obuf;
|
char *obuf;
|
||||||
|
|
||||||
vlong skip;
|
vlong skip;
|
||||||
vlong oseekn;
|
vlong oseekn;
|
||||||
vlong iseekn;
|
vlong iseekn;
|
||||||
vlong count;
|
vlong count;
|
||||||
|
|
||||||
long files = 1;
|
long files = 1;
|
||||||
long ibs = 512;
|
long ibs = 512;
|
||||||
long obs = 512;
|
long obs = 512;
|
||||||
|
|
@ -31,18 +36,23 @@ long nipr;
|
||||||
long nofr;
|
long nofr;
|
||||||
long nopr;
|
long nopr;
|
||||||
long ntrunc;
|
long ntrunc;
|
||||||
|
|
||||||
int dotrunc = 1;
|
int dotrunc = 1;
|
||||||
int ibf;
|
int ibf;
|
||||||
int obf;
|
int obf;
|
||||||
|
|
||||||
char *op;
|
char *op;
|
||||||
int nspace;
|
int nspace;
|
||||||
|
|
||||||
uchar etoa[256];
|
uchar etoa[256];
|
||||||
uchar atoe[256];
|
uchar atoe[256];
|
||||||
uchar atoibm[256];
|
uchar atoibm[256];
|
||||||
|
|
||||||
|
int quiet;
|
||||||
|
|
||||||
void flsh(void);
|
void flsh(void);
|
||||||
int match(char *s);
|
int match(char *s);
|
||||||
vlong number(long big);
|
vlong number(vlong big);
|
||||||
void cnull(int cc);
|
void cnull(int cc);
|
||||||
void null(int c);
|
void null(int c);
|
||||||
void ascii(int cc);
|
void ascii(int cc);
|
||||||
|
|
@ -50,12 +60,12 @@ void unblock(int cc);
|
||||||
void ebcdic(int cc);
|
void ebcdic(int cc);
|
||||||
void ibm(int cc);
|
void ibm(int cc);
|
||||||
void block(int cc);
|
void block(int cc);
|
||||||
void term(void);
|
void term(char*);
|
||||||
void stats(void);
|
void stats(void);
|
||||||
|
|
||||||
#define iskey(s) ((key[0] == '-') && (strcmp(key+1, s) == 0))
|
#define iskey(s) ((key[0] == '-') && (strcmp(key+1, s) == 0))
|
||||||
|
|
||||||
void
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
void (*conv)(int);
|
void (*conv)(int);
|
||||||
|
|
@ -99,20 +109,24 @@ main(int argc, char *argv[])
|
||||||
dotrunc = number(BIG);
|
dotrunc = number(BIG);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if(iskey("quiet")) {
|
||||||
|
quiet = number(BIG);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if(iskey("skip")) {
|
if(iskey("skip")) {
|
||||||
skip = number(BIG);
|
skip = number(VBIG);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(iskey("seek") || iskey("oseek")) {
|
if(iskey("seek") || iskey("oseek")) {
|
||||||
oseekn = number(BIG);
|
oseekn = number(VBIG);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(iskey("iseek")) {
|
if(iskey("iseek")) {
|
||||||
iseekn = number(BIG);
|
iseekn = number(VBIG);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(iskey("count")) {
|
if(iskey("count")) {
|
||||||
count = number(BIG);
|
count = number(VBIG);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(iskey("files")) {
|
if(iskey("files")) {
|
||||||
|
|
@ -165,6 +179,8 @@ main(int argc, char *argv[])
|
||||||
cflag |= SYNC;
|
cflag |= SYNC;
|
||||||
goto cloop;
|
goto cloop;
|
||||||
}
|
}
|
||||||
|
fprint(2, "dd: bad conv %s\n", argv[c]);
|
||||||
|
exits("arg");
|
||||||
}
|
}
|
||||||
fprint(2, "dd: bad arg: %s\n", key);
|
fprint(2, "dd: bad arg: %s\n", key);
|
||||||
exits("arg");
|
exits("arg");
|
||||||
|
|
@ -243,17 +259,17 @@ loop:
|
||||||
perror("read");
|
perror("read");
|
||||||
if((cflag&NERR) == 0) {
|
if((cflag&NERR) == 0) {
|
||||||
flsh();
|
flsh();
|
||||||
term();
|
term("errors");
|
||||||
}
|
}
|
||||||
ibc = 0;
|
ibc = 0;
|
||||||
for(c=0; c<ibs; c++)
|
for(c=0; c<ibs; c++)
|
||||||
if(ibuf[c] != 0)
|
if(ibuf[c] != 0)
|
||||||
ibc = c;
|
ibc = c+1;
|
||||||
|
seek(ibf, ibs, 1);
|
||||||
stats();
|
stats();
|
||||||
}
|
}else if(ibc == 0 && --files<=0) {
|
||||||
if(ibc == 0 && --files<=0) {
|
|
||||||
flsh();
|
flsh();
|
||||||
term();
|
term(nil);
|
||||||
}
|
}
|
||||||
if(ibc != ibs) {
|
if(ibc != ibs) {
|
||||||
nipr++;
|
nipr++;
|
||||||
|
|
@ -290,12 +306,14 @@ flsh(void)
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
if(obc) {
|
if(obc) {
|
||||||
|
/* don't perror dregs of previous errors on a short write */
|
||||||
|
werrstr("");
|
||||||
c = write(obf, obuf, obc);
|
c = write(obf, obuf, obc);
|
||||||
if(c != obc) {
|
if(c != obc) {
|
||||||
if(c > 0)
|
if(c > 0)
|
||||||
++nopr;
|
++nopr;
|
||||||
perror("write");
|
perror("write");
|
||||||
term();
|
term("errors");
|
||||||
}
|
}
|
||||||
if(obc == obs)
|
if(obc == obs)
|
||||||
nofr++;
|
nofr++;
|
||||||
|
|
@ -324,10 +342,10 @@ true:
|
||||||
}
|
}
|
||||||
|
|
||||||
vlong
|
vlong
|
||||||
number(long big)
|
number(vlong big)
|
||||||
{
|
{
|
||||||
char *cs;
|
char *cs;
|
||||||
vlong n;
|
uvlong n;
|
||||||
|
|
||||||
cs = string;
|
cs = string;
|
||||||
n = 0;
|
n = 0;
|
||||||
|
|
@ -340,11 +358,6 @@ number(long big)
|
||||||
n *= 1024;
|
n *= 1024;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* case 'w':
|
|
||||||
n *= sizeof(int);
|
|
||||||
continue;
|
|
||||||
*/
|
|
||||||
|
|
||||||
case 'b':
|
case 'b':
|
||||||
n *= 512;
|
n *= 512;
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -352,11 +365,11 @@ number(long big)
|
||||||
/* case '*':*/
|
/* case '*':*/
|
||||||
case 'x':
|
case 'x':
|
||||||
string = cs;
|
string = cs;
|
||||||
n *= number(BIG);
|
n *= number(VBIG);
|
||||||
|
|
||||||
case '\0':
|
case '\0':
|
||||||
if(n>=big || n<0) {
|
if(n > big) {
|
||||||
fprint(2, "dd: argument %lld out of range\n", n);
|
fprint(2, "dd: argument %llud out of range\n", n);
|
||||||
exits("range");
|
exits("range");
|
||||||
}
|
}
|
||||||
return n;
|
return n;
|
||||||
|
|
@ -536,17 +549,17 @@ block(int cc)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
term(void)
|
term(char *status)
|
||||||
{
|
{
|
||||||
|
|
||||||
stats();
|
stats();
|
||||||
exits(0);
|
exits(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stats(void)
|
stats(void)
|
||||||
{
|
{
|
||||||
|
if(quiet)
|
||||||
|
return;
|
||||||
fprint(2, "%lud+%lud records in\n", nifr, nipr);
|
fprint(2, "%lud+%lud records in\n", nifr, nipr);
|
||||||
fprint(2, "%lud+%lud records out\n", nofr, nopr);
|
fprint(2, "%lud+%lud records out\n", nofr, nopr);
|
||||||
if(ntrunc)
|
if(ntrunc)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue