From: Bernhard Voelker Date: Sat, 1 Nov 2025 21:27:59 +0000 (+0100) Subject: tests: avoid skipping of LD_PRELOAD based df tests X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d36d0f28a4b4dbe4b44230e0877a2e15a4690d32;p=thirdparty%2Fcoreutils.git tests: avoid skipping of LD_PRELOAD based df tests It was seen that gnulib's read_file_system_list may use fopen instead of open. Adjust the df(1) tests to replace both library functions. * tests/df/no-mtab-status.sh: Change the shared library code invoked via LD_PRELOAD to override both fopen and open. While at it, perform varargs processing only when path is not "/proc/self/mountinfo". * tests/df/skip-duplicates.sh: Likewise. --- diff --git a/tests/df/no-mtab-status.sh b/tests/df/no-mtab-status.sh index 135462393d..021e949916 100755 --- a/tests/df/no-mtab-status.sh +++ b/tests/df/no-mtab-status.sh @@ -28,8 +28,8 @@ grep '^#define HAVE_GETMNTENT 1' $CONFIG_HEADER > /dev/null \ || skip_ "getmntent is not used on this system" # Simulate "mtab" failure. -# Replace gnulib streq as that is not available here. -sed 's/streq/0==str''cmp/' > k.c < k.c < #include @@ -40,6 +40,35 @@ sed 's/streq/0==str''cmp/' > k.c < #include +static FILE* (*fopen_func)(const char *, const char *); + +FILE* fopen(const char *path, const char *mode) +{ + + /* get reference to original (libc provided) fopen */ + if (!fopen_func) + { + fopen_func = (FILE*(*)(const char *, const char *)) + dlsym(RTLD_NEXT, "fopen"); + if (!fopen_func) + { + fprintf (stderr, "Failed to find fopen()\n"); + errno = ESRCH; + return nullptr; + } + } + + /* Returning ENOENT here will get read_file_system_list() + to fall back to using getmntent() below. */ + if (streq (path, "/proc/self/mountinfo")) + { + errno = ENOENT; + return nullptr; + } + + return fopen_func(path, mode); +} + int open(const char *path, int flags, ...) { static int (*open_func)(const char *, int, ...); @@ -57,13 +86,6 @@ int open(const char *path, int flags, ...) } } - va_list ap; - va_start (ap, flags); - mode_t mode = (sizeof (mode_t) < sizeof (int) - ? va_arg (ap, int) - : va_arg (ap, mode_t)); - va_end (ap); - /* Returning ENOENT here will get read_file_system_list() to fall back to using getmntent() below. */ if (streq (path, "/proc/self/mountinfo")) @@ -71,8 +93,15 @@ int open(const char *path, int flags, ...) errno = ENOENT; return -1; } - else - return open_func(path, flags, mode); + + va_list ap; + va_start (ap, flags); + mode_t mode = (sizeof (mode_t) < sizeof (int) + ? va_arg (ap, int) + : va_arg (ap, mode_t)); + va_end (ap); + + return open_func(path, flags, mode); } struct mntent *getmntent (FILE *fp) @@ -81,12 +110,12 @@ struct mntent *getmntent (FILE *fp) static int done = 0; if (!done) { - fclose (fopen ("x", "w")); + fclose (fopen_func ("x", "w")); ++done; } /* Now simulate the failure. */ errno = ENOENT; - return NULL; + return nullptr; } EOF @@ -99,7 +128,7 @@ cleanup_() { unset LD_PRELOAD; } export LD_PRELOAD=$LD_PRELOAD:./k.so # Test if LD_PRELOAD works: -df 2>/dev/null +df test -f x || skip_ "internal test failure: maybe LD_PRELOAD doesn't work?" # These tests are supposed to succeed: diff --git a/tests/df/skip-duplicates.sh b/tests/df/skip-duplicates.sh index c839f4e191..8521a99644 100755 --- a/tests/df/skip-duplicates.sh +++ b/tests/df/skip-duplicates.sh @@ -38,8 +38,8 @@ grep '^#define HAVE_GETMNTENT 1' $CONFIG_HEADER > /dev/null \ || skip_ "getmntent is not used on this system" # Simulate an mtab file to test various cases. -# Replace gnulib streq as that is not available here. -sed 's/streq/0==str''cmp/' > k.c < k.c < #include @@ -50,6 +50,35 @@ sed 's/streq/0==str''cmp/' > k.c < #include +static FILE* (*fopen_func)(const char *, const char *); + +FILE* fopen(const char *path, const char *mode) +{ + + /* get reference to original (libc provided) fopen */ + if (!fopen_func) + { + fopen_func = (FILE*(*)(const char *, const char *)) + dlsym(RTLD_NEXT, "fopen"); + if (!fopen_func) + { + fprintf (stderr, "Failed to find fopen()\n"); + errno = ESRCH; + return nullptr; + } + } + + /* Returning ENOENT here will get read_file_system_list() + to fall back to using getmntent() below. */ + if (streq (path, "/proc/self/mountinfo")) + { + errno = ENOENT; + return nullptr; + } + + return fopen_func(path, mode); +} + int open(const char *path, int flags, ...) { static int (*open_func)(const char *, int, ...); @@ -67,13 +96,6 @@ int open(const char *path, int flags, ...) } } - va_list ap; - va_start (ap, flags); - mode_t mode = (sizeof (mode_t) < sizeof (int) - ? va_arg (ap, int) - : va_arg (ap, mode_t)); - va_end (ap); - /* Returning ENOENT here will get read_file_system_list() to fall back to using getmntent() below. */ if (streq (path, "/proc/self/mountinfo")) @@ -81,8 +103,15 @@ int open(const char *path, int flags, ...) errno = ENOENT; return -1; } - else - return open_func(path, flags, mode); + + va_list ap; + va_start (ap, flags); + mode_t mode = (sizeof (mode_t) < sizeof (int) + ? va_arg (ap, int) + : va_arg (ap, mode_t)); + va_end (ap); + + return open_func(path, flags, mode); } struct mntent *getmntent (FILE *fp) @@ -94,7 +123,7 @@ struct mntent *getmntent (FILE *fp) /* Prove that LD_PRELOAD works. */ if (!done) { - fclose (fopen ("x", "w")); + fclose (fopen_func ("x", "w")); ++done; }