diff --git a/bin/dd/args.c b/bin/dd/args.c index 3ca49d243ce8..35a076175a93 100644 --- a/bin/dd/args.c +++ b/bin/dd/args.c @@ -266,6 +266,7 @@ static const struct iflag { const char *name; uint64_t set, noset; } ilist[] = { + { "direct", C_IDIRECT, 0 }, { "fullblock", C_IFULLBLOCK, C_SYNC }, }; @@ -410,6 +411,7 @@ static const struct oflag { const char *name; uint64_t set; } olist[] = { + { "direct", C_ODIRECT }, { "fsync", C_OFSYNC }, { "sync", C_OFSYNC }, }; diff --git a/bin/dd/dd.1 b/bin/dd/dd.1 index 756a585d3b26..8bd5fa662ac6 100644 --- a/bin/dd/dd.1 +++ b/bin/dd/dd.1 @@ -32,7 +32,7 @@ .\" @(#)dd.1 8.2 (Berkeley) 1/13/94 .\" $FreeBSD$ .\" -.Dd March 26, 2019 +.Dd June 4, 2020 .Dt DD 1 .Os .Sh NAME @@ -117,6 +117,8 @@ limits the number of times is called on the input rather than the number of blocks copied in full. May not be combined with .Cm conv=sync . +.It Cm direct +Set the O_DIRECT flag on the input file to make reads bypass any local caching. .El .It Cm iseek Ns = Ns Ar n Seek on the input file @@ -143,7 +145,7 @@ the output file is truncated at that point. Where .Cm value is one of the symbols from the following list. -.Bl -tag -width "fsync" +.Bl -tag -width "direct" .It Cm fsync Set the O_FSYNC flag on the output file to make writes synchronous. .It Cm sync @@ -151,6 +153,8 @@ Set the O_SYNC flag on the output file to make writes synchronous. This is synonymous with the .Cm fsync value. +.It Cm direct +Set the O_DIRECT flag on the output file to make writes bypass any local caching. .El .It Cm oseek Ns = Ns Ar n Seek on the output file diff --git a/bin/dd/dd.c b/bin/dd/dd.c index fd228f332b98..c43645fa0073 100644 --- a/bin/dd/dd.c +++ b/bin/dd/dd.c @@ -143,7 +143,7 @@ static void setup(void) { u_int cnt; - int oflags; + int iflags, oflags; cap_rights_t rights; unsigned long cmds[] = { FIODTYPE, MTIOCTOP }; @@ -151,7 +151,10 @@ setup(void) in.name = "stdin"; in.fd = STDIN_FILENO; } else { - in.fd = open(in.name, O_RDONLY, 0); + iflags = 0; + if (ddflags & C_IDIRECT) + iflags |= O_DIRECT; + in.fd = open(in.name, O_RDONLY | iflags, 0); if (in.fd == -1) err(1, "%s", in.name); } @@ -186,6 +189,8 @@ setup(void) oflags |= O_TRUNC; if (ddflags & C_OFSYNC) oflags |= O_FSYNC; + if (ddflags & C_ODIRECT) + oflags |= O_DIRECT; out.fd = open(out.name, O_RDWR | oflags, DEFFILEMODE); /* * May not have read access, so try again with write only. diff --git a/bin/dd/dd.h b/bin/dd/dd.h index a39f879830de..ea606f288f3f 100644 --- a/bin/dd/dd.h +++ b/bin/dd/dd.h @@ -105,6 +105,8 @@ typedef struct { #define C_FDATASYNC 0x0000000100000000ULL #define C_OFSYNC 0x0000000200000000ULL #define C_IFULLBLOCK 0x0000000400000000ULL +#define C_IDIRECT 0x0000000800000000ULL +#define C_ODIRECT 0x0000001000000000ULL #define C_PARITY (C_PAREVEN | C_PARODD | C_PARNONE | C_PARSET)