diff options
Diffstat (limited to 'libmount/src/optstr.c')
-rw-r--r-- | libmount/src/optstr.c | 130 |
1 files changed, 108 insertions, 22 deletions
diff --git a/libmount/src/optstr.c b/libmount/src/optstr.c index e86b962..7ebc295 100644 --- a/libmount/src/optstr.c +++ b/libmount/src/optstr.c @@ -43,13 +43,16 @@ struct libmnt_optloc { * Locates the first option that matches @name. The @end is set to the * char behind the option (it means ',' or \0). * + * @ol is optional. + * * Returns negative number on parse error, 1 when not found and 0 on success. */ -static int mnt_optstr_locate_option(char *optstr, const char *name, +static int mnt_optstr_locate_option(char *optstr, + const char *name, size_t namesz, struct libmnt_optloc *ol) { char *n; - size_t namesz, nsz; + size_t nsz; int rc; if (!optstr) @@ -57,27 +60,30 @@ static int mnt_optstr_locate_option(char *optstr, const char *name, assert(name); - namesz = strlen(name); + if (!namesz) + namesz = strlen(name); if (!namesz) return 1; do { rc = ul_optstr_next(&optstr, &n, &nsz, - &ol->value, &ol->valsz); + ol ? &ol->value : NULL, + ol ? &ol->valsz : NULL); if (rc) break; if (namesz == nsz && strncmp(n, name, nsz) == 0) { - ol->begin = n; - ol->end = *(optstr - 1) == ',' ? optstr - 1 : optstr; - ol->namesz = nsz; + if (ol) { + ol->begin = n; + ol->end = *(optstr - 1) == ',' ? optstr - 1 : optstr; + ol->namesz = nsz; + } return 0; } } while(1); return rc; } - /** * mnt_optstr_next_option: * @optstr: option string, returns the position of the next option @@ -223,7 +229,7 @@ int mnt_optstr_get_option(const char *optstr, const char *name, if (!optstr || !name) return -EINVAL; - rc = mnt_optstr_locate_option((char *) optstr, name, &ol); + rc = mnt_optstr_locate_option((char *) optstr, name, 0, &ol); if (!rc) { if (value) *value = ol.value; @@ -255,7 +261,7 @@ int mnt_optstr_deduplicate_option(char **optstr, const char *name) do { struct libmnt_optloc ol = MNT_INIT_OPTLOC; - rc = mnt_optstr_locate_option(opt, name, &ol); + rc = mnt_optstr_locate_option(opt, name, 0, &ol); if (!rc) { if (begin) { /* remove the previous instance */ @@ -368,7 +374,7 @@ int mnt_optstr_set_option(char **optstr, const char *name, const char *value) return -EINVAL; if (*optstr) - rc = mnt_optstr_locate_option(*optstr, name, &ol); + rc = mnt_optstr_locate_option(*optstr, name, 0, &ol); if (rc < 0) return rc; /* parse error */ if (rc == 1) @@ -411,7 +417,7 @@ int mnt_optstr_remove_option(char **optstr, const char *name) if (!optstr || !name) return -EINVAL; - rc = mnt_optstr_locate_option(*optstr, name, &ol); + rc = mnt_optstr_locate_option(*optstr, name, 0, &ol); if (rc != 0) return rc; @@ -571,6 +577,51 @@ int mnt_optstr_get_options(const char *optstr, char **subset, return rc; } +/* + * @optstr: string with comma separated list of options + * @wanted: options expected in @optstr + * @missing: returns options from @wanted which missing in @optstr (optional) + * + * Retursn: <0 on error, 0 on missing options, 1 if nothing is missing + */ +int mnt_optstr_get_missing(const char *optstr, const char *wanted, char **missing) +{ + char *name, *val, *str = (char *) wanted; + size_t namesz = 0, valsz = 0; + struct ul_buffer buf = UL_INIT_BUFFER; + int rc = 0; + + if (!wanted) + return 1; + if (missing) { + /* caller wants data, prepare buffer */ + ul_buffer_set_chunksize(&buf, strlen(wanted) + 3); /* to call realloc() only once */ + *missing = NULL; + } + + while (!mnt_optstr_next_option(&str, &name, &namesz, &val, &valsz)) { + + rc = mnt_optstr_locate_option((char *) optstr, name, namesz, NULL); + if (rc == 1) { /* not found */ + if (!missing) + return 0; + rc = mnt_buffer_append_option(&buf, name, namesz, val, valsz, 0); + } + if (rc < 0) + break; + rc = 0; + } + + if (!rc && missing) { + if (ul_buffer_is_empty(&buf)) + rc = 1; + else + *missing = ul_buffer_get_data(&buf, NULL, NULL); + } else + ul_buffer_free_data(&buf); + + return rc; +} /** * mnt_optstr_get_flags: @@ -910,7 +961,8 @@ int mnt_match_options(const char *optstr, const char *pattern) } #ifdef TEST_PROGRAM -static int test_append(struct libmnt_test *ts, int argc, char *argv[]) +static int test_append(struct libmnt_test *ts __attribute__((unused)), + int argc, char *argv[]) { const char *value = NULL, *name; char *optstr; @@ -933,7 +985,8 @@ static int test_append(struct libmnt_test *ts, int argc, char *argv[]) return rc; } -static int test_prepend(struct libmnt_test *ts, int argc, char *argv[]) +static int test_prepend(struct libmnt_test *ts __attribute__((unused)), + int argc, char *argv[]) { const char *value = NULL, *name; char *optstr; @@ -956,7 +1009,8 @@ static int test_prepend(struct libmnt_test *ts, int argc, char *argv[]) return rc; } -static int test_split(struct libmnt_test *ts, int argc, char *argv[]) +static int test_split(struct libmnt_test *ts __attribute__((unused)), + int argc, char *argv[]) { char *optstr, *user = NULL, *fs = NULL, *vfs = NULL; int rc; @@ -982,7 +1036,8 @@ static int test_split(struct libmnt_test *ts, int argc, char *argv[]) return rc; } -static int test_flags(struct libmnt_test *ts, int argc, char *argv[]) +static int test_flags(struct libmnt_test *ts __attribute__((unused)), + int argc, char *argv[]) { char *optstr; int rc; @@ -1010,7 +1065,8 @@ static int test_flags(struct libmnt_test *ts, int argc, char *argv[]) return rc; } -static int test_apply(struct libmnt_test *ts, int argc, char *argv[]) +static int test_apply(struct libmnt_test *ts __attribute__((unused)), + int argc, char *argv[]) { char *optstr; int rc, map; @@ -1042,7 +1098,8 @@ static int test_apply(struct libmnt_test *ts, int argc, char *argv[]) return rc; } -static int test_set(struct libmnt_test *ts, int argc, char *argv[]) +static int test_set(struct libmnt_test *ts __attribute__((unused)), + int argc, char *argv[]) { const char *value = NULL, *name; char *optstr; @@ -1065,7 +1122,8 @@ static int test_set(struct libmnt_test *ts, int argc, char *argv[]) return rc; } -static int test_get(struct libmnt_test *ts, int argc, char *argv[]) +static int test_get(struct libmnt_test *ts __attribute__((unused)), + int argc, char *argv[]) { char *optstr; const char *name; @@ -1094,7 +1152,32 @@ static int test_get(struct libmnt_test *ts, int argc, char *argv[]) return rc; } -static int test_remove(struct libmnt_test *ts, int argc, char *argv[]) +static int test_missing(struct libmnt_test *ts __attribute__((unused)), + int argc, char *argv[]) +{ + const char *optstr; + const char *wanted; + char *missing = NULL; + int rc; + + if (argc < 2) + return -EINVAL; + optstr = argv[1]; + wanted = argv[2]; + + rc = mnt_optstr_get_missing(optstr, wanted, &missing); + if (rc == 0) + printf("missing: %s\n", missing); + else if (rc == 1) { + printf("nothing\n"); + rc = 0; + } else + printf("parse error: %s\n", optstr); + return rc; +} + +static int test_remove(struct libmnt_test *ts __attribute__((unused)), + int argc, char *argv[]) { const char *name; char *optstr; @@ -1114,7 +1197,8 @@ static int test_remove(struct libmnt_test *ts, int argc, char *argv[]) return rc; } -static int test_dedup(struct libmnt_test *ts, int argc, char *argv[]) +static int test_dedup(struct libmnt_test *ts __attribute__((unused)), + int argc, char *argv[]) { const char *name; char *optstr; @@ -1134,7 +1218,8 @@ static int test_dedup(struct libmnt_test *ts, int argc, char *argv[]) return rc; } -static int test_match(struct libmnt_test *ts, int argc, char *argv[]) +static int test_match(struct libmnt_test *ts __attribute__((unused)), + int argc, char *argv[]) { char *optstr, *pattern; @@ -1156,6 +1241,7 @@ int main(int argc, char *argv[]) { "--prepend",test_prepend,"<optstr> <name> [<value>] prepend value to optstr" }, { "--set", test_set, "<optstr> <name> [<value>] (un)set value" }, { "--get", test_get, "<optstr> <name> search name in optstr" }, + { "--missing",test_missing,"<optstr> <wanted> what from wanted is missing" }, { "--remove", test_remove, "<optstr> <name> remove name in optstr" }, { "--dedup", test_dedup, "<optstr> <name> deduplicate name in optstr" }, { "--match", test_match, "<optstr> <pattern> compare optstr with pattern" }, |