[ As said requested in the original message, please keep me in Cc ] On 05/08/2020, Paul Eggert wrote: > On 8/5/20 11:47 AM, Nikos Tsipinakis wrote: > > Can you elaborate? I can't find a code path that loses the errno. > > full_read reads a partial block and then tries to read again. The second > read fails with errno == EIO. full_read then returns the number of bytes > successfully read, and the caller ignores errno.
Apologies for the delay, but now I have the time and energy to get this through the finish line. The easiest way to do fix this is probably to make `blocking_read` check errno and return an error if bytes < count (see attached patch)
>From 8dbbf9cc23e769faf580f53d6ee0fff5f3c68356 Mon Sep 17 00:00:00 2001 From: Nikos Tsipinakis <ni...@tsipinakis.com> Date: Sat, 26 Sep 2020 16:41:54 +0300 Subject: [PATCH] Use full_read to avoid errors due to short reads In networked filesystems such as 9p, read() can return short reads even for regular files. --- gnulib.modules | 1 + src/common.h | 1 + src/misc.c | 8 ++++++-- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/gnulib.modules b/gnulib.modules index 82f5e1c..9ded7da 100644 --- a/gnulib.modules +++ b/gnulib.modules @@ -44,6 +44,7 @@ fprintftime fseeko fstatat full-write +full-read futimens getline getopt-gnu diff --git a/src/common.h b/src/common.h index a451999..7f696c5 100644 --- a/src/common.h +++ b/src/common.h @@ -57,6 +57,7 @@ #include "arith.h" #include <backupfile.h> #include <exclude.h> +#include <full-read.h> #include <full-write.h> #include <modechange.h> #include <quote.h> diff --git a/src/misc.c b/src/misc.c index d833b8d..f39707d 100644 --- a/src/misc.c +++ b/src/misc.c @@ -804,7 +804,7 @@ deref_stat (char const *name, struct stat *buf) size_t blocking_read (int fd, void *buf, size_t count) { - size_t bytes = safe_read (fd, buf, count); + size_t bytes = full_read (fd, buf, count); #if defined F_SETFL && O_NONBLOCK if (bytes == SAFE_READ_ERROR && errno == EAGAIN) @@ -812,10 +812,14 @@ blocking_read (int fd, void *buf, size_t count) int flags = fcntl (fd, F_GETFL); if (0 <= flags && flags & O_NONBLOCK && fcntl (fd, F_SETFL, flags & ~O_NONBLOCK) != -1) - bytes = safe_read (fd, buf, count); + bytes = full_read (fd, buf, count); } #endif + if (bytes < count && errno != 0) { + return SAFE_READ_ERROR; + } + return bytes; } -- 2.28.0