Author: mmacy
Date: Mon Sep 30 21:56:42 2019
New Revision: 352922
URL: https://svnweb.freebsd.org/changeset/base/352922

Log:
  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

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:53:26 2019        (r352921)
+++ head/bin/dd/args.c  Mon Sep 30 21:56:42 2019        (r352922)
@@ -41,7 +41,7 @@ static char sccsid[] = "@(#)args.c    8.3 (Berkeley) 4/2/
 #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)
@@ -366,6 +369,37 @@ c_conv(const void *a, const void *b)
 
        return (strcmp(((const struct conv *)a)->name,
            ((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

Modified: head/bin/dd/dd.1
==============================================================================
--- head/bin/dd/dd.1    Mon Sep 30 21:53:26 2019        (r352921)
+++ head/bin/dd/dd.1    Mon Sep 30 21:56:42 2019        (r352922)
@@ -123,6 +123,19 @@ If an initial portion of the output file is seeked pas
 .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

Modified: head/bin/dd/dd.c
==============================================================================
--- head/bin/dd/dd.c    Mon Sep 30 21:53:26 2019        (r352921)
+++ head/bin/dd/dd.c    Mon Sep 30 21:56:42 2019        (r352922)
@@ -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);
                }

Modified: head/bin/dd/dd.h
==============================================================================
--- head/bin/dd/dd.h    Mon Sep 30 21:53:26 2019        (r352921)
+++ head/bin/dd/dd.h    Mon Sep 30 21:56:42 2019        (r352922)
@@ -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)
 
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to