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
This commit is contained in:
parent
2048fe7098
commit
919156e34c
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=352922
@ -41,7 +41,7 @@ static char sccsid[] = "@(#)args.c 8.3 (Berkeley) 4/2/94";
|
|||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/param.h>
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
|
|
||||||
static int c_arg(const void *, const void *);
|
static int c_arg(const void *, const void *);
|
||||||
static int c_conv(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_bs(char *);
|
||||||
static void f_cbs(char *);
|
static void f_cbs(char *);
|
||||||
static void f_conv(char *);
|
static void f_conv(char *);
|
||||||
@ -67,6 +68,7 @@ static void f_ibs(char *);
|
|||||||
static void f_if(char *);
|
static void f_if(char *);
|
||||||
static void f_obs(char *);
|
static void f_obs(char *);
|
||||||
static void f_of(char *);
|
static void f_of(char *);
|
||||||
|
static void f_oflag(char *);
|
||||||
static void f_seek(char *);
|
static void f_seek(char *);
|
||||||
static void f_skip(char *);
|
static void f_skip(char *);
|
||||||
static void f_speed(char *);
|
static void f_speed(char *);
|
||||||
@ -90,6 +92,7 @@ static const struct arg {
|
|||||||
{ "iseek", f_skip, C_SKIP, C_SKIP },
|
{ "iseek", f_skip, C_SKIP, C_SKIP },
|
||||||
{ "obs", f_obs, C_OBS, C_BS|C_OBS },
|
{ "obs", f_obs, C_OBS, C_BS|C_OBS },
|
||||||
{ "of", f_of, C_OF, C_OF },
|
{ "of", f_of, C_OF, C_OF },
|
||||||
|
{ "oflag", f_oflag, 0, 0 },
|
||||||
{ "oseek", f_seek, C_SEEK, C_SEEK },
|
{ "oseek", f_seek, C_SEEK, C_SEEK },
|
||||||
{ "seek", f_seek, C_SEEK, C_SEEK },
|
{ "seek", f_seek, C_SEEK, C_SEEK },
|
||||||
{ "skip", f_skip, C_SKIP, C_SKIP },
|
{ "skip", f_skip, C_SKIP, C_SKIP },
|
||||||
@ -348,8 +351,8 @@ f_conv(char *arg)
|
|||||||
|
|
||||||
while (arg != NULL) {
|
while (arg != NULL) {
|
||||||
tmp.name = strsep(&arg, ",");
|
tmp.name = strsep(&arg, ",");
|
||||||
cp = bsearch(&tmp, clist, sizeof(clist) / sizeof(struct conv),
|
cp = bsearch(&tmp, clist, nitems(clist), sizeof(struct conv),
|
||||||
sizeof(struct conv), c_conv);
|
c_conv);
|
||||||
if (cp == NULL)
|
if (cp == NULL)
|
||||||
errx(1, "unknown conversion %s", tmp.name);
|
errx(1, "unknown conversion %s", tmp.name);
|
||||||
if (ddflags & cp->noset)
|
if (ddflags & cp->noset)
|
||||||
@ -368,6 +371,37 @@ c_conv(const void *a, const void *b)
|
|||||||
((const struct conv *)b)->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
|
static intmax_t
|
||||||
postfix_to_mult(const char expr)
|
postfix_to_mult(const char expr)
|
||||||
{
|
{
|
||||||
|
13
bin/dd/dd.1
13
bin/dd/dd.1
@ -123,6 +123,19 @@ If an initial portion of the output file is seeked past (see the
|
|||||||
.Cm oseek
|
.Cm oseek
|
||||||
operand),
|
operand),
|
||||||
the output file is truncated at that point.
|
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
|
.It Cm oseek Ns = Ns Ar n
|
||||||
Seek on the output file
|
Seek on the output file
|
||||||
.Ar n
|
.Ar n
|
||||||
|
20
bin/dd/dd.c
20
bin/dd/dd.c
@ -143,6 +143,7 @@ static void
|
|||||||
setup(void)
|
setup(void)
|
||||||
{
|
{
|
||||||
u_int cnt;
|
u_int cnt;
|
||||||
|
int oflags;
|
||||||
cap_rights_t rights;
|
cap_rights_t rights;
|
||||||
unsigned long cmds[] = { FIODTYPE, MTIOCTOP };
|
unsigned long cmds[] = { FIODTYPE, MTIOCTOP };
|
||||||
|
|
||||||
@ -171,17 +172,28 @@ setup(void)
|
|||||||
/* No way to check for read access here. */
|
/* No way to check for read access here. */
|
||||||
out.fd = STDOUT_FILENO;
|
out.fd = STDOUT_FILENO;
|
||||||
out.name = "stdout";
|
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 {
|
} else {
|
||||||
#define OFLAGS \
|
oflags = O_CREAT;
|
||||||
(O_CREAT | (ddflags & (C_SEEK | C_NOTRUNC) ? 0 : O_TRUNC))
|
if (!(ddflags & (C_SEEK | C_NOTRUNC)))
|
||||||
out.fd = open(out.name, O_RDWR | OFLAGS, DEFFILEMODE);
|
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.
|
* May not have read access, so try again with write only.
|
||||||
* Without read we may have a problem if output also does
|
* Without read we may have a problem if output also does
|
||||||
* not support seeks.
|
* not support seeks.
|
||||||
*/
|
*/
|
||||||
if (out.fd == -1) {
|
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;
|
out.flags |= NOREAD;
|
||||||
cap_rights_clear(&rights, CAP_READ);
|
cap_rights_clear(&rights, CAP_READ);
|
||||||
}
|
}
|
||||||
|
@ -103,6 +103,7 @@ typedef struct {
|
|||||||
#define C_PROGRESS 0x0000000040000000ULL
|
#define C_PROGRESS 0x0000000040000000ULL
|
||||||
#define C_FSYNC 0x0000000080000000ULL
|
#define C_FSYNC 0x0000000080000000ULL
|
||||||
#define C_FDATASYNC 0x0000000100000000ULL
|
#define C_FDATASYNC 0x0000000100000000ULL
|
||||||
|
#define C_OFSYNC 0x0000000200000000ULL
|
||||||
|
|
||||||
#define C_PARITY (C_PAREVEN | C_PARODD | C_PARNONE | C_PARSET)
|
#define C_PARITY (C_PAREVEN | C_PARODD | C_PARNONE | C_PARSET)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user