Mercurial > gnulib
diff lib/mountlist.c @ 17756:326ae329c003
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.
* DEPENDENCIES: Mention the optional util-linux dependency.
author | Fridolin Pokorny <fpokorny@redhat.com> |
---|---|
date | Wed, 27 Aug 2014 15:25:30 +0200 |
parents | 5a079c01ad79 |
children | f8a2b0c3de24 |
line wrap: on
line diff
--- a/lib/mountlist.c Sun Sep 07 03:22:12 2014 +0000 +++ b/lib/mountlist.c Wed Aug 27 15:25:30 2014 +0200 @@ -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 @@ #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; + + 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; + } - /* 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. */