From 0532ba1d8f875d97c3938bc8bd32e7e536f8d08f Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Wed, 14 Jul 2010 15:05:14 +0200 Subject: libmount: add mnt_tab_parse_mtab() Signed-off-by: Karel Zak --- shlibs/mount/src/fs.c | 1 + shlibs/mount/src/mount.h.in | 1 + shlibs/mount/src/mount.sym | 1 + shlibs/mount/src/mountP.h | 7 +++- shlibs/mount/src/tab.c | 2 + shlibs/mount/src/tab_parse.c | 90 ++++++++++++++++++++++++++++++++++++++++++++ shlibs/mount/src/utils.c | 13 +++++++ 7 files changed, 113 insertions(+), 2 deletions(-) (limited to 'shlibs/mount/src') 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 #include +#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[]) { -- cgit v1.2.3-55-g7522