From: Pádraig Brady Date: Mon, 16 Oct 2017 06:54:29 +0000 (-0700) Subject: dd: support iflag=direct with arbitrary sized files X-Git-Tag: v8.29~28 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5f02cddc184a55b47d2b27c50c25d093d35ce13a;p=thirdparty%2Fcoreutils.git dd: support iflag=direct with arbitrary sized files * src/dd.c (iread): Handle read error with a non-aligned file offset in the O_DIRECT case. This is not an issue on XFS at least, but on EXT4 the final read will return EINVAL rather than the expected 0 to indicate EOF. * tests/dd/direct.sh: Test the iflag=direct case also. * NEWS: Mention the improvement. --- diff --git a/NEWS b/NEWS index 4c697b591e..d5060d1c8e 100644 --- a/NEWS +++ b/NEWS @@ -37,6 +37,8 @@ GNU coreutils NEWS -*- outline -*- ** Improvements + dd now supports iflag=direct with arbitrary sized files on all file systems. + tail --bytes=NUM will efficiently seek to the end of block devices, rather than reading from the start. diff --git a/src/dd.c b/src/dd.c index b6ceb4fd7c..0ff618c963 100644 --- a/src/dd.c +++ b/src/dd.c @@ -1108,11 +1108,21 @@ static ssize_t iread (int fd, char *buf, size_t size) { ssize_t nread; + static ssize_t prev_nread; do { process_signals (); nread = read (fd, buf, size); + /* Ignore final read error with iflag=direct as that + returns EINVAL due to the non aligned file offset. */ + if (nread == -1 && errno == EINVAL + && 0 < prev_nread && prev_nread < size + && (input_flags & O_DIRECT)) + { + errno = 0; + nread = 0; + } } while (nread < 0 && errno == EINTR); @@ -1122,8 +1132,6 @@ iread (int fd, char *buf, size_t size) if (0 < nread && warn_partial_read) { - static ssize_t prev_nread; - if (0 < prev_nread && prev_nread < size) { uintmax_t prev = prev_nread; @@ -1136,10 +1144,9 @@ iread (int fd, char *buf, size_t size) prev); warn_partial_read = false; } - - prev_nread = nread; } + prev_nread = nread; return nread; } diff --git a/tests/dd/direct.sh b/tests/dd/direct.sh index 55f92aea9e..b2a355c0ff 100755 --- a/tests/dd/direct.sh +++ b/tests/dd/direct.sh @@ -1,5 +1,5 @@ #!/bin/sh -# ensure that dd's oflag=direct works +# ensure that dd's iflag=direct and oflag=direct work # Copyright (C) 2009-2017 Free Software Foundation, Inc. @@ -29,7 +29,7 @@ truncate -s 8193 p1 || framework_failure_ for i in short m1 p1; do rm -f out - dd if=$i oflag=direct of=out || fail=1 + dd if=$i iflag=direct oflag=direct of=out || fail=1 done Exit $fail