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.
This commit is contained in:
Bernhard Voelker 2025-11-01 22:27:59 +01:00
parent 71c9921d55
commit d36d0f28a4
2 changed files with 84 additions and 26 deletions

View File

@ -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 <<EOF || framework_failure_
# Replace gnulib streq and C23 nullptr as that are not available here.
sed 's/streq/0==str''cmp/; s/nullptr/NU''LL/' > k.c <<EOF || framework_failure_
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
@ -40,6 +40,35 @@ sed 's/streq/0==str''cmp/' > k.c <<EOF || framework_failure_
#include <stdarg.h>
#include <dlfcn.h>
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:

View File

@ -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 <<EOF || framework_failure_
# Replace gnulib streq and C23 nullptr as that are not available here.
sed 's/streq/0==str''cmp/; s/nullptr/NU''LL/' > k.c <<EOF || framework_failure_
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
@ -50,6 +50,35 @@ sed 's/streq/0==str''cmp/' > k.c <<EOF || framework_failure_
#include <stdarg.h>
#include <dlfcn.h>
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;
}