summaryrefslogtreecommitdiffstats
path: root/shlibs/mount/src/optstr.c
diff options
context:
space:
mode:
authorKarel Zak2010-09-30 12:07:50 +0200
committerKarel Zak2011-01-03 12:28:43 +0100
commit04e83b1bda824e420de259e8db344375e1adc7fe (patch)
treea008cfd9ef358aeda581eb6a36d93504e2d3fc29 /shlibs/mount/src/optstr.c
parentlibmount: update mount.sym (diff)
downloadkernel-qcow2-util-linux-04e83b1bda824e420de259e8db344375e1adc7fe.tar.gz
kernel-qcow2-util-linux-04e83b1bda824e420de259e8db344375e1adc7fe.tar.xz
kernel-qcow2-util-linux-04e83b1bda824e420de259e8db344375e1adc7fe.zip
libmount: always store rw/ro flags to mtab
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'shlibs/mount/src/optstr.c')
-rw-r--r--shlibs/mount/src/optstr.c67
1 files changed, 52 insertions, 15 deletions
diff --git a/shlibs/mount/src/optstr.c b/shlibs/mount/src/optstr.c
index 626711c48..84ce04896 100644
--- a/shlibs/mount/src/optstr.c
+++ b/shlibs/mount/src/optstr.c
@@ -248,7 +248,7 @@ int mnt_optstr_prepend_option(char **optstr, const char *name, const char *value
*optstr = NULL;
rc = mnt_optstr_append_option(optstr, name, value);
- if (!rc && tmp)
+ if (!rc && tmp && *tmp)
rc = mnt_optstr_append_option(optstr, tmp, NULL);
if (!rc) {
free(tmp);
@@ -629,22 +629,59 @@ int mnt_optstr_apply_flags(char **optstr, unsigned long flags,
next = *optstr;
fl = flags;
- /* scan @optstr and remove options that are missing in the @flags */
- while(!mnt_optstr_next_option(&next, &name, &namesz, &val, &valsz)) {
- const struct mnt_optmap *ent;
-
- if (mnt_optmap_get_entry(maps, 1, name, namesz, &ent)) {
+ /*
+ * There is convetion that 'rw/ro' flags is always at the begin of
+ * the string (athough the 'rw' is unnecessary).
+ */
+ if (map == mnt_get_builtin_optmap(MNT_LINUX_MAP)) {
+ const char *o = (fl & MS_RDONLY) ? "ro" : "rw";
+
+ if (next &&
+ (!strncmp(next, "rw", 2) || !strncmp(next, "ro", 2)) &&
+ (*(next + 2) == '\0' || *(next + 2) == ',')) {
+
+ /* already set, be paranoid and fix it */
+ memcpy(next, o, 2);
+ } else {
+ rc = mnt_optstr_prepend_option(optstr, o, NULL);
+ if (rc)
+ goto err;
+ next = *optstr; /* because realloc() */
+ }
+ fl &= ~MS_RDONLY;
+ next += 2;
+ if (*next == ',')
+ next++;
+ }
- /* remove unwanted option */
- if ((ent->mask & MNT_INVERT) || !(fl & ent->id)) {
- char *end = val ? val + valsz : name + namesz;
- next = name;
- rc = mnt_optstr_remove_option_at(optstr, name, end);
- if (rc)
- goto err;
+ if (next && *next) {
+ /*
+ * scan @optstr and remove options that are missing in
+ * the @flags
+ */
+ while(!mnt_optstr_next_option(&next, &name, &namesz,
+ &val, &valsz)) {
+ const struct mnt_optmap *ent;
+
+ if (mnt_optmap_get_entry(maps, 1, name, namesz, &ent)) {
+ /*
+ * remove unwanted option (rw/ro is already set)
+ */
+ if (ent->id == MS_RDONLY ||
+ (ent->mask & MNT_INVERT) ||
+ !(fl & ent->id)) {
+
+ char *end = val ? val + valsz :
+ name + namesz;
+ next = name;
+ rc = mnt_optstr_remove_option_at(
+ optstr, name, end);
+ if (rc)
+ goto err;
+ }
+ if (!(ent->mask & MNT_INVERT))
+ fl &= ~ent->id;
}
- if (!(ent->mask & MNT_INVERT))
- fl &= ~ent->id;
}
}