summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog13
-rw-r--r--DEPENDENCIES7
-rw-r--r--lib/mountlist.c82
-rw-r--r--m4/ls-mntd-fs.m415
4 files changed, 96 insertions, 21 deletions
diff --git a/ChangeLog b/ChangeLog
index 48e0b17ab6..7b8202f206 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2014-09-09 Fridolin Pokorny <fpokorny@redhat.com>
+
+ mountlist: use /proc/self/mountinfo when available
+ Use libmount to propagate device IDs provided by Linux in
+ /proc/self/mountinfo. This will give more accurate output when
+ using df in chroot'ed environments as the device IDs are not
+ determined by stat() which may be inaccurate within the chroot.
+ * lib/mountlist.c (read_file_system_list): Use the libmount routines
+ from util-linux to parse "/proc/self/mountinfo" or fall back to
+ standard getmntent() processing.
+ * m4/ls-mntd-fs.m4: Check for libmount only when 1-argument
+ getmntent() is used, as is the case on GNU/Linux.
+
2014-09-07 Eric Wong <normalperson@yhbt.net>
users.txt: add cmogstored
diff --git a/DEPENDENCIES b/DEPENDENCIES
index e19a37e7a7..44f7ca04df 100644
--- a/DEPENDENCIES
+++ b/DEPENDENCIES
@@ -162,3 +162,10 @@ at any time.
+ Download:
http://ftp.gnu.org/gnu/libtool/
ftp://ftp.gnu.org/gnu/libtool/
+
+* util-linux
+ + Optional.
+ Needed if you want to support /proc/self/mountinfo available on Linux.
+ This will give an ability to propagate device ID of a mounted file system.
+ + Download:
+ http://www.kernel.org/pub/linux/utils/util-linux/
diff --git a/lib/mountlist.c b/lib/mountlist.c
index b3be011a1b..84dc2c8cc0 100644
--- a/lib/mountlist.c
+++ b/lib/mountlist.c
@@ -128,6 +128,12 @@
# include <sys/mntent.h>
#endif
+#ifdef MOUNTED_PROC_MOUNTINFO
+/* Use /proc/self/mountinfo instead of /proc/self/mounts (/etc/mtab)
+ * on Linux, if available */
+# include <libmount/libmount.h>
+#endif
+
#ifndef HAVE_HASMNTOPT
# define hasmntopt(mnt, opt) ((char *) 0)
#endif
@@ -429,32 +435,68 @@ read_file_system_list (bool need_fs_type)
#ifdef MOUNTED_GETMNTENT1 /* GNU/Linux, 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
{
- struct mntent *mnt;
- char const *table = MOUNTED;
- FILE *fp;
+#ifdef MOUNTED_PROC_MOUNTINFO
+ struct libmnt_table *fstable = NULL;
- fp = setmntent (table, "r");
- if (fp == NULL)
- return NULL;
+ fstable = mnt_new_table_from_file ("/proc/self/mountinfo");
- while ((mnt = getmntent (fp)))
+ if (fstable != NULL)
{
- me = xmalloc (sizeof *me);
- me->me_devname = xstrdup (mnt->mnt_fsname);
- me->me_mountdir = xstrdup (mnt->mnt_dir);
- me->me_type = xstrdup (mnt->mnt_type);
- me->me_type_malloced = 1;
- me->me_dummy = ME_DUMMY (me->me_devname, me->me_type, mnt);
- me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
- me->me_dev = dev_from_mount_options (mnt->mnt_opts);
+ struct libmnt_fs *fs;
+ struct libmnt_iter *iter;
- /* Add to the linked list. */
- *mtail = me;
- mtail = &me->me_next;
+ iter = mnt_new_iter (MNT_ITER_FORWARD);
+
+ while (iter && mnt_table_next_fs (fstable, iter, &fs) == 0)
+ {
+ me = xmalloc (sizeof *me);
+
+ me->me_devname = xstrdup (mnt_fs_get_source (fs));
+ me->me_mountdir = xstrdup (mnt_fs_get_target (fs));
+ me->me_type = xstrdup (mnt_fs_get_fstype (fs));
+ me->me_type_malloced = 1;
+ me->me_dev = mnt_fs_get_devno (fs);
+ me->me_dummy = mnt_fs_is_pseudofs (fs);
+ me->me_remote = mnt_fs_is_netfs (fs);
+
+ /* Add to the linked list. */
+ *mtail = me;
+ mtail = &me->me_next;
+ }
+
+ mnt_free_iter (iter);
+ mnt_free_table (fstable);
}
+ else /* fallback to /proc/self/mounts (/etc/mtab) if anything failed */
+#endif /* MOUNTED_PROC_MOUNTINFO */
+ {
+ FILE * fp;
+ struct mntent *mnt;
+ char const *table = MOUNTED;
- if (endmntent (fp) == 0)
- goto free_then_fail;
+ fp = setmntent (table, "r");
+ if (fp == NULL)
+ return NULL;
+
+ while ((mnt = getmntent (fp)))
+ {
+ me = xmalloc (sizeof *me);
+ me->me_devname = xstrdup (mnt->mnt_fsname);
+ me->me_mountdir = xstrdup (mnt->mnt_dir);
+ me->me_type = xstrdup (mnt->mnt_type);
+ me->me_type_malloced = 1;
+ me->me_dummy = ME_DUMMY (me->me_devname, me->me_type, mnt);
+ me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
+ me->me_dev = dev_from_mount_options (mnt->mnt_opts);
+
+ /* Add to the linked list. */
+ *mtail = me;
+ mtail = &me->me_next;
+ }
+
+ if (endmntent (fp) == 0)
+ goto free_then_fail;
+ }
}
#endif /* MOUNTED_GETMNTENT1. */
diff --git a/m4/ls-mntd-fs.m4 b/m4/ls-mntd-fs.m4
index 563ed71cbe..9e46ccccaa 100644
--- a/m4/ls-mntd-fs.m4
+++ b/m4/ls-mntd-fs.m4
@@ -1,4 +1,4 @@
-# serial 30
+# serial 31
# How to list mounted file systems.
# Copyright (C) 1998-2004, 2006, 2009-2014 Free Software Foundation, Inc.
@@ -152,6 +152,19 @@ if test $ac_cv_func_getmntent = yes; then
of mounted file systems, and that function takes a single argument.
(4.3BSD, SunOS, HP-UX, Dynix, Irix)])
AC_CHECK_FUNCS([hasmntopt])
+
+ # Check for libmount to support /proc/self/mountinfo on Linux
+ AC_CACHE_VAL([ac_cv_lib_libmount_mnt_table_parse_stream],
+ [AC_CHECK_LIB([mount], [mnt_new_table_from_file],
+ ac_cv_lib_mount_mnt_table_parse_stream=yes,
+ ac_cv_lib_mount_mnt_table_parse_stream=no)])
+ if test $ac_cv_lib_mount_mnt_table_parse_stream = yes; then
+ AC_DEFINE([MOUNTED_PROC_MOUNTINFO], [1],
+ [Define if want to use /proc/self/mountinfo on Linux.])
+ LIBS="-lmount $LIBS"
+ elif test -f /proc/self/mountinfo; then
+ AC_MSG_WARN([/proc/self/mountinfo present but libmount is missing.])
+ fi
fi
fi