Index: head/bin/dd/args.c =================================================================== --- head/bin/dd/args.c +++ head/bin/dd/args.c @@ -41,7 +41,7 @@ #include __FBSDID("$FreeBSD$"); -#include +#include #include #include @@ -57,6 +57,7 @@ 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_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 @@ { "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 @@ 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 @@ 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 Index: head/bin/dd/dd.h =================================================================== --- head/bin/dd/dd.h +++ head/bin/dd/dd.h @@ -103,6 +103,7 @@ #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) Index: head/bin/dd/dd.1 =================================================================== --- head/bin/dd/dd.1 +++ head/bin/dd/dd.1 @@ -123,6 +123,19 @@ .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 Index: head/bin/dd/dd.c =================================================================== --- head/bin/dd/dd.c +++ head/bin/dd/dd.c @@ -143,6 +143,7 @@ setup(void) { u_int cnt; + int oflags; cap_rights_t rights; unsigned long cmds[] = { FIODTYPE, MTIOCTOP }; @@ -171,17 +172,28 @@ /* 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); }