summaryrefslogtreecommitdiff
path: root/bin
diff options
context:
space:
mode:
authorMatt Macy <mmacy@FreeBSD.org>2019-09-30 21:56:42 +0000
committerMatt Macy <mmacy@FreeBSD.org>2019-09-30 21:56:42 +0000
commit919156e34c859f4690eff7af344c76cfbe6e8a64 (patch)
tree42cd7c0af218c863b8582d41fbe2ad8b9ed227d5 /bin
parent2048fe709808fc2658de070dd3ad98659508b041 (diff)
downloadsrc-test-919156e34c859f4690eff7af344c76cfbe6e8a64.tar.gz
src-test-919156e34c859f4690eff7af344c76cfbe6e8a64.zip
Add oflag=fsync and oflag=sync capability to dd
Sets the O_FSYNC flag on the output file. oflag=fsync and oflag=sync are synonyms just as O_FSYNC and O_SYNC are synonyms. This functionality is intended to improve portability of dd commands in the ZFS test suite. Submitted by: Ryan Moeller Reviewed by: manpages, mmacy@ MFC after: 1 week Sponsored by: iXsytems, Inc. Differential Revision: https://reviews.freebsd.org/D21422
Notes
Notes: svn path=/head/; revision=352922
Diffstat (limited to 'bin')
-rw-r--r--bin/dd/args.c40
-rw-r--r--bin/dd/dd.113
-rw-r--r--bin/dd/dd.c20
-rw-r--r--bin/dd/dd.h1
4 files changed, 67 insertions, 7 deletions
diff --git a/bin/dd/args.c b/bin/dd/args.c
index 87385d2d6a91f..2624d73094a2d 100644
--- a/bin/dd/args.c
+++ b/bin/dd/args.c
@@ -41,7 +41,7 @@ static char sccsid[] = "@(#)args.c 8.3 (Berkeley) 4/2/94";
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <sys/types.h>
+#include <sys/param.h>
#include <ctype.h>
#include <err.h>
@@ -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_oflag(const void *, const void *);
static void f_bs(char *);
static void f_cbs(char *);
static void f_conv(char *);
@@ -67,6 +68,7 @@ static void f_ibs(char *);
static void f_if(char *);
static void f_obs(char *);
static void f_of(char *);
+static void f_oflag(char *);
static void f_seek(char *);
static void f_skip(char *);
static void f_speed(char *);
@@ -90,6 +92,7 @@ static const struct arg {
{ "iseek", f_skip, C_SKIP, C_SKIP },
{ "obs", f_obs, C_OBS, C_BS|C_OBS },
{ "of", f_of, C_OF, C_OF },
+ { "oflag", f_oflag, 0, 0 },
{ "oseek", f_seek, C_SEEK, C_SEEK },
{ "seek", f_seek, C_SEEK, C_SEEK },
{ "skip", f_skip, C_SKIP, C_SKIP },
@@ -348,8 +351,8 @@ f_conv(char *arg)
while (arg != NULL) {
tmp.name = strsep(&arg, ",");
- cp = bsearch(&tmp, clist, sizeof(clist) / sizeof(struct conv),
- sizeof(struct conv), c_conv);
+ cp = bsearch(&tmp, clist, nitems(clist), sizeof(struct conv),
+ c_conv);
if (cp == NULL)
errx(1, "unknown conversion %s", tmp.name);
if (ddflags & cp->noset)
@@ -368,6 +371,37 @@ c_conv(const void *a, const void *b)
((const struct conv *)b)->name));
}
+static const struct oflag {
+ const char *name;
+ uint64_t set;
+} olist[] = {
+ { "fsync", C_OFSYNC },
+ { "sync", C_OFSYNC },
+};
+
+static void
+f_oflag(char *arg)
+{
+ struct oflag *op, tmp;
+
+ while (arg != NULL) {
+ tmp.name = strsep(&arg, ",");
+ op = bsearch(&tmp, olist, nitems(olist), sizeof(struct oflag),
+ c_oflag);
+ if (op == NULL)
+ errx(1, "unknown open flag %s", tmp.name);
+ ddflags |= op->set;
+ }
+}
+
+static int
+c_oflag(const void *a, const void *b)
+{
+
+ return (strcmp(((const struct oflag *)a)->name,
+ ((const struct oflag *)b)->name));
+}
+
static intmax_t
postfix_to_mult(const char expr)
{
diff --git a/bin/dd/dd.1 b/bin/dd/dd.1
index e1fa48a82520a..e68e0dd8bf038 100644
--- a/bin/dd/dd.1
+++ b/bin/dd/dd.1
@@ -123,6 +123,19 @@ If an initial portion of the output file is seeked past (see the
.Cm oseek
operand),
the output file is truncated at that point.
+.It Cm oflag Ns = Ns Ar value Ns Op , Ns Ar value ...
+Where
+.Cm value
+is one of the symbols from the following list.
+.Bl -tag -width "fsync"
+.It Cm fsync
+Set the O_FSYNC flag on the output file to make writes synchronous.
+.It Cm sync
+Set the O_SYNC flag on the output file to make writes synchronous.
+This is synonymous with the
+.Cm fsync
+value.
+.El
.It Cm oseek Ns = Ns Ar n
Seek on the output file
.Ar n
diff --git a/bin/dd/dd.c b/bin/dd/dd.c
index 64484bd7d5640..7977d18b4bfcf 100644
--- a/bin/dd/dd.c
+++ b/bin/dd/dd.c
@@ -143,6 +143,7 @@ static void
setup(void)
{
u_int cnt;
+ int oflags;
cap_rights_t rights;
unsigned long cmds[] = { FIODTYPE, MTIOCTOP };
@@ -171,17 +172,28 @@ setup(void)
/* No way to check for read access here. */
out.fd = STDOUT_FILENO;
out.name = "stdout";
+ if (ddflags & C_OFSYNC) {
+ oflags = fcntl(out.fd, F_GETFL);
+ if (oflags == -1)
+ err(1, "unable to get fd flags for stdout");
+ oflags |= O_FSYNC;
+ if (fcntl(out.fd, F_SETFL, oflags) == -1)
+ err(1, "unable to set fd flags for stdout");
+ }
} else {
-#define OFLAGS \
- (O_CREAT | (ddflags & (C_SEEK | C_NOTRUNC) ? 0 : O_TRUNC))
- out.fd = open(out.name, O_RDWR | OFLAGS, DEFFILEMODE);
+ oflags = O_CREAT;
+ if (!(ddflags & (C_SEEK | C_NOTRUNC)))
+ oflags |= O_TRUNC;
+ if (ddflags & C_OFSYNC)
+ oflags |= O_FSYNC;
+ out.fd = open(out.name, O_RDWR | oflags, DEFFILEMODE);
/*
* May not have read access, so try again with write only.
* Without read we may have a problem if output also does
* not support seeks.
*/
if (out.fd == -1) {
- out.fd = open(out.name, O_WRONLY | OFLAGS, DEFFILEMODE);
+ out.fd = open(out.name, O_WRONLY | oflags, DEFFILEMODE);
out.flags |= NOREAD;
cap_rights_clear(&rights, CAP_READ);
}
diff --git a/bin/dd/dd.h b/bin/dd/dd.h
index a255a5970e527..893e9965e8d3f 100644
--- a/bin/dd/dd.h
+++ b/bin/dd/dd.h
@@ -103,6 +103,7 @@ typedef struct {
#define C_PROGRESS 0x0000000040000000ULL
#define C_FSYNC 0x0000000080000000ULL
#define C_FDATASYNC 0x0000000100000000ULL
+#define C_OFSYNC 0x0000000200000000ULL
#define C_PARITY (C_PAREVEN | C_PARODD | C_PARNONE | C_PARSET)