|
|
#!/bin/sh |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src |
|
|
print_ver_ df |
|
|
require_gcc_shared_ |
|
|
|
|
|
|
|
|
|
|
|
df --local --output=target >LOCAL_FS || skip_ 'df fails' |
|
|
grep '^/$' LOCAL_FS || skip_ 'no root file system found' |
|
|
|
|
|
|
|
|
export CU_NONROOT_FS=$(grep /. LOCAL_FS | head -n1) |
|
|
export CU_REMOTE_FS=$(grep /. LOCAL_FS | tail -n+2 | head -n1) |
|
|
|
|
|
unique_entries=1 |
|
|
test -z "$CU_NONROOT_FS" || unique_entries=$(expr $unique_entries + 1) |
|
|
test -z "$CU_REMOTE_FS" || unique_entries=$(expr $unique_entries + 2) |
|
|
|
|
|
grep '^#define HAVE_GETMNTENT 1' $CONFIG_HEADER > /dev/null \ |
|
|
|| skip_ "getmntent is not used on this system" |
|
|
|
|
|
|
|
|
cat > k.c <<EOF || framework_failure_ |
|
|
#define _GNU_SOURCE |
|
|
#include <stdio.h> |
|
|
#include <stdlib.h> |
|
|
#include <errno.h> |
|
|
#include <fcntl.h> |
|
|
#include <mntent.h> |
|
|
#include <string.h> |
|
|
#include <stdarg.h> |
|
|
#include <dlfcn.h> |
|
|
|
|
|
int open(const char *path, int flags, ...) |
|
|
{ |
|
|
static int (*open_func)(const char *, int, ...); |
|
|
|
|
|
/* get reference to original (libc provided) open */ |
|
|
if (!open_func) |
|
|
{ |
|
|
open_func = (int(*)(const char *, int, ...)) |
|
|
dlsym(RTLD_NEXT, "open"); |
|
|
if (!open_func) |
|
|
{ |
|
|
fprintf (stderr, "Failed to find open()\n"); |
|
|
errno = ESRCH; |
|
|
return -1; |
|
|
} |
|
|
} |
|
|
|
|
|
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")) |
|
|
{ |
|
|
errno = ENOENT; |
|
|
return -1; |
|
|
} |
|
|
else |
|
|
return open_func(path, flags, mode); |
|
|
} |
|
|
|
|
|
struct mntent *getmntent (FILE *fp) |
|
|
{ |
|
|
static char *nonroot_fs; |
|
|
static char *remote_fs; |
|
|
static int done; |
|
|
|
|
|
/* Prove that LD_PRELOAD works. */ |
|
|
if (!done) |
|
|
{ |
|
|
fclose (fopen ("x", "w")); |
|
|
++done; |
|
|
} |
|
|
|
|
|
static struct mntent mntents[] = { |
|
|
{.mnt_fsname="/short", .mnt_dir="/invalid/mount/dir", .mnt_opts=""}, |
|
|
{.mnt_fsname="fsname", .mnt_dir="/", .mnt_opts=""}, |
|
|
{.mnt_fsname="/fsname", .mnt_dir="/.", .mnt_opts=""}, |
|
|
{.mnt_fsname="/fsname", .mnt_dir="/", .mnt_opts=""}, |
|
|
{.mnt_fsname="virtfs", .mnt_dir="/NONROOT", .mnt_type="t1", .mnt_opts=""}, |
|
|
{.mnt_fsname="virtfs2", .mnt_dir="/NONROOT", .mnt_type="t2", .mnt_opts=""}, |
|
|
{.mnt_fsname="netns", .mnt_dir="net:[1234567]", .mnt_opts=""}, |
|
|
{.mnt_fsname="rem:ote1",.mnt_dir="/REMOTE", .mnt_opts=""}, |
|
|
{.mnt_fsname="rem:ote1",.mnt_dir="/REMOTE", .mnt_opts=""}, |
|
|
{.mnt_fsname="rem:ote2",.mnt_dir="/REMOTE", .mnt_opts=""}, |
|
|
}; |
|
|
|
|
|
if (done == 1) |
|
|
{ |
|
|
nonroot_fs = getenv ("CU_NONROOT_FS"); |
|
|
if (!nonroot_fs || !*nonroot_fs) |
|
|
nonroot_fs = "/"; /* merge into / entries. */ |
|
|
|
|
|
remote_fs = getenv ("CU_REMOTE_FS"); |
|
|
} |
|
|
|
|
|
if (done == 1 && !getenv ("CU_TEST_DUPE_INVALID")) |
|
|
done++; /* skip the first entry. */ |
|
|
|
|
|
while (done++ <= 10) |
|
|
{ |
|
|
if (!mntents[done-2].mnt_type) |
|
|
mntents[done-2].mnt_type = "-"; |
|
|
if (!mntents[done-2].mnt_opts) |
|
|
mntents[done-2].mnt_opts = "-"; |
|
|
if (streq (mntents[done-2].mnt_dir, "/NONROOT")) |
|
|
mntents[done-2].mnt_dir = nonroot_fs; |
|
|
if (streq (mntents[done-2].mnt_dir, "/REMOTE")) |
|
|
{ |
|
|
if (!remote_fs || !*remote_fs) |
|
|
continue; |
|
|
else |
|
|
mntents[done-2].mnt_dir = remote_fs; |
|
|
} |
|
|
return &mntents[done-2]; |
|
|
} |
|
|
|
|
|
return NULL; |
|
|
} |
|
|
EOF |
|
|
|
|
|
|
|
|
gcc_shared_ k.c k.so \ |
|
|
|| skip_ 'failed to build mntent shared library' |
|
|
|
|
|
|
|
|
LD_PRELOAD=$LD_PRELOAD:./k.so df |
|
|
test -f x || skip_ "internal test failure: maybe LD_PRELOAD doesn't work?" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LD_PRELOAD=$LD_PRELOAD:./k.so df -T >out || fail=1 |
|
|
test $(wc -l <out) -eq $(expr 1 + $unique_entries) || { fail=1; cat out; } |
|
|
|
|
|
|
|
|
LD_PRELOAD=$LD_PRELOAD:./k.so df --total >out || fail=1 |
|
|
test "$CU_REMOTE_FS" && elide_remote=1 || elide_remote=0 |
|
|
test $(wc -l <out) -eq $(expr 2 + $unique_entries - $elide_remote) || |
|
|
{ fail=1; cat out; } |
|
|
|
|
|
|
|
|
LD_PRELOAD=$LD_PRELOAD:./k.so CU_TEST_DUPE_INVALID=1 df -T >out || fail=1 |
|
|
test $(wc -l <out) -eq $(expr 1 + $unique_entries) || { fail=1; cat out; } |
|
|
|
|
|
|
|
|
if test "$unique_entries" = 2; then |
|
|
test $(grep -c '/fsname' <out) -eq 1 || { fail=1; cat out; } |
|
|
|
|
|
test $(grep -cF '/.' <out) -eq 0 || { fail=1; cat out; } |
|
|
fi |
|
|
|
|
|
|
|
|
test $(grep -c 'virtfs2.*t2' <out) -eq 1 || { fail=1; cat out; } |
|
|
|
|
|
|
|
|
LD_PRELOAD=$LD_PRELOAD:./k.so df -a >out || fail=1 |
|
|
total_fs=6; test "$CU_REMOTE_FS" && total_fs=$(expr $total_fs + 3) |
|
|
test $(wc -l <out) -eq $total_fs || { fail=1; cat out; } |
|
|
|
|
|
test $(grep -c 'virtfs *-' <out) -eq 1 || { fail=1; cat out; } |
|
|
|
|
|
|
|
|
|
|
|
df '.' '.' >out || fail=1 |
|
|
test $(wc -l <out) -eq 3 || { fail=1; cat out; } |
|
|
|
|
|
Exit $fail |
|
|
|