summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--misc-utils/findmnt.c2
-rw-r--r--shlibs/mount/src/fs.c1
-rw-r--r--shlibs/mount/src/mount.h.in1
-rw-r--r--shlibs/mount/src/mount.sym1
-rw-r--r--shlibs/mount/src/mountP.h7
-rw-r--r--shlibs/mount/src/tab.c2
-rw-r--r--shlibs/mount/src/tab_parse.c90
-rw-r--r--shlibs/mount/src/utils.c13
8 files changed, 115 insertions, 2 deletions
diff --git a/misc-utils/findmnt.c b/misc-utils/findmnt.c
index 76564f6b8..7314bb6e3 100644
--- a/misc-utils/findmnt.c
+++ b/misc-utils/findmnt.c
@@ -330,6 +330,8 @@ static mnt_tab *parse_tabfile(const char *path)
if (!strcmp(path, _PATH_MNTTAB))
rc = mnt_tab_parse_fstab(tb);
+ else if (!strcmp(path, _PATH_MOUNTED))
+ rc = mnt_tab_parse_mtab(tb);
else
rc = mnt_tab_parse_file(tb, path);
diff --git a/shlibs/mount/src/fs.c b/shlibs/mount/src/fs.c
index 8e51fd73d..0cd2eaa5b 100644
--- a/shlibs/mount/src/fs.c
+++ b/shlibs/mount/src/fs.c
@@ -381,6 +381,7 @@ int mnt_fs_append_optstr(mnt_fs *fs, const char *optstr)
if (!fs || !optstr)
return -1;
+
return mnt_optstr_append_option(&fs->optstr, optstr, NULL);
}
diff --git a/shlibs/mount/src/mount.h.in b/shlibs/mount/src/mount.h.in
index 402d8fc76..fcb4b4e5a 100644
--- a/shlibs/mount/src/mount.h.in
+++ b/shlibs/mount/src/mount.h.in
@@ -271,6 +271,7 @@ extern mnt_tab *mnt_new_tab_from_file(const char *filename);
extern int mnt_tab_parse_stream(mnt_tab *tb, FILE *f, const char *filename);
extern int mnt_tab_parse_file(mnt_tab *tb, const char *filename);
extern int mnt_tab_parse_fstab(mnt_tab *tb);
+extern int mnt_tab_parse_mtab(mnt_tab *tb);
extern int mnt_tab_set_parser_errcb(mnt_tab *tb,
int (*cb)(mnt_tab *tb, const char *filename, int line, int flag));
diff --git a/shlibs/mount/src/mount.sym b/shlibs/mount/src/mount.sym
index e5c1fcf96..14d9fbf4e 100644
--- a/shlibs/mount/src/mount.sym
+++ b/shlibs/mount/src/mount.sym
@@ -126,6 +126,7 @@ global:
mnt_tab_next_fs;
mnt_tab_parse_file;
mnt_tab_parse_fstab;
+ mnt_tab_parse_mtab;
mnt_tab_parse_stream;
mnt_tab_remove_fs;
mnt_tab_set_cache;
diff --git a/shlibs/mount/src/mountP.h b/shlibs/mount/src/mountP.h
index 04084e5d1..1de13917f 100644
--- a/shlibs/mount/src/mountP.h
+++ b/shlibs/mount/src/mountP.h
@@ -50,6 +50,10 @@ extern int libmount_debug_mask;
/* extension for files in the /etc/fstab.d directory */
#define MNT_MNTTABDIR_EXT ".fstab"
+/* library private paths */
+#define MNT_PATH_RUNDIR "/var/run/mount"
+#define MNT_PATH_MOUNTINFO MNT_PATH_RUNDIR "/mountinfo"
+
#ifdef TEST_PROGRAM
struct mtest {
const char *name;
@@ -64,6 +68,7 @@ extern int mnt_run_test(struct mtest *tests, int argc, char *argv[]);
/* utils.c */
extern char *mnt_getenv_safe(const char *arg);
extern char *mnt_get_username(const uid_t uid);
+extern int mnt_has_regular_mtab(void);
/*
* Generic iterator
@@ -206,6 +211,4 @@ extern int mnt_optent_assign_map(mnt_optent *op,
extern int __mnt_fs_set_source(mnt_fs *fs, char *source);
extern int __mnt_fs_set_fstype(mnt_fs *fs, char *fstype);
-
-
#endif /* _LIBMOUNT_PRIVATE_H */
diff --git a/shlibs/mount/src/tab.c b/shlibs/mount/src/tab.c
index 45e52e1b6..939e8c876 100644
--- a/shlibs/mount/src/tab.c
+++ b/shlibs/mount/src/tab.c
@@ -332,6 +332,8 @@ int mnt_tab_next_fs(mnt_tab *tb, mnt_iter *itr, mnt_fs **fs)
if (!tb || !itr || !fs)
return -1;
rc = 1;
+ *fs = NULL;
+
if (!itr->head)
MNT_ITER_INIT(itr, &tb->ents);
if (itr->p != itr->head) {
diff --git a/shlibs/mount/src/tab_parse.c b/shlibs/mount/src/tab_parse.c
index 06bb64862..dc3486d53 100644
--- a/shlibs/mount/src/tab_parse.c
+++ b/shlibs/mount/src/tab_parse.c
@@ -602,3 +602,93 @@ done:
return num > 0 ? 0 : -1;
}
+
+/*
+ * This function uses @uf to found corresponding record in @tb, then the record
+ * from @tb is updated (userspace specific mount options are added).
+ *
+ * Note that @uf must contain userspace specific mount options only!
+ *
+ * Returns: modified filesystem (from @tb) or NULL.
+ */
+static mnt_fs *mnt_tab_merge_userspace_fs(mnt_tab *tb, mnt_fs *uf)
+{
+ mnt_fs *fs;
+ mnt_iter itr;
+ const char *optstr, *src, *target, *root;
+
+ assert(tb);
+ assert(uf);
+ if (!tb || !uf)
+ return NULL;
+
+ src = mnt_fs_get_srcpath(uf);
+ target = mnt_fs_get_target(uf);
+ optstr = mnt_fs_get_vfs_optstr(uf);
+ root = mnt_fs_get_root(uf);
+
+ if (!src || !target || !optstr || !root)
+ return NULL;
+
+ mnt_reset_iter(&itr, MNT_ITER_BACKWARD);
+
+ while(mnt_tab_next_fs(tb, &itr, &fs) == 0) {
+ const char *s = mnt_fs_get_srcpath(fs),
+ *t = mnt_fs_get_target(fs),
+ *r = mnt_fs_get_root(fs);
+
+ if (s && t && r && !strcmp(t, target) &&
+ !strcmp(s, src) && !strcmp(r, root))
+ break;
+ }
+
+ if (fs)
+ mnt_fs_append_optstr(fs, optstr);
+ return fs;
+}
+
+/**
+ * mnt_tab_parse_mtab:
+ * @tb: table
+ *
+ * This function parses /etc/mtab or {/proc/self,/var/run/mount}/mountinfo or
+ * /proc/mounts. Note that the /var/run/mount/mountinfo file is optional and
+ * contains userspace specific mount options only.
+ *
+ * See also mnt_tab_set_parser_errcb().
+ *
+ * Returns: 0 on success or -1 in case of error.
+ */
+int mnt_tab_parse_mtab(mnt_tab *tb)
+{
+ int rc;
+ mnt_tab *u_tb;
+ mnt_fs *u_fs;
+ mnt_iter itr;
+
+ if (mnt_has_regular_mtab()) {
+ rc = mnt_tab_parse_file(tb, _PATH_MOUNTED);
+ if (!rc)
+ return 0; /* system with regular mtab */
+ }
+
+ /* read kernel information from /proc/self/mountinfo */
+ rc = mnt_tab_parse_file(tb, _PATH_PROC_MOUNTINFO);
+ if (rc)
+ /* hmm, old kernel? ...try /proc/mounts */
+ return mnt_tab_parse_file(tb, _PATH_PROC_MOUNTS);
+
+ /* try to read userspace specific information from /var/run/mount */
+ u_tb = mnt_new_tab_from_file(MNT_PATH_MOUNTINFO);
+ if (!u_tb)
+ return 0; /* private mountinfo does not exist */
+
+ mnt_reset_iter(&itr, MNT_ITER_BACKWARD);
+
+ /* merge userspace options into mountinfo from kernel */
+ while(mnt_tab_next_fs(u_tb, &itr, &u_fs) == 0)
+ mnt_tab_merge_userspace_fs(tb, u_fs);
+
+ mnt_free_tab(u_tb);
+ return 0;
+}
diff --git a/shlibs/mount/src/utils.c b/shlibs/mount/src/utils.c
index a1ab50c08..9bdd62ade 100644
--- a/shlibs/mount/src/utils.c
+++ b/shlibs/mount/src/utils.c
@@ -28,6 +28,7 @@
#include <fcntl.h>
#include <pwd.h>
+#include "pathnames.h"
#include "mountP.h"
char *mnt_getenv_safe(const char *arg)
@@ -249,6 +250,18 @@ char *mnt_get_username(const uid_t uid)
return username;
}
+/*
+ * Returns 1 if /etc/mtab is a reqular file.
+ */
+int mnt_has_regular_mtab(void)
+{
+ struct stat st;
+
+ if (lstat(_PATH_MOUNTED, &st) == 0 && S_ISREG(st.st_mode))
+ return 1;
+ return 0;
+}
+
#ifdef TEST_PROGRAM
int test_match_fstype(struct mtest *ts, int argc, char *argv[])
{