summaryrefslogtreecommitdiffstats
path: root/shlibs/mount
diff options
context:
space:
mode:
authorKarel Zak2010-12-22 13:15:04 +0100
committerKarel Zak2011-01-03 12:28:48 +0100
commitf84fa6f7b98dd00ef6f196815b18590ca50c3528 (patch)
tree6b7c7f0a084ea242240c2fb0d9980e954ae24fcc /shlibs/mount
parenttests: check for mtab (diff)
downloadkernel-qcow2-util-linux-f84fa6f7b98dd00ef6f196815b18590ca50c3528.tar.gz
kernel-qcow2-util-linux-f84fa6f7b98dd00ef6f196815b18590ca50c3528.tar.xz
kernel-qcow2-util-linux-f84fa6f7b98dd00ef6f196815b18590ca50c3528.zip
libmount: better work with mtab options
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'shlibs/mount')
-rw-r--r--shlibs/mount/src/fs.c54
-rw-r--r--shlibs/mount/src/mount.h.in7
-rw-r--r--shlibs/mount/src/mount.sym2
-rw-r--r--shlibs/mount/src/mountP.h4
-rw-r--r--shlibs/mount/src/optmap.c2
-rw-r--r--shlibs/mount/src/optstr.c54
-rw-r--r--shlibs/mount/src/tab_parse.c2
-rw-r--r--shlibs/mount/src/tab_update.c44
-rw-r--r--shlibs/mount/src/utils.c8
9 files changed, 159 insertions, 18 deletions
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
@@ -146,6 +146,60 @@ err:
}
/**
+ * 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[=%<type>] (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;
}
@@ -514,6 +513,59 @@ int mnt_split_optstr(const char *optstr, char **user, char **vfs, char **fs,
}
/**
+ * 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
* @flags: returns mount flags
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