From f84fa6f7b98dd00ef6f196815b18590ca50c3528 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Wed, 22 Dec 2010 13:15:04 +0100 Subject: libmount: better work with mtab options Signed-off-by: Karel Zak --- shlibs/mount/src/fs.c | 54 +++++++++++++++++++++++++++++++++++++++++++ shlibs/mount/src/mount.h.in | 7 +++++- shlibs/mount/src/mount.sym | 2 +- shlibs/mount/src/mountP.h | 4 ++-- shlibs/mount/src/optmap.c | 2 +- shlibs/mount/src/optstr.c | 54 ++++++++++++++++++++++++++++++++++++++++++- shlibs/mount/src/tab_parse.c | 2 +- shlibs/mount/src/tab_update.c | 44 ++++++++++++++++++++++++++++------- shlibs/mount/src/utils.c | 8 ++++--- 9 files changed, 159 insertions(+), 18 deletions(-) (limited to 'shlibs/mount') diff --git a/shlibs/mount/src/fs.c b/shlibs/mount/src/fs.c index 94c353558..21e02f3df 100644 --- a/shlibs/mount/src/fs.c +++ b/shlibs/mount/src/fs.c @@ -145,6 +145,60 @@ err: return NULL; } +/** + * mnt_copy_mtab_fs: + * @fs: filesystem + * + * This function copies all @fs description except information that does not + * belong to /etc/mtab (e.g. VFS and userspace mount options with MNT_NOMTAB + * mask). + * + * Returns: copy of @fs. + */ +mnt_fs *mnt_copy_mtab_fs(const mnt_fs *fs) +{ + mnt_fs *n = mnt_new_fs(); + + if (!n) + return NULL; + + if (cpy_str_at_offset(n, fs, offsetof(struct _mnt_fs, source))) + goto err; + if (cpy_str_at_offset(n, fs, offsetof(struct _mnt_fs, target))) + goto err; + if (cpy_str_at_offset(n, fs, offsetof(struct _mnt_fs, fstype))) + goto err; + + if (fs->vfs_optstr) { + char *p = NULL; + mnt_optstr_get_options(fs->vfs_optstr, &p, + mnt_get_builtin_optmap(MNT_LINUX_MAP), + MNT_NOMTAB); + n->vfs_optstr = p; + } + + if (fs->user_optstr) { + char *p = NULL; + mnt_optstr_get_options(fs->user_optstr, &p, + mnt_get_builtin_optmap(MNT_USERSPACE_MAP), + MNT_NOMTAB); + n->user_optstr = p; + } + + if (cpy_str_at_offset(n, fs, offsetof(struct _mnt_fs, fs_optstr))) + goto err; + + n->freq = fs->freq; + n->passno = fs->passno; + n->flags = fs->flags; + + return n; +err: + mnt_free_fs(n); + return NULL; + +} + /** * mnt_fs_get_userdata: * @fs: mnt_file instance diff --git a/shlibs/mount/src/mount.h.in b/shlibs/mount/src/mount.h.in index e0212fa51..76d66aaad 100644 --- a/shlibs/mount/src/mount.h.in +++ b/shlibs/mount/src/mount.h.in @@ -65,7 +65,7 @@ struct mnt_optmap { const char *name; /* option name[=%] (e.g. "loop[=%s]") */ int id; /* option ID or MS_* flags (e.g MS_RDONLY) */ - int mask; /* MNT_{MFLAG,MDATA,INVMASK,...} mask */ + int mask; /* MNT_{NOMTAB,INVERT,...} mask */ }; /* @@ -167,6 +167,9 @@ extern int mnt_split_optstr(const char *optstr, char **user, char **vfs, char **fs, int ifnore_user, int ignore_vfs); +extern int mnt_optstr_get_options(const char *optstr, char **subset, + const struct mnt_optmap *map, int ignore); + extern int mnt_optstr_get_flags(const char *optstr, unsigned long *flags, const struct mnt_optmap *map); extern int mnt_optstr_apply_flags(char **optstr, unsigned long flags, @@ -204,6 +207,7 @@ extern int mnt_lock_file(mnt_lock *ml); extern mnt_fs *mnt_new_fs(void); extern void mnt_free_fs(mnt_fs *ent); extern mnt_fs *mnt_copy_fs(const mnt_fs *fs); +extern mnt_fs *mnt_copy_mtab_fs(const mnt_fs *fs); extern void *mnt_fs_get_userdata(mnt_fs *fs); extern int mnt_fs_set_userdata(mnt_fs *fs, void *data); extern const char *mnt_fs_get_source(mnt_fs *ent); @@ -314,6 +318,7 @@ extern int mnt_update_tab(mnt_update *upd, mnt_lock *lc); extern unsigned long mnt_update_get_mountflags(mnt_update *upd); extern int mnt_update_force_rdonly(mnt_update *upd, int rdonly); extern const char *mnt_update_get_filename(mnt_update *upd); +extern mnt_fs *mnt_update_get_fs(mnt_update *upd); /* context.c */ diff --git a/shlibs/mount/src/mount.sym b/shlibs/mount/src/mount.sym index 7890a1403..3d2475ba1 100644 --- a/shlibs/mount/src/mount.sym +++ b/shlibs/mount/src/mount.sym @@ -136,7 +136,7 @@ global: mnt_update_get_mountflags; mnt_update_force_rdonly; mnt_update_get_filename; - + mnt_update_get_fs; local: *; }; diff --git a/shlibs/mount/src/mountP.h b/shlibs/mount/src/mountP.h index 3403ab705..fe6ea5698 100644 --- a/shlibs/mount/src/mountP.h +++ b/shlibs/mount/src/mountP.h @@ -84,8 +84,8 @@ mnt_debug_h(void *handler, const char *mesg, ...) } #else /* !CONFIG_LIBMOUNT_DEBUG */ -# define DBG(m,x) -# define DBG_FLUSH +# define DBG(m,x) do { ; } while(0) +# define DBG_FLUSH do { ; } while(0) #endif /* extension for files in the /etc/fstab.d directory */ diff --git a/shlibs/mount/src/optmap.c b/shlibs/mount/src/optmap.c index d5f641096..38256b09d 100644 --- a/shlibs/mount/src/optmap.c +++ b/shlibs/mount/src/optmap.c @@ -99,7 +99,7 @@ static const struct mnt_optmap linux_flags_map[] = { "async", MS_SYNCHRONOUS, MNT_INVERT },/* asynchronous I/O */ { "dirsync", MS_DIRSYNC }, /* synchronous directory modifications */ - { "remount", MS_REMOUNT }, /* Alter flags of mounted FS */ + { "remount", MS_REMOUNT, MNT_NOMTAB }, /* alter flags of mounted FS */ { "bind", MS_BIND }, /* Remount part of tree elsewhere */ { "rbind", MS_BIND | MS_REC }, /* Idem, plus mounted subtrees */ #ifdef MS_NOSUB diff --git a/shlibs/mount/src/optstr.c b/shlibs/mount/src/optstr.c index 62c5701dd..7c41f6857 100644 --- a/shlibs/mount/src/optstr.c +++ b/shlibs/mount/src/optstr.c @@ -147,7 +147,6 @@ static int mnt_optstr_locate_option(char *optstr, const char *name, } } while(1); - DBG(OPTIONS, mnt_debug("can't found '%s' option", name)); return rc; } @@ -513,6 +512,59 @@ int mnt_split_optstr(const char *optstr, char **user, char **vfs, char **fs, return 0; } +/** + * mnt_optstr_get_options + * @optstr: string with comma separated list of options + * @subset: returns newly allocated string with options + * @map: options map + * @ignore: mask of the options that should be ignored + * + * Extracts options from @optstr that belongs to the @map, for example: + * + * mnt_split_optstr_by_map(optstr, &p, + * mnt_get_builtin_optmap(MNT_LINUX_MAP), + * MNT_NOMTAB); + * + * returns all VFS options, the options that does not belong to mtab + * are ignored. + * + * Returns: 0 on success, or negative number in case of error. + */ +int mnt_optstr_get_options(const char *optstr, char **subset, + const struct mnt_optmap *map, int ignore) +{ + struct mnt_optmap const *maps[1]; + char *name, *val, *str = (char *) optstr; + size_t namesz, valsz; + + if (!optstr || !subset) + return -EINVAL; + + maps[0] = map; + *subset = NULL; + + while(!mnt_optstr_next_option(&str, &name, &namesz, &val, &valsz)) { + int rc = 0; + const struct mnt_optmap *ent; + + mnt_optmap_get_entry(maps, 1, name, namesz, &ent); + + if (!ent || !ent->id) + continue; /* ignore undefined options (comments) */ + + if (ignore && (ent->mask & ignore)) + continue; + rc = __mnt_optstr_append_option(subset, name, namesz, val, valsz); + if (rc) { + free(*subset); + return rc; + } + } + + return 0; +} + + /** * mnt_optstr_get_flags: * @optstr: string with comma separated list of options diff --git a/shlibs/mount/src/tab_parse.c b/shlibs/mount/src/tab_parse.c index a6c14ffff..335f703aa 100644 --- a/shlibs/mount/src/tab_parse.c +++ b/shlibs/mount/src/tab_parse.c @@ -469,7 +469,7 @@ mnt_tab *__mnt_new_tab_from_file(const char *filename, int fmt) if (!filename) return NULL; - if (stat(filename, &st) || st.st_size == 0) + if (stat(filename, &st)) return NULL; tb = mnt_new_tab(); if (tb) { diff --git a/shlibs/mount/src/tab_update.c b/shlibs/mount/src/tab_update.c index 603b6689c..986eff8e9 100644 --- a/shlibs/mount/src/tab_update.c +++ b/shlibs/mount/src/tab_update.c @@ -201,9 +201,10 @@ int mnt_update_set_fs(mnt_update *upd, unsigned long mountflags, if (rc) return rc; } else { - upd->fs = mnt_copy_fs(fs); + upd->fs = mnt_copy_mtab_fs(fs); if (!upd->fs) return -ENOMEM; + } } @@ -214,7 +215,10 @@ int mnt_update_set_fs(mnt_update *upd, unsigned long mountflags, } /** - * Returns update filesystem or NULL + * mnt_update_get_fs: + * @upd: update + * + * Returns: update filesystem entry or NULL */ mnt_fs *mnt_update_get_fs(mnt_update *upd) { @@ -283,6 +287,7 @@ static int utab_new_entry(mnt_fs *fs, unsigned long mountflags, mnt_fs **ent) { int rc = 0; const char *o = NULL, *a = NULL; + char *u = NULL; assert(fs); assert(ent); @@ -297,8 +302,19 @@ static int utab_new_entry(mnt_fs *fs, unsigned long mountflags, mnt_fs **ent) o = mnt_fs_get_userspace_options(fs); a = mnt_fs_get_attributes(fs); - if (!o && !a) - return 1; /* don't have mount options */ + if (o) { + /* remove non-mtab options */ + rc = mnt_optstr_get_options(o, &u, + mnt_get_builtin_optmap(MNT_USERSPACE_MAP), + MNT_NOMTAB); + if (rc) + goto err; + } + + if (!u && !a) { + DBG(UPDATE, mnt_debug("utab entry unnecessary (no options)")); + return 1; + } /* allocate the entry */ *ent = mnt_copy_fs(fs); @@ -307,7 +323,7 @@ static int utab_new_entry(mnt_fs *fs, unsigned long mountflags, mnt_fs **ent) goto err; } - rc = mnt_fs_set_userspace_options(*ent, o); + rc = mnt_fs_set_userspace_options(*ent, u); if (rc) goto err; rc = mnt_fs_set_attributes(*ent, a); @@ -320,10 +336,12 @@ static int utab_new_entry(mnt_fs *fs, unsigned long mountflags, mnt_fs **ent) goto err; } + free(u); DBG(UPDATE, mnt_debug("utab entry OK")); return 0; err: mnt_free_fs(*ent); + free(u); *ent = NULL; return rc; } @@ -349,6 +367,8 @@ static int set_fs_root(mnt_fs *result, mnt_fs *fs, unsigned long mountflags) const char *src, *src_root; mnt_fs *src_fs; + DBG(UPDATE, mnt_debug("setting FS root: bind")); + src = mnt_fs_get_srcpath(fs); if (src) { rc = mnt_fs_set_bindsrc(result, src); @@ -363,11 +383,15 @@ static int set_fs_root(mnt_fs *result, mnt_fs *fs, unsigned long mountflags) root = mnt_get_fs_root(src, mnt); tb = __mnt_new_tab_from_file(_PATH_PROC_MOUNTINFO, MNT_FMT_MOUNTINFO); - if (!tb) + if (!tb) { + DBG(UPDATE, mnt_debug("failed to parse mountinfo -- using default")); goto dflt; + } src_fs = mnt_tab_find_target(tb, mnt, MNT_ITER_BACKWARD); - if (!src_fs) + if (!src_fs) { + DBG(UPDATE, mnt_debug("not found '%s' in mountinfo -- using default", mnt)); goto dflt; + } /* set device name and fs */ src = mnt_fs_get_srcpath(src_fs); @@ -405,6 +429,8 @@ static int set_fs_root(mnt_fs *result, mnt_fs *fs, unsigned long mountflags) if (mnt_fs_get_option(fs, "subvol", &vol, &volsz)) goto dflt; + DBG(UPDATE, mnt_debug("setting FS root: btrfs subvol")); + sz = volsz; if (*vol != '/') sz++; @@ -762,7 +788,9 @@ int mnt_update_tab(mnt_update *upd, mnt_lock *lc) return 0; DBG(UPDATE, mnt_debug_h(upd, "%s: update tab", upd->filename)); - DBG(UPDATE, mnt_fs_print_debug(upd->fs, stderr)); + if (upd->fs) { + DBG(UPDATE, mnt_fs_print_debug(upd->fs, stderr)); + } if (!upd->fs && upd->target) rc = update_remove_entry(upd, lc); /* umount */ diff --git a/shlibs/mount/src/utils.c b/shlibs/mount/src/utils.c index 96ce7ddb1..ff3c90cdb 100644 --- a/shlibs/mount/src/utils.c +++ b/shlibs/mount/src/utils.c @@ -722,7 +722,7 @@ char *mnt_get_mountpoint(const char *path) memcpy(mnt, "/", 2); done: - DBG(UTILS, mnt_debug("fs-root for %s is %s", path, mnt)); + DBG(UTILS, mnt_debug("%s mountpoint is %s", path, mnt)); return mnt; err: free(mnt); @@ -731,7 +731,7 @@ err: char *mnt_get_fs_root(const char *path, const char *mnt) { - char *m = (char *) mnt; + char *m = (char *) mnt, *res; const char *p; size_t sz; @@ -746,7 +746,9 @@ char *mnt_get_fs_root(const char *path, const char *mnt) if (m != mnt) free(m); - return *p ? strdup(p) : strdup("/"); + res = *p ? strdup(p) : strdup("/"); + DBG(UTILS, mnt_debug("%s fs-root is %s", path, res)); + return res; } #ifdef TEST_PROGRAM -- cgit v1.2.3-55-g7522