Index: head/bin/dd/args.c =================================================================== --- head/bin/dd/args.c +++ head/bin/dd/args.c @@ -266,6 +266,7 @@ const char *name; uint64_t set, noset; } ilist[] = { + { "direct", C_IDIRECT, 0 }, { "fullblock", C_IFULLBLOCK, C_SYNC }, }; @@ -410,6 +411,7 @@ const char *name; uint64_t set; } olist[] = { + { "direct", C_ODIRECT }, { "fsync", C_OFSYNC }, { "sync", C_OFSYNC }, }; Index: head/bin/dd/dd.h =================================================================== --- head/bin/dd/dd.h +++ head/bin/dd/dd.h @@ -105,6 +105,8 @@ #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) Index: head/bin/dd/dd.1 =================================================================== --- head/bin/dd/dd.1 +++ head/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 @@ 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 @@ 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 @@ 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 Index: head/bin/dd/dd.c =================================================================== --- head/bin/dd/dd.c +++ head/bin/dd/dd.c @@ -143,7 +143,7 @@ setup(void) { u_int cnt; - int oflags; + int iflags, oflags; cap_rights_t rights; unsigned long cmds[] = { FIODTYPE, MTIOCTOP }; @@ -151,7 +151,10 @@ 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 @@ 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.