From: Karel Zak Date: Thu, 30 Sep 2010 10:07:50 +0000 (+0200) Subject: libmount: always store rw/ro flags to mtab X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=04e83b1bda824e420de259e8db344375e1adc7fe;p=util-linux libmount: always store rw/ro flags to mtab Signed-off-by: Karel Zak --- diff --git a/shlibs/mount/src/optstr.c b/shlibs/mount/src/optstr.c index 626711c4..84ce0489 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; } }