From 12fac096ed47fcbde2bf3732a849992400df6e55 Mon Sep 17 00:00:00 2001 From: Andrew Borodin Date: Sun, 21 Sep 2014 16:53:32 +0400 Subject: [PATCH] Sync with gnulib 3ea43e02541ece750ffc6cd1dfe34195421b4ef3. 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. Signed-off-by: Andrew Borodin --- m4.include/ls-mntd-fs.m4 | 13 ++++++ src/filemanager/mountlist.c | 83 ++++++++++++++++++++++++++++--------- 2 files changed, 76 insertions(+), 20 deletions(-) diff --git a/m4.include/ls-mntd-fs.m4 b/m4.include/ls-mntd-fs.m4 index 466f89af7..c29f0aa23 100644 --- a/m4.include/ls-mntd-fs.m4 +++ b/m4.include/ls-mntd-fs.m4 @@ -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 diff --git a/src/filemanager/mountlist.c b/src/filemanager/mountlist.c index 41b3522f9..e2306f6be 100644 --- a/src/filemanager/mountlist.c +++ b/src/filemanager/mountlist.c @@ -157,6 +157,12 @@ #include #endif +#ifdef MOUNTED_PROC_MOUNTINFO +/* Use /proc/self/mountinfo instead of /proc/self/mounts (/etc/mtab) + * on Linux, if available */ +#include +#endif + #ifndef HAVE_HASMNTOPT #define hasmntopt(mnt, opt) ((char *) 0) #endif @@ -653,32 +659,69 @@ read_file_system_list (int need_fs_type) #ifdef MOUNTED_GETMNTENT1 /* GNU/Linux, 4.3BSD, SunOS, HP-UX, Dynix, Irix. */ { - struct mntent *mnt; - const char *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 = g_malloc (sizeof (*me)); - me->me_devname = g_strdup (mnt->mnt_fsname); - me->me_mountdir = g_strdup (mnt->mnt_dir); - me->me_type = g_strdup (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; + + iter = mnt_new_iter (MNT_ITER_FORWARD); + + while (iter && mnt_table_next_fs (fstable, iter, &fs) == 0) + { + me = g_malloc (sizeof *me); + + me->me_devname = g_strdup (mnt_fs_get_source (fs)); + me->me_mountdir = g_strdup (mnt_fs_get_target (fs)); + me->me_type = g_strdup (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); - /* Add to the linked list. */ - *mtail = me; - mtail = &me->me_next; } + else /* fallback to /proc/self/mounts (/etc/mtab) if anything failed */ +#endif /* MOUNTED_PROC_MOUNTINFO */ + { + FILE *fp; + struct mntent *mnt; + const char *table = MOUNTED; - if (endmntent (fp) == 0) - goto free_then_fail; + fp = setmntent (table, "r"); + if (fp == NULL) + return NULL; + + while ((mnt = getmntent (fp))) + { + me = g_malloc (sizeof (*me)); + me->me_devname = g_strdup (mnt->mnt_fsname); + me->me_mountdir = g_strdup (mnt->mnt_dir); + me->me_type = g_strdup (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. */