From: Christopher Illarionova Date: Tue, 6 Jan 2026 04:07:49 +0000 (+0000) Subject: tests: cp: support glibc 2.33+ in nfs-removal-race test X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1afe4109f2e568141ea8d36e62e38ad704dc44f3;p=thirdparty%2Fcoreutils.git tests: cp: support glibc 2.33+ in nfs-removal-race test glibc 2.33 removed __xstat, making stat() a direct symbol. This test previously only intercepted __xstat, causing it to skip on modern glibc with 'LD_PRELOAD was ineffective'. Changes: - Intercept both __xstat (glibc < 2.33) and stat (glibc >= 2.33) - Only mark 'preloaded' when stat is called on destination 'd', ensuring the test verifies cp actually stats the destination --- diff --git a/tests/cp/nfs-removal-race.sh b/tests/cp/nfs-removal-race.sh index 207deb94f2..da787e6bb9 100755 --- a/tests/cp/nfs-removal-race.sh +++ b/tests/cp/nfs-removal-race.sh @@ -11,7 +11,9 @@ # file and return 0. # # This test is skipped on systems that lack LD_PRELOAD support; that's fine. -# Similarly, on a system that lacks or __xstat, skipping it is fine. +# Similarly, on a system that lacks , skipping it is fine. +# Note: glibc 2.33+ removed __xstat, so we intercept both __xstat (old glibc) +# and stat (new glibc) to support all systems. # Copyright (C) 2012-2026 Free Software Foundation, Inc. @@ -33,6 +35,8 @@ print_ver_ cp require_gcc_shared_ # Replace each stat call with a call to this wrapper. +# We intercept both __xstat (glibc < 2.33) and stat (glibc >= 2.33) +# to support all glibc versions. cat > k.c <<'EOF' || framework_failure_ #define _GNU_SOURCE #include @@ -46,16 +50,48 @@ cat > k.c <<'EOF' || framework_failure_ #undef __xstat +static int +is_dest_path (const char *path) +{ + return *path == 'd' && path[1] == 0; +} + +static const char * +redirect_path (const char *path) +{ + /* When asked to stat nonexistent "d", + return results suggesting it exists. */ + if (is_dest_path (path)) + { + /* Only mark preloaded when we intercept stat on the destination "d". + This ensures the test verifies that cp actually calls stat on + the destination, not just any file. */ + fclose (fopen ("preloaded", "w")); + return "d2"; + } + return path; +} + +/* For glibc < 2.33: stat() calls __xstat() internally */ int __xstat (int ver, const char *path, struct stat *st) { - static int (*real_stat)(int ver, const char *path, struct stat *st) = NULL; - fclose(fopen("preloaded", "w")); + static int (*real_xstat) (int, const char *, struct stat *) = NULL; + if (!real_xstat) + real_xstat = dlsym (RTLD_NEXT, "__xstat"); + if (!real_xstat) + return -1; + return real_xstat (ver, redirect_path (path), st); +} + +/* For glibc >= 2.33: stat() is a direct symbol */ +int +stat (const char *path, struct stat *st) +{ + static int (*real_stat) (const char *, struct stat *) = NULL; if (!real_stat) - real_stat = dlsym (RTLD_NEXT, "__xstat"); - /* When asked to stat nonexistent "d", - return results suggesting it exists. */ - return real_stat (ver, *path == 'd' && path[1] == 0 ? "d2" : path, st); + real_stat = dlsym (RTLD_NEXT, "stat"); + return real_stat (redirect_path (path), st); } EOF