On 10/28/21 12:11, Paul Eggert wrote:
Wait - lseek returns a number less than -1?! We could easily check for
that FreeBSD bug, perhaps as an independent patch; this shouldn't
require any extra syscalls.
I installed the attached patch to do this. This doesn't fix coreutils
bug#51433; it merely makes 'cp' and similar programs more likely to
detect and report the FreeBSD 9.1 bug you mentioned.From 674912c6f7c45b5f0b1f77da89663cac02c118f7 Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Fri, 29 Oct 2021 18:01:34 -0700
Subject: [PATCH] cp: defend better against FreeBSD 9.1 zfs bug
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Problem reported by Pádraig Brady (Bug#51433#14).
* src/copy.c (lseek_copy, infer_scantype): Report an error if
lseek with SEEK_DATA or SEEK_HOLE returns less than -1,
as this is an lseek bug.
---
src/copy.c | 15 ++++++---------
1 file changed, 6 insertions(+), 9 deletions(-)
diff --git a/src/copy.c b/src/copy.c
index cb9018f93..1cbc9480c 100644
--- a/src/copy.c
+++ b/src/copy.c
@@ -530,7 +530,7 @@ lseek_copy (int src_fd, int dest_fd, char *buf, size_t buf_size,
off_t ext_end = lseek (src_fd, ext_start, SEEK_HOLE);
if (ext_end < 0)
{
- if (errno != ENXIO)
+ if (! (ext_end == -1 && errno == ENXIO))
goto cannot_lseek;
ext_end = src_total_size;
if (ext_end <= ext_start)
@@ -607,12 +607,8 @@ lseek_copy (int src_fd, int dest_fd, char *buf, size_t buf_size,
}
ext_start = lseek (src_fd, dest_pos, SEEK_DATA);
- if (ext_start < 0)
- {
- if (errno != ENXIO)
- goto cannot_lseek;
- break;
- }
+ if (ext_start < 0 && ! (ext_start == -1 && errno == ENXIO))
+ goto cannot_lseek;
}
/* When the source file ends with a hole, we have to do a little more work,
@@ -1097,10 +1093,11 @@ infer_scantype (int fd, struct stat const *sb,
#ifdef SEEK_HOLE
scan_inference->ext_start = lseek (fd, 0, SEEK_DATA);
- if (0 <= scan_inference->ext_start)
+ if (0 <= scan_inference->ext_start
+ || (scan_inference->ext_start == -1 && errno == ENXIO))
return LSEEK_SCANTYPE;
else if (errno != EINVAL && !is_ENOTSUP (errno))
- return errno == ENXIO ? LSEEK_SCANTYPE : ERROR_SCANTYPE;
+ return ERROR_SCANTYPE;
#endif
return ZERO_SCANTYPE;
--
2.31.1