diff options
author | Karel Zak <kzak@redhat.com> | 2010-04-16 14:05:42 +0200 |
---|---|---|
committer | Karel Zak <kzak@redhat.com> | 2010-06-03 15:20:12 +0200 |
commit | 6b5f7bd16386cce8ba59df8991d5e3cbee9acdc0 (patch) | |
tree | 22997d62a30afd59bc46125c89f77dd00770bb6d | |
parent | 3d73558960025f6bd18fd8b05986e021e5159df2 (diff) | |
download | util-linux-old-6b5f7bd16386cce8ba59df8991d5e3cbee9acdc0.tar.gz |
libmount: merge vfs and fs options more carefully
Signed-off-by: Karel Zak <kzak@redhat.com>
-rw-r--r-- | shlibs/mount/src/tab_parse.c | 54 |
1 files changed, 31 insertions, 23 deletions
diff --git a/shlibs/mount/src/tab_parse.c b/shlibs/mount/src/tab_parse.c index fe2b1103..e103aad8 100644 --- a/shlibs/mount/src/tab_parse.c +++ b/shlibs/mount/src/tab_parse.c @@ -248,21 +248,26 @@ static int detect_fmt(char *line) /* - * Merges @vfs and @fs options strings into a new string - * This function skips the generic part of @fs options. - * For example (see "rw"): + * Merges @vfs and @fs options strings into a new string. + * This function cares about 'ro/rw' options. The 'ro' is + * always used if @vfs or @fs is read-only. + * For example: * - * mnt_merge_optstr("rw,noexec", "rw,journal=update") + * mnt_merge_optstr("rw,noexec", "ro,journal=update") + * + * returns: "ro,noexec,journal=update" * - * returns --> "rw,noexec,journal=update" + * mnt_merge_optstr("rw,noexec", "rw,journal=update") * + * returns: "rw,noexec,journal=update" + * We need this function for /proc/self/mountinfo parsing. */ static char *merge_optstr(const char *vfs, const char *fs) { - const char *p1 = vfs, *p2 = fs; - char *res; + char *res, *p; size_t sz; + int ro = 0, rw = 0; if (!vfs && !fs) return NULL; @@ -271,26 +276,29 @@ static char *merge_optstr(const char *vfs, const char *fs) if (!strcmp(vfs, fs)) return strdup(vfs); /* e.g. "aaa" and "aaa" */ - /* skip the same FS options */ - while (*p1 && *p2 && *++p1 == *++p2); - - if (*p1 == ',') - p1++; - if (*p2 == ',') - p2++; - if (!*p1 && !*p2) /* e.g. "aaa,bbb" and "aaa,bbb," */ - return strdup(vfs); - if (!*p1 || !*p2) /* e.g. "aaa" and "aaa,bbb" */ - return strdup(*p1 ? vfs : fs); - - p1 = vfs; - sz = strlen(p1) + strlen(p2) + 2; /* 2= separator + '\0' */ - + sz = strlen(vfs) + strlen(fs) + 2; res = malloc(sz); if (!res) return NULL; + p = res + 3; /* make a room for rw/ro flag */ + + snprintf(p, sz - 3, "%s,%s", vfs, fs); + + /* remove 'rw' flags */ + rw += !mnt_optstr_remove_option(&p, "rw"); /* from vfs */ + rw += !mnt_optstr_remove_option(&p, "rw"); /* from fs */ - snprintf(res, sz, "%s,%s", p1, p2); + /* remove 'ro' flags if necessary */ + if (rw != 2) { + ro += !mnt_optstr_remove_option(&p, "ro"); + if (ro + rw < 2) + ro += !mnt_optstr_remove_option(&p, "ro"); + } + + if (!strlen(p)) + memcpy(res, ro ? "ro" : "rw", 3); + else + memcpy(res, ro ? "ro," : "rw,", 3); return res; } |