On macOS, lseek may not always report a trailing hole, in which case seeking with SEEK_HOLE or SEEK_DATA will fail with ENXIO. Detect this condition by checking if errno is set to ENXIO even with a valid offset and return ENOTSUP instead so that it can be correctly handled rather than the file being considered empty.
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3124 Signed-off-by: Mohamed Akram <[email protected]> --- block/file-posix.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/block/file-posix.c b/block/file-posix.c index 8c738674c..89b3e338c 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -3190,6 +3190,20 @@ static int find_allocation(BlockDriverState *bs, off_t start, BDRVRawState *s = bs->opaque; off_t offs; + /* + * When using SEEK_HOLE on macOS, if errno is ENXIO even if start is not + * beyond EOF, then SEEK_HOLE and SEEK_DATA aren't supported for this file. + */ +#ifdef __APPLE__ + offs = lseek(s->fd, start, SEEK_HOLE); + if (offs < 0) { + if (errno == ENXIO && start < bs->total_sectors * BDRV_SECTOR_SIZE) { + return -ENOTSUP; + } + return -errno; + } +#endif + /* * SEEK_DATA cases: * D1. offs == start: start is in data -- 2.51.0
