From a3826d76199071c287086107abeba12f9335fda0 Mon Sep 17 00:00:00 2001 From: George Valkov Date: Mon, 13 Feb 2023 18:50:49 +0000 Subject: [PATCH 3/3] copy: disable sparse copy on macOS Due to a bug in macOS, sparse copies are corrupted on virtual disks formatted with APFS. HFS is not affected. Affected are coreutils install, and gcp when compiled with SEEK_HOLE, as well as macOS Finder. While reading the entire file returns valid data, scanning for allocated segments may return holes where valid data is present. In this case a sparse copy does not contain these segments and returns zeroes instead. Once the virtual disk is dismounted and then mounted again, a sparse copy produces correct results. This breaks OpenWRT build on macOS. Details: https://github.com/openwrt/openwrt/pull/11960 https://github.com/openwrt/openwrt/pull/11960#issuecomment-1423185579 * NEWS: Mention the bug fix. * src/copy.c (infer_scantype): Avoid SEEK_DATA on __APPLE__. * tests/seek-data-capable: Likewise. Addresses https://bugs.gnu.org/61386 --- NEWS | 4 ++++ src/copy.c | 3 ++- tests/seek-data-capable | 3 +++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index cbc614c2e..8f50c0b8e 100644 --- a/NEWS +++ b/NEWS @@ -29,6 +29,10 @@ GNU coreutils NEWS -*- outline -*- falling back from copy_file_range to a better supported standard copy. [issue introduced in coreutils-9.0] + cp, mv, and install now avoid the use of lseek+SEEK_HOLE on macOS, + as data corruption was seen in some cases on APFS file systems. + [issue introduced in coreutils-9.0] + 'mv --backup=simple f d/' no longer mistakenly backs up d/f to f~. [bug introduced in coreutils-9.1] diff --git a/src/copy.c b/src/copy.c index 8370f55bd..e98a36b13 100644 --- a/src/copy.c +++ b/src/copy.c @@ -1062,7 +1062,8 @@ infer_scantype (int fd, struct stat const *sb, && ST_NBLOCKS (*sb) < sb->st_size / ST_NBLOCKSIZE)) return PLAIN_SCANTYPE; -#ifdef SEEK_HOLE +#if defined SEEK_HOLE && !defined __APPLE__ + /* Avoid on macOS (APFS) due to bug #61386. */ off_t ext_start = lseek (fd, 0, SEEK_DATA); if (0 <= ext_start || errno == ENXIO) { diff --git a/tests/seek-data-capable b/tests/seek-data-capable index cc6372214..275a46464 100644 --- a/tests/seek-data-capable +++ b/tests/seek-data-capable @@ -4,6 +4,9 @@ import sys, os, errno, platform if len(sys.argv) != 2: sys.exit(1) +if platform.system() == "Darwin": + sys.exit(1) # as per bug 61386 + if not hasattr(os, 'SEEK_DATA'): # Not available on python 2, or on darwin python 3 # Also Darwin swaps SEEK_DATA/SEEK_HOLE definitions -- 2.26.2