diff options
author | Matt Macy <mmacy@FreeBSD.org> | 2019-09-30 22:00:48 +0000 |
---|---|---|
committer | Matt Macy <mmacy@FreeBSD.org> | 2019-09-30 22:00:48 +0000 |
commit | b52c534bffcc40e5be49f6d012c9d4005f0bbd81 (patch) | |
tree | 48fe378c50706301933447378a6f14c238c855c6 /bin | |
parent | 919156e34c859f4690eff7af344c76cfbe6e8a64 (diff) | |
download | src-test2-b52c534bffcc40e5be49f6d012c9d4005f0bbd81.tar.gz src-test2-b52c534bffcc40e5be49f6d012c9d4005f0bbd81.zip |
Notes
Diffstat (limited to 'bin')
-rw-r--r-- | bin/dd/args.c | 37 | ||||
-rw-r--r-- | bin/dd/dd.1 | 16 | ||||
-rw-r--r-- | bin/dd/dd.c | 43 | ||||
-rw-r--r-- | bin/dd/dd.h | 1 |
4 files changed, 76 insertions, 21 deletions
diff --git a/bin/dd/args.c b/bin/dd/args.c index 2624d73094a2..3ca49d243ce8 100644 --- a/bin/dd/args.c +++ b/bin/dd/args.c @@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$"); static int c_arg(const void *, const void *); static int c_conv(const void *, const void *); +static int c_iflag(const void *, const void *); static int c_oflag(const void *, const void *); static void f_bs(char *); static void f_cbs(char *); @@ -66,6 +67,7 @@ static void f_files(char *); static void f_fillchar(char *); static void f_ibs(char *); static void f_if(char *); +static void f_iflag(char *); static void f_obs(char *); static void f_of(char *); static void f_oflag(char *); @@ -89,6 +91,7 @@ static const struct arg { { "fillchar", f_fillchar, C_FILL, C_FILL }, { "ibs", f_ibs, C_IBS, C_BS|C_IBS }, { "if", f_if, C_IF, C_IF }, + { "iflag", f_iflag, 0, 0 }, { "iseek", f_skip, C_SKIP, C_SKIP }, { "obs", f_obs, C_OBS, C_BS|C_OBS }, { "of", f_of, C_OF, C_OF }, @@ -259,6 +262,38 @@ f_if(char *arg) in.name = arg; } +static const struct iflag { + const char *name; + uint64_t set, noset; +} ilist[] = { + { "fullblock", C_IFULLBLOCK, C_SYNC }, +}; + +static void +f_iflag(char *arg) +{ + struct iflag *ip, tmp; + + while (arg != NULL) { + tmp.name = strsep(&arg, ","); + ip = bsearch(&tmp, ilist, nitems(ilist), sizeof(struct iflag), + c_iflag); + if (ip == NULL) + errx(1, "unknown iflag %s", tmp.name); + if (ddflags & ip->noset) + errx(1, "%s: illegal conversion combination", tmp.name); + ddflags |= ip->set; + } +} + +static int +c_iflag(const void *a, const void *b) +{ + + return (strcmp(((const struct iflag *)a)->name, + ((const struct iflag *)b)->name)); +} + static void f_obs(char *arg) { @@ -339,7 +374,7 @@ static const struct conv { { "parset", C_PARSET, C_PARODD|C_PAREVEN|C_PARNONE, NULL}, { "sparse", C_SPARSE, 0, NULL }, { "swab", C_SWAB, 0, NULL }, - { "sync", C_SYNC, 0, NULL }, + { "sync", C_SYNC, C_IFULLBLOCK, NULL }, { "ucase", C_UCASE, C_LCASE, NULL }, { "unblock", C_UNBLOCK, C_BLOCK, NULL }, }; diff --git a/bin/dd/dd.1 b/bin/dd/dd.1 index e68e0dd8bf03..756a585d3b26 100644 --- a/bin/dd/dd.1 +++ b/bin/dd/dd.1 @@ -102,6 +102,22 @@ bytes instead of the default 512. Read input from .Ar file instead of the standard input. +.It Cm iflag Ns = Ns Ar value Ns Op , Ns Ar value ... +Where +.Cm value +is one of the symbols from the following list. +.Bl -tag -width "fullblock" +.It Cm fullblock +Reading from the input file may not obtain a full block. +When a read returns short, continue reading to fill the block. +Without this flag, +.Cm count +limits the number of times +.Xr read 2 +is called on the input rather than the number of blocks copied in full. +May not be combined with +.Cm conv=sync . +.El .It Cm iseek Ns = Ns Ar n Seek on the input file .Ar n diff --git a/bin/dd/dd.c b/bin/dd/dd.c index 7977d18b4bfc..fd228f332b98 100644 --- a/bin/dd/dd.c +++ b/bin/dd/dd.c @@ -408,13 +408,15 @@ dd_in(void) memset(in.dbp, 0, in.dbsz); } - n = read(in.fd, in.dbp, in.dbsz); - if (n == 0) { - in.dbrcnt = 0; + in.dbrcnt = 0; +fill: + n = read(in.fd, in.dbp + in.dbrcnt, in.dbsz - in.dbrcnt); + + /* EOF */ + if (n == 0 && in.dbrcnt == 0) return; - } - /* Read error. */ + /* Read error */ if (n == -1) { /* * If noerror not specified, die. POSIX requires that @@ -438,25 +440,25 @@ dd_in(void) /* If sync not specified, omit block and continue. */ if (!(ddflags & C_SYNC)) continue; + } - /* Read errors count as full blocks. */ - in.dbcnt += in.dbrcnt = in.dbsz; - ++st.in_full; + /* If conv=sync, use the entire block. */ + if (ddflags & C_SYNC) + n = in.dbsz; - /* Handle full input blocks. */ - } else if ((size_t)n == (size_t)in.dbsz) { - in.dbcnt += in.dbrcnt = n; - ++st.in_full; + /* Count the bytes read for this block. */ + in.dbrcnt += n; - /* Handle partial input blocks. */ - } else { - /* If sync, use the entire block. */ - if (ddflags & C_SYNC) - in.dbcnt += in.dbrcnt = in.dbsz; - else - in.dbcnt += in.dbrcnt = n; + /* Count the number of full and partial blocks. */ + if (in.dbrcnt == in.dbsz) + ++st.in_full; + else if (ddflags & C_IFULLBLOCK && n != 0) + goto fill; /* these don't count */ + else ++st.in_part; - } + + /* Count the total bytes read for this file. */ + in.dbcnt += in.dbrcnt; /* * POSIX states that if bs is set and no other conversions @@ -478,6 +480,7 @@ dd_in(void) swapbytes(in.dbp, (size_t)n); } + /* Advance to the next block. */ in.dbp += in.dbrcnt; (*cfunc)(); if (need_summary) diff --git a/bin/dd/dd.h b/bin/dd/dd.h index 893e9965e8d3..a39f879830de 100644 --- a/bin/dd/dd.h +++ b/bin/dd/dd.h @@ -104,6 +104,7 @@ typedef struct { #define C_FSYNC 0x0000000080000000ULL #define C_FDATASYNC 0x0000000100000000ULL #define C_OFSYNC 0x0000000200000000ULL +#define C_IFULLBLOCK 0x0000000400000000ULL #define C_PARITY (C_PAREVEN | C_PARODD | C_PARNONE | C_PARSET) |