|
|
998e46 |
diff --git a/src/df.c b/src/df.c
|
|
|
998e46 |
index e28a656..fe222d9 100644
|
|
|
998e46 |
--- a/src/df.c
|
|
|
998e46 |
+++ b/src/df.c
|
|
|
998e46 |
@@ -45,12 +45,12 @@
|
|
|
522fea |
|
|
|
522fea |
/* Filled with device numbers of examined file systems to avoid
|
|
|
522fea |
duplicities in output. */
|
|
|
522fea |
-struct devlist
|
|
|
522fea |
+static struct devlist
|
|
|
522fea |
{
|
|
|
522fea |
dev_t dev_num;
|
|
|
522fea |
struct mount_entry *me;
|
|
|
522fea |
struct devlist *next;
|
|
|
522fea |
-};
|
|
|
522fea |
+} *device_list;
|
|
|
522fea |
|
|
|
522fea |
/* If true, show even file systems with zero size or
|
|
|
522fea |
uninteresting types. */
|
|
|
998e46 |
@@ -609,13 +609,10 @@ excluded_fstype (const char *fstype)
|
|
|
522fea |
me_mountdir wins. */
|
|
|
522fea |
|
|
|
522fea |
static void
|
|
|
522fea |
-filter_mount_list (void)
|
|
|
522fea |
+filter_mount_list (bool devices_only)
|
|
|
522fea |
{
|
|
|
522fea |
struct mount_entry *me;
|
|
|
522fea |
|
|
|
522fea |
- /* Store of already-processed device numbers. */
|
|
|
522fea |
- struct devlist *devlist_head = NULL;
|
|
|
522fea |
-
|
|
|
522fea |
/* Sort all 'wanted' entries into the list devlist_head. */
|
|
|
522fea |
for (me = mount_list; me;)
|
|
|
522fea |
{
|
|
|
998e46 |
@@ -623,41 +620,66 @@ filter_mount_list (void)
|
|
|
522fea |
struct devlist *devlist;
|
|
|
522fea |
struct mount_entry *discard_me = NULL;
|
|
|
522fea |
|
|
|
522fea |
- if (-1 == stat (me->me_mountdir, &buf))
|
|
|
522fea |
+ /* Avoid stating remote file systems as that may hang.
|
|
|
522fea |
+ On Linux we probably have me_dev populated from /proc/self/mountinfo,
|
|
|
522fea |
+ however we still stat() in case another device was mounted later. */
|
|
|
522fea |
+ if ((me->me_remote && show_local_fs)
|
|
|
522fea |
+ || -1 == stat (me->me_mountdir, &buf))
|
|
|
522fea |
{
|
|
|
522fea |
- /* Stat failed - add ME to be able to complain about it later. */
|
|
|
522fea |
+ /* If remote, and showing just local, add ME for filtering later.
|
|
|
522fea |
+ If stat failed; add ME to be able to complain about it later. */
|
|
|
522fea |
buf.st_dev = me->me_dev;
|
|
|
522fea |
}
|
|
|
522fea |
else
|
|
|
522fea |
{
|
|
|
522fea |
- /* If the device name is a real path name ... */
|
|
|
522fea |
- if (strchr (me->me_devname, '/'))
|
|
|
522fea |
- {
|
|
|
522fea |
- /* ... try to find its device number in the devlist. */
|
|
|
522fea |
- for (devlist = devlist_head; devlist; devlist = devlist->next)
|
|
|
522fea |
- if (devlist->dev_num == buf.st_dev)
|
|
|
522fea |
- break;
|
|
|
522fea |
+ /* If we've already seen this device... */
|
|
|
522fea |
+ for (devlist = device_list; devlist; devlist = devlist->next)
|
|
|
522fea |
+ if (devlist->dev_num == buf.st_dev)
|
|
|
522fea |
+ break;
|
|
|
522fea |
|
|
|
522fea |
- if (devlist)
|
|
|
522fea |
+ if (devlist)
|
|
|
522fea |
+ {
|
|
|
522fea |
+ if (! print_grand_total && me->me_remote && devlist->me->me_remote
|
|
|
522fea |
+ && ! STREQ (devlist->me->me_devname, me->me_devname))
|
|
|
522fea |
{
|
|
|
522fea |
+ /* Don't discard remote entries with different locations,
|
|
|
522fea |
+ as these are more likely to be explicitly mounted.
|
|
|
522fea |
+ However avoid this when producing a total to give
|
|
|
522fea |
+ a more accurate value in that case. */
|
|
|
522fea |
+ }
|
|
|
522fea |
+ else if ((strchr (me->me_devname, '/')
|
|
|
522fea |
+ /* let "real" devices with '/' in the name win. */
|
|
|
522fea |
+ && ! strchr (devlist->me->me_devname, '/'))
|
|
|
522fea |
+ /* let a shorter mountdir win. */
|
|
|
522fea |
+ || (strlen (devlist->me->me_mountdir)
|
|
|
522fea |
+ > strlen (me->me_mountdir))
|
|
|
522fea |
+ /* let an entry overmounted on a new device win... */
|
|
|
522fea |
+ || (! STREQ (devlist->me->me_devname, me->me_devname)
|
|
|
522fea |
+ /* ... but only when matching an existing mnt point,
|
|
|
522fea |
+ to avoid problematic replacement when given
|
|
|
522fea |
+ inaccurate mount lists, seen with some chroot
|
|
|
522fea |
+ environments for example. */
|
|
|
522fea |
+ && STREQ (me->me_mountdir,
|
|
|
522fea |
+ devlist->me->me_mountdir)))
|
|
|
522fea |
+ {
|
|
|
522fea |
+ /* Discard mount entry for existing device. */
|
|
|
522fea |
+ discard_me = devlist->me;
|
|
|
522fea |
+ devlist->me = me;
|
|
|
522fea |
+ }
|
|
|
522fea |
+ else
|
|
|
522fea |
+ {
|
|
|
522fea |
+ /* Discard mount entry currently being processed. */
|
|
|
522fea |
discard_me = me;
|
|
|
522fea |
-
|
|
|
522fea |
- /* Let the shorter mountdir win. */
|
|
|
522fea |
- if (! strchr (devlist->me->me_devname, '/')
|
|
|
522fea |
- || (strlen (devlist->me->me_mountdir)
|
|
|
522fea |
- > strlen (me->me_mountdir)))
|
|
|
522fea |
- {
|
|
|
522fea |
- discard_me = devlist->me;
|
|
|
522fea |
- devlist->me = me;
|
|
|
522fea |
- }
|
|
|
522fea |
}
|
|
|
522fea |
+
|
|
|
522fea |
}
|
|
|
522fea |
}
|
|
|
522fea |
|
|
|
522fea |
if (discard_me)
|
|
|
522fea |
{
|
|
|
522fea |
me = me->me_next;
|
|
|
522fea |
- free_mount_entry (discard_me);
|
|
|
522fea |
+ if (! devices_only)
|
|
|
522fea |
+ free_mount_entry (discard_me);
|
|
|
522fea |
}
|
|
|
522fea |
else
|
|
|
522fea |
{
|
|
|
998e46 |
@@ -665,28 +687,49 @@ filter_mount_list (void)
|
|
|
522fea |
devlist = xmalloc (sizeof *devlist);
|
|
|
522fea |
devlist->me = me;
|
|
|
522fea |
devlist->dev_num = buf.st_dev;
|
|
|
522fea |
- devlist->next = devlist_head;
|
|
|
522fea |
- devlist_head = devlist;
|
|
|
522fea |
+ devlist->next = device_list;
|
|
|
522fea |
+ device_list = devlist;
|
|
|
522fea |
|
|
|
522fea |
me = me->me_next;
|
|
|
522fea |
}
|
|
|
522fea |
}
|
|
|
522fea |
|
|
|
522fea |
/* Finally rebuild the mount_list from the devlist. */
|
|
|
522fea |
- mount_list = NULL;
|
|
|
522fea |
- while (devlist_head)
|
|
|
522fea |
+ if (! devices_only) {
|
|
|
522fea |
+ mount_list = NULL;
|
|
|
522fea |
+ while (device_list)
|
|
|
522fea |
+ {
|
|
|
522fea |
+ /* Add the mount entry. */
|
|
|
522fea |
+ me = device_list->me;
|
|
|
522fea |
+ me->me_next = mount_list;
|
|
|
522fea |
+ mount_list = me;
|
|
|
522fea |
+ /* Free devlist entry and advance. */
|
|
|
522fea |
+ struct devlist *devlist = device_list->next;
|
|
|
522fea |
+ free (device_list);
|
|
|
522fea |
+ device_list = devlist;
|
|
|
522fea |
+ }
|
|
|
522fea |
+ }
|
|
|
998e46 |
+}
|
|
|
998e46 |
+
|
|
|
522fea |
+/* Search a mount entry list for device id DEV.
|
|
|
522fea |
+ Return the corresponding mount entry if found or NULL if not. */
|
|
|
522fea |
+
|
|
|
522fea |
+static struct mount_entry const * _GL_ATTRIBUTE_PURE
|
|
|
522fea |
+me_for_dev (dev_t dev)
|
|
|
522fea |
+{
|
|
|
522fea |
+ struct devlist *dl = device_list;
|
|
|
522fea |
+
|
|
|
522fea |
+ while (dl)
|
|
|
998e46 |
{
|
|
|
998e46 |
- /* Add the mount entry. */
|
|
|
998e46 |
- me = devlist_head->me;
|
|
|
998e46 |
- me->me_next = mount_list;
|
|
|
998e46 |
- mount_list = me;
|
|
|
998e46 |
- /* Free devlist entry and advance. */
|
|
|
998e46 |
- struct devlist *devlist = devlist_head->next;
|
|
|
998e46 |
- free (devlist_head);
|
|
|
998e46 |
- devlist_head = devlist;
|
|
|
522fea |
+ if (dl->dev_num == dev)
|
|
|
522fea |
+ return dl->me;
|
|
|
522fea |
+ dl = dl->next;
|
|
|
998e46 |
}
|
|
|
522fea |
+
|
|
|
522fea |
+ return NULL;
|
|
|
998e46 |
}
|
|
|
998e46 |
|
|
|
522fea |
+
|
|
|
522fea |
/* Return true if N is a known integer value. On many file systems,
|
|
|
522fea |
UINTMAX_MAX represents an unknown value; on AIX, UINTMAX_MAX - 1
|
|
|
522fea |
represents unknown. Use a rule that works on AIX file systems, and
|
|
|
998e46 |
@@ -856,6 +899,11 @@ get_dev (char const *disk, char const *mount_point, char const* file,
|
|
|
522fea |
if (!selected_fstype (fstype) || excluded_fstype (fstype))
|
|
|
522fea |
return;
|
|
|
522fea |
|
|
|
522fea |
+ /* Ignore relative MOUNT_POINTs, which are present for example
|
|
|
522fea |
+ in /proc/mounts on Linux with network namespaces. */
|
|
|
522fea |
+ if (!force_fsu && mount_point && ! IS_ABSOLUTE_FILE_NAME (mount_point))
|
|
|
522fea |
+ return;
|
|
|
522fea |
+
|
|
|
522fea |
/* If MOUNT_POINT is NULL, then the file system is not mounted, and this
|
|
|
522fea |
program reports on the file system that the special file is on.
|
|
|
522fea |
It would be better to report on the unmounted file system,
|
|
|
998e46 |
@@ -868,9 +916,43 @@ get_dev (char const *disk, char const *mount_point, char const* file,
|
|
|
522fea |
fsu = *force_fsu;
|
|
|
522fea |
else if (get_fs_usage (stat_file, disk, &fsu))
|
|
|
522fea |
{
|
|
|
522fea |
- error (0, errno, "%s", quote (stat_file));
|
|
|
522fea |
- exit_status = EXIT_FAILURE;
|
|
|
522fea |
- return;
|
|
|
522fea |
+ /* If we can't access a system provided entry due
|
|
|
522fea |
+ to it not being present (now), or due to permissions,
|
|
|
522fea |
+ just output placeholder values rather than failing. */
|
|
|
522fea |
+ if (process_all && (errno == EACCES || errno == ENOENT))
|
|
|
522fea |
+ {
|
|
|
522fea |
+ if (! show_all_fs)
|
|
|
522fea |
+ return;
|
|
|
522fea |
+
|
|
|
522fea |
+ fstype = "-";
|
|
|
522fea |
+ fsu.fsu_blocksize = fsu.fsu_blocks = fsu.fsu_bfree =
|
|
|
522fea |
+ fsu.fsu_bavail = fsu.fsu_files = fsu.fsu_ffree = UINTMAX_MAX;
|
|
|
522fea |
+ }
|
|
|
522fea |
+ else
|
|
|
522fea |
+ {
|
|
|
522fea |
+ error (0, errno, "%s", quote (stat_file));
|
|
|
522fea |
+ exit_status = EXIT_FAILURE;
|
|
|
522fea |
+ return;
|
|
|
522fea |
+ }
|
|
|
522fea |
+ }
|
|
|
522fea |
+ else if (process_all && show_all_fs)
|
|
|
522fea |
+ {
|
|
|
522fea |
+ /* Ensure we don't output incorrect stats for over-mounted directories.
|
|
|
522fea |
+ Discard stats when the device name doesn't match. Though don't
|
|
|
522fea |
+ discard when used and current mount entries are both remote due
|
|
|
522fea |
+ to the possibility of aliased host names or exports. */
|
|
|
522fea |
+ struct stat sb;
|
|
|
522fea |
+ if (stat (stat_file, &sb) == 0)
|
|
|
522fea |
+ {
|
|
|
522fea |
+ struct mount_entry const * dev_me = me_for_dev (sb.st_dev);
|
|
|
522fea |
+ if (dev_me && ! STREQ (dev_me->me_devname, disk)
|
|
|
522fea |
+ && (! dev_me->me_remote || ! me_remote))
|
|
|
522fea |
+ {
|
|
|
522fea |
+ fstype = "-";
|
|
|
522fea |
+ fsu.fsu_blocksize = fsu.fsu_blocks = fsu.fsu_bfree =
|
|
|
522fea |
+ fsu.fsu_bavail = fsu.fsu_files = fsu.fsu_ffree = UINTMAX_MAX;
|
|
|
522fea |
+ }
|
|
|
522fea |
+ }
|
|
|
522fea |
}
|
|
|
522fea |
|
|
|
522fea |
if (fsu.fsu_blocks == 0 && !show_all_fs && !show_listed_fs)
|
|
|
998e46 |
@@ -1275,8 +1357,7 @@ get_all_entries (void)
|
|
|
522fea |
{
|
|
|
522fea |
struct mount_entry *me;
|
|
|
522fea |
|
|
|
522fea |
- if (!show_all_fs)
|
|
|
522fea |
- filter_mount_list ();
|
|
|
522fea |
+ filter_mount_list (show_all_fs);
|
|
|
522fea |
|
|
|
522fea |
for (me = mount_list; me; me = me->me_next)
|
|
|
522fea |
get_dev (me->me_devname, me->me_mountdir, NULL, NULL, me->me_type,
|
|
|
998e46 |
@@ -1325,7 +1406,7 @@ or all file systems by default.\n\
|
|
|
998e46 |
emit_mandatory_arg_note ();
|
|
|
998e46 |
|
|
|
998e46 |
fputs (_("\
|
|
|
998e46 |
- -a, --all include dummy file systems\n\
|
|
|
998e46 |
+ -a, --all include pseudo, duplicate, inaccessible file systems\n\
|
|
|
998e46 |
-B, --block-size=SIZE scale sizes by SIZE before printing them; e.g.,\n\
|
|
|
998e46 |
'-BM' prints sizes in units of 1,048,576 bytes;\n\
|
|
|
998e46 |
see SIZE format below\n\
|
|
|
998e46 |
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
|
|
|
998e46 |
index 942d9a1..1df1eac 100644
|
|
|
998e46 |
--- a/doc/coreutils.texi
|
|
|
998e46 |
+++ b/doc/coreutils.texi
|
|
|
998e46 |
@@ -11123,11 +11123,15 @@ The program accepts the following options. Also see @ref{Common options}.
|
|
|
522fea |
@itemx --all
|
|
|
522fea |
@opindex -a
|
|
|
522fea |
@opindex --all
|
|
|
522fea |
-@cindex automounter file systems
|
|
|
522fea |
@cindex ignore file systems
|
|
|
522fea |
-Include in the listing dummy file systems, which
|
|
|
522fea |
-are omitted by default. Such file systems are typically special-purpose
|
|
|
522fea |
-pseudo-file-systems, such as automounter entries.
|
|
|
522fea |
+Include in the listing dummy, duplicate, or inaccessible file systems, which
|
|
|
522fea |
+are omitted by default. Dummy file systems are typically special purpose
|
|
|
522fea |
+pseudo file systems such as @samp{/proc}, with no associated storage.
|
|
|
522fea |
+Duplicate file systems are local or remote file systems that are mounted
|
|
|
522fea |
+at separate locations in the local file hierarchy, or bind mounted locations.
|
|
|
522fea |
+Inaccessible file systems are those which are mounted but subsequently
|
|
|
522fea |
+over-mounted by another file system at that point, or otherwise inaccessible
|
|
|
522fea |
+due to permissions of the mount point etc.
|
|
|
522fea |
|
|
|
522fea |
@item -B @var{size}
|
|
|
522fea |
@itemx --block-size=@var{size}
|
|
|
998e46 |
diff --git a/tests/df/skip-duplicates.sh b/tests/df/skip-duplicates.sh
|
|
|
998e46 |
index 1e94dc0..4069604 100755
|
|
|
998e46 |
--- a/tests/df/skip-duplicates.sh
|
|
|
998e46 |
+++ b/tests/df/skip-duplicates.sh
|
|
|
522fea |
@@ -2,7 +2,7 @@
|
|
|
522fea |
# Test df's behavior when the mount list contains duplicate entries.
|
|
|
522fea |
# This test is skipped on systems that lack LD_PRELOAD support; that's fine.
|
|
|
522fea |
|
|
|
522fea |
-# Copyright (C) 2012-2013 Free Software Foundation, Inc.
|
|
|
522fea |
+# Copyright (C) 2012-2015 Free Software Foundation, Inc.
|
|
|
522fea |
|
|
|
522fea |
# This program is free software: you can redistribute it and/or modify
|
|
|
522fea |
# it under the terms of the GNU General Public License as published by
|
|
|
522fea |
@@ -21,19 +21,73 @@
|
|
|
522fea |
print_ver_ df
|
|
|
522fea |
require_gcc_shared_
|
|
|
522fea |
|
|
|
522fea |
-df || skip_ "df fails"
|
|
|
522fea |
+# We use --local here so as to not activate
|
|
|
522fea |
+# potentially very many remote mounts.
|
|
|
522fea |
+df --local || skip_ 'df fails'
|
|
|
998e46 |
|
|
|
998e46 |
-# Simulate an mtab file with two entries of the same device number.
|
|
|
998e46 |
-# Also add entries with unstatable mount dirs to ensure that's handled.
|
|
|
998e46 |
-cat > k.c <<'EOF' || framework_failure_
|
|
|
522fea |
+export CU_NONROOT_FS=$(df --local --output=target 2>&1 | grep /. | head -n1)
|
|
|
522fea |
+export CU_REMOTE_FS=$(df --local --output=target 2>&1 | grep /. |
|
|
|
522fea |
+ tail -n+2 | head -n1)
|
|
|
522fea |
+
|
|
|
522fea |
+unique_entries=1
|
|
|
522fea |
+test -z "$CU_NONROOT_FS" || unique_entries=$(expr $unique_entries + 1)
|
|
|
522fea |
+test -z "$CU_REMOTE_FS" || unique_entries=$(expr $unique_entries + 2)
|
|
|
522fea |
+
|
|
|
522fea |
+grep '^#define HAVE_MNTENT_H 1' $CONFIG_HEADER > /dev/null \
|
|
|
522fea |
+ || skip_ "no mntent.h available to confirm the interface"
|
|
|
522fea |
+
|
|
|
522fea |
+grep '^#define HAVE_GETMNTENT 1' $CONFIG_HEADER > /dev/null \
|
|
|
522fea |
+ || skip_ "getmntent is not used on this system"
|
|
|
522fea |
+
|
|
|
522fea |
+# Simulate an mtab file to test various cases.
|
|
|
522fea |
+cat > k.c <
|
|
|
522fea |
+#define _GNU_SOURCE
|
|
|
522fea |
#include <stdio.h>
|
|
|
522fea |
#include <stdlib.h>
|
|
|
522fea |
+#include <errno.h>
|
|
|
522fea |
#include <mntent.h>
|
|
|
522fea |
+#include <string.h>
|
|
|
522fea |
+#include <dlfcn.h>
|
|
|
522fea |
+
|
|
|
522fea |
+#define STREQ(a, b) (strcmp (a, b) == 0)
|
|
|
522fea |
+
|
|
|
522fea |
+FILE* fopen(const char *path, const char *mode)
|
|
|
522fea |
+{
|
|
|
522fea |
+ static FILE* (*fopen_func)(char const *, char const *);
|
|
|
522fea |
+
|
|
|
522fea |
+ /* get reference to original (libc provided) fopen */
|
|
|
522fea |
+ if (!fopen_func)
|
|
|
522fea |
+ {
|
|
|
522fea |
+ fopen_func = (FILE*(*)(char const *, char const *))
|
|
|
522fea |
+ dlsym(RTLD_NEXT, "fopen");
|
|
|
522fea |
+ if (!fopen_func)
|
|
|
522fea |
+ {
|
|
|
522fea |
+ fprintf (stderr, "Failed to find fopen()\n");
|
|
|
522fea |
+ errno = ESRCH;
|
|
|
522fea |
+ return NULL;
|
|
|
522fea |
+ }
|
|
|
522fea |
+ }
|
|
|
522fea |
+
|
|
|
522fea |
+ /* Returning ENOENT here will get read_file_system_list()
|
|
|
522fea |
+ to fall back to using getmntent() below. */
|
|
|
522fea |
+ if (STREQ (path, "/proc/self/mountinfo"))
|
|
|
522fea |
+ {
|
|
|
522fea |
+ errno = ENOENT;
|
|
|
522fea |
+ return NULL;
|
|
|
522fea |
+ }
|
|
|
522fea |
+ else
|
|
|
522fea |
+ return fopen_func(path, mode);
|
|
|
522fea |
+}
|
|
|
522fea |
+
|
|
|
522fea |
+#define STREQ(a, b) (strcmp (a, b) == 0)
|
|
|
522fea |
|
|
|
522fea |
struct mntent *getmntent (FILE *fp)
|
|
|
522fea |
{
|
|
|
522fea |
+ static char *nonroot_fs;
|
|
|
522fea |
+ static char *remote_fs;
|
|
|
522fea |
+ static int done;
|
|
|
522fea |
+
|
|
|
522fea |
/* Prove that LD_PRELOAD works. */
|
|
|
522fea |
- static int done = 0;
|
|
|
522fea |
if (!done)
|
|
|
522fea |
{
|
|
|
522fea |
fclose (fopen ("x", "w"));
|
|
|
522fea |
@@ -41,50 +95,92 @@ struct mntent *getmntent (FILE *fp)
|
|
|
522fea |
}
|
|
|
522fea |
|
|
|
522fea |
static struct mntent mntents[] = {
|
|
|
522fea |
- {.mnt_fsname="/short", .mnt_dir="/invalid/mount/dir"},
|
|
|
522fea |
- {.mnt_fsname="fsname", .mnt_dir="/",},
|
|
|
522fea |
- {.mnt_fsname="/fsname", .mnt_dir="/root"},
|
|
|
522fea |
- {.mnt_fsname="/fsname", .mnt_dir="/"},
|
|
|
522fea |
+ {.mnt_fsname="/short", .mnt_dir="/invalid/mount/dir", .mnt_opts=""},
|
|
|
522fea |
+ {.mnt_fsname="fsname", .mnt_dir="/", .mnt_opts=""},
|
|
|
522fea |
+ {.mnt_fsname="/fsname", .mnt_dir="/.", .mnt_opts=""},
|
|
|
522fea |
+ {.mnt_fsname="/fsname", .mnt_dir="/", .mnt_opts=""},
|
|
|
522fea |
+ {.mnt_fsname="virtfs", .mnt_dir="/NONROOT", .mnt_type="t1", .mnt_opts=""},
|
|
|
522fea |
+ {.mnt_fsname="virtfs2", .mnt_dir="/NONROOT", .mnt_type="t2", .mnt_opts=""},
|
|
|
522fea |
+ {.mnt_fsname="netns", .mnt_dir="net:[1234567]", .mnt_opts=""},
|
|
|
522fea |
+ {.mnt_fsname="rem:ote1",.mnt_dir="/REMOTE", .mnt_opts=""},
|
|
|
522fea |
+ {.mnt_fsname="rem:ote1",.mnt_dir="/REMOTE", .mnt_opts=""},
|
|
|
522fea |
+ {.mnt_fsname="rem:ote2",.mnt_dir="/REMOTE", .mnt_opts=""},
|
|
|
522fea |
};
|
|
|
522fea |
|
|
|
522fea |
- if (!getenv ("CU_TEST_DUPE_INVALID") && done == 1)
|
|
|
522fea |
+ if (done == 1)
|
|
|
522fea |
+ {
|
|
|
522fea |
+ nonroot_fs = getenv ("CU_NONROOT_FS");
|
|
|
522fea |
+ if (!nonroot_fs || !*nonroot_fs)
|
|
|
522fea |
+ nonroot_fs = "/"; /* merge into / entries. */
|
|
|
522fea |
+
|
|
|
522fea |
+ remote_fs = getenv ("CU_REMOTE_FS");
|
|
|
522fea |
+ }
|
|
|
522fea |
+
|
|
|
522fea |
+ if (done == 1 && !getenv ("CU_TEST_DUPE_INVALID"))
|
|
|
522fea |
done++; /* skip the first entry. */
|
|
|
522fea |
|
|
|
522fea |
- while (done++ <= 4)
|
|
|
522fea |
+ while (done++ <= 10)
|
|
|
522fea |
{
|
|
|
522fea |
- mntents[done-2].mnt_type = "-";
|
|
|
522fea |
+ if (!mntents[done-2].mnt_type)
|
|
|
522fea |
+ mntents[done-2].mnt_type = "-";
|
|
|
522fea |
+ if (!mntents[done-2].mnt_opts)
|
|
|
522fea |
+ mntents[done-2].mnt_opts = "-";
|
|
|
522fea |
+ if (STREQ (mntents[done-2].mnt_dir, "/NONROOT"))
|
|
|
522fea |
+ mntents[done-2].mnt_dir = nonroot_fs;
|
|
|
522fea |
+ if (STREQ (mntents[done-2].mnt_dir, "/REMOTE"))
|
|
|
522fea |
+ {
|
|
|
522fea |
+ if (!remote_fs || !*remote_fs)
|
|
|
522fea |
+ continue;
|
|
|
522fea |
+ else
|
|
|
522fea |
+ mntents[done-2].mnt_dir = remote_fs;
|
|
|
522fea |
+ }
|
|
|
522fea |
return &mntents[done-2];
|
|
|
522fea |
}
|
|
|
522fea |
+
|
|
|
522fea |
return NULL;
|
|
|
522fea |
}
|
|
|
522fea |
EOF
|
|
|
522fea |
|
|
|
522fea |
# Then compile/link it:
|
|
|
522fea |
-gcc --std=gnu99 -shared -fPIC -ldl -O2 k.c -o k.so \
|
|
|
522fea |
+gcc_shared_ k.c k.so \
|
|
|
522fea |
|| framework_failure_ 'failed to build shared library'
|
|
|
522fea |
|
|
|
522fea |
# Test if LD_PRELOAD works:
|
|
|
522fea |
-LD_PRELOAD=./k.so df
|
|
|
522fea |
+LD_PRELOAD=$LD_PRELOAD:./k.so df
|
|
|
522fea |
test -f x || skip_ "internal test failure: maybe LD_PRELOAD doesn't work?"
|
|
|
522fea |
|
|
|
522fea |
# The fake mtab file should only contain entries
|
|
|
522fea |
# having the same device number; thus the output should
|
|
|
522fea |
-# consist of a header and one entry.
|
|
|
522fea |
-LD_PRELOAD=./k.so df >out || fail=1
|
|
|
522fea |
-test $(wc -l
|
|
|
522fea |
+# consist of a header and unique entries.
|
|
|
522fea |
+LD_PRELOAD=$LD_PRELOAD:./k.so df -T >out || fail=1
|
|
|
522fea |
+test $(wc -l
|
|
|
998e46 |
|
|
|
998e46 |
-# Ensure we fail when unable to stat invalid entries
|
|
|
998e46 |
-LD_PRELOAD=./k.so CU_TEST_DUPE_INVALID=1 df >out && fail=1
|
|
|
998e46 |
-test $(wc -l
|
|
|
522fea |
+# With --total we should suppress the duplicate but separate remote file system
|
|
|
522fea |
+LD_PRELOAD=$LD_PRELOAD:./k.so df --total >out || fail=1
|
|
|
522fea |
+test "$CU_REMOTE_FS" && elide_remote=1 || elide_remote=0
|
|
|
522fea |
+test $(wc -l
|
|
|
522fea |
+ { fail=1; cat out; }
|
|
|
522fea |
+
|
|
|
522fea |
+# Ensure we don't fail when unable to stat (currently) unavailable entries
|
|
|
522fea |
+LD_PRELOAD=$LD_PRELOAD:./k.so CU_TEST_DUPE_INVALID=1 df -T >out || fail=1
|
|
|
522fea |
+test $(wc -l
|
|
|
522fea |
|
|
|
522fea |
# df should also prefer "/fsname" over "fsname"
|
|
|
522fea |
-test $(grep -c '/fsname'
|
|
|
522fea |
-# ... and "/fsname" with '/' as Mounted on over '/root'
|
|
|
522fea |
-test $(grep -c '/root'
|
|
|
522fea |
+if test "$unique_entries" = 2; then
|
|
|
522fea |
+ test $(grep -c '/fsname'
|
|
|
522fea |
+ # ... and "/fsname" with '/' as Mounted on over '/.'
|
|
|
522fea |
+ test $(grep -cF '/.'
|
|
|
522fea |
+fi
|
|
|
522fea |
+
|
|
|
522fea |
+# df should use the last seen devname (mnt_fsname) and devtype (mnt_type)
|
|
|
522fea |
+test $(grep -c 'virtfs2.*t2'
|
|
|
522fea |
|
|
|
522fea |
# Ensure that filtering duplicates does not affect -a processing.
|
|
|
522fea |
-LD_PRELOAD=./k.so df -a >out || fail=1
|
|
|
522fea |
-test $(wc -l
|
|
|
522fea |
+LD_PRELOAD=$LD_PRELOAD:./k.so df -a >out || fail=1
|
|
|
522fea |
+total_fs=6; test "$CU_REMOTE_FS" && total_fs=$(expr $total_fs + 3)
|
|
|
522fea |
+test $(wc -l
|
|
|
522fea |
+# Ensure placeholder "-" values used for the eclipsed "virtfs"
|
|
|
522fea |
+test $(grep -c 'virtfs *-'
|
|
|
522fea |
|
|
|
522fea |
# Ensure that filtering duplicates does not affect
|
|
|
522fea |
# argument processing (now without the fake getmntent()).
|
|
|
998e46 |
diff --git a/init.cfg b/init.cfg
|
|
|
998e46 |
index 360d4da..16f9813 100644
|
|
|
998e46 |
--- a/init.cfg
|
|
|
998e46 |
+++ b/init.cfg
|
|
|
522fea |
@@ -472,6 +472,18 @@ require_sparse_support_()
|
|
|
522fea |
fi
|
|
|
522fea |
}
|
|
|
522fea |
|
|
|
522fea |
+# Compile a shared lib using the GCC options for doing so.
|
|
|
522fea |
+# Pass input and output file as parameters respectively.
|
|
|
522fea |
+# Any other optional parmeters are passed to $CC.
|
|
|
522fea |
+gcc_shared_()
|
|
|
522fea |
+{
|
|
|
522fea |
+ local in=$1
|
|
|
522fea |
+ local out=$2
|
|
|
522fea |
+ shift 2 || return 1
|
|
|
522fea |
+
|
|
|
522fea |
+ $CC -Wall -shared --std=gnu99 -fPIC -O2 $* "$in" -o "$out" -ldl
|
|
|
522fea |
+}
|
|
|
522fea |
+
|
|
|
522fea |
# There are a myriad of ways to build shared libs,
|
|
|
522fea |
# so we only consider running tests requiring shared libs,
|
|
|
522fea |
# on platforms that support building them as follows.
|