Date: Mon, 30 Sep 2019 22:00:48 +0000 (UTC) From: Matt Macy <mmacy@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r352923 - head/bin/dd Message-ID: <201909302200.x8UM0mU5032395@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mmacy Date: Mon Sep 30 22:00:48 2019 New Revision: 352923 URL: https://svnweb.freebsd.org/changeset/base/352923 Log: Add iflag=fullblock to dd Normally, count=n means read(2) will be called n times on the input to dd. If the read() returns short, as may happen when reading from a pipe, fewer bytes will be copied from the input. With conv=sync the buffer is padded with zeros to fill the rest of the block. iflag=fullblock causes dd to continue reading until the block is full, so that count=n means n full blocks are copied. This flag is compatible with illumos and GNU dd and is used in the ZFS test suite. Submitted by: Ryan Moeller Reviewed by: manpages, mmacy@ MFC after: 1 week Sponsored by: iXsystems, Inc. Differential Revision: https://reviews.freebsd.org/D21441 Modified: head/bin/dd/args.c head/bin/dd/dd.1 head/bin/dd/dd.c head/bin/dd/dd.h Modified: head/bin/dd/args.c ============================================================================== --- head/bin/dd/args.c Mon Sep 30 21:56:42 2019 (r352922) +++ head/bin/dd/args.c Mon Sep 30 22:00:48 2019 (r352923) @@ -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,7 +262,39 @@ 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) { uintmax_t res; @@ -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 }, }; Modified: head/bin/dd/dd.1 ============================================================================== --- head/bin/dd/dd.1 Mon Sep 30 21:56:42 2019 (r352922) +++ head/bin/dd/dd.1 Mon Sep 30 22:00:48 2019 (r352923) @@ -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 Modified: head/bin/dd/dd.c ============================================================================== --- head/bin/dd/dd.c Mon Sep 30 21:56:42 2019 (r352922) +++ head/bin/dd/dd.c Mon Sep 30 22:00:48 2019 (r352923) @@ -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,26 +440,26 @@ 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 * than noerror, notrunc or sync are specified, the block @@ -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) Modified: head/bin/dd/dd.h ============================================================================== --- head/bin/dd/dd.h Mon Sep 30 21:56:42 2019 (r352922) +++ head/bin/dd/dd.h Mon Sep 30 22:00:48 2019 (r352923) @@ -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)
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201909302200.x8UM0mU5032395>