From: Karel Zak Date: Tue, 22 Mar 2022 10:09:07 +0000 (+0100) Subject: libmount: move optstr parsing to lib/ X-Git-Tag: v2.39-rc1~750 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6c513f3c54b76666ac85cf1635a060efa327eaf3;p=thirdparty%2Futil-linux.git libmount: move optstr parsing to lib/ Signed-off-by: Karel Zak --- diff --git a/include/strutils.h b/include/strutils.h index ae689a30ad..62129f6f30 100644 --- a/include/strutils.h +++ b/include/strutils.h @@ -392,4 +392,6 @@ extern const char *split(const char **state, size_t *l, const char *separator, i extern int skip_fline(FILE *fp); extern int ul_stralnumcmp(const char *p1, const char *p2); +extern int ul_optstr_next(char **optstr, char **name, size_t *namesz, char **value, size_t *valsz); + #endif diff --git a/lib/strutils.c b/lib/strutils.c index e85d265d2d..cfbd35e677 100644 --- a/lib/strutils.c +++ b/lib/strutils.c @@ -1123,6 +1123,76 @@ int ul_stralnumcmp(const char *p1, const char *p2) return c1 - c2; } +/* + * Parses the first option from @optstr. The @optstr pointer is set to the beginning + * of the next option. The options string looks like 'aaa,bbb=data,foo,bar="xxx"'. + * + * Note this function is used by libmount to parse mount options. Be careful when modify. + * + * Returns -EINVAL on parse error, 1 at the end of optstr and 0 on success. + */ +int ul_optstr_next(char **optstr, char **name, size_t *namesz, + char **value, size_t *valsz) +{ + int open_quote = 0; + char *start = NULL, *stop = NULL, *p, *sep = NULL; + char *optstr0; + + assert(optstr); + assert(*optstr); + + optstr0 = *optstr; + + if (name) + *name = NULL; + if (namesz) + *namesz = 0; + if (value) + *value = NULL; + if (valsz) + *valsz = 0; + + /* trim leading commas as to not invalidate option + * strings with multiple consecutive commas */ + while (optstr0 && *optstr0 == ',') + optstr0++; + + for (p = optstr0; p && *p; p++) { + if (!start) + start = p; /* beginning of the option item */ + if (*p == '"') + open_quote ^= 1; /* reverse the status */ + if (open_quote) + continue; /* still in quoted block */ + if (!sep && p > start && *p == '=') + sep = p; /* name and value separator */ + if (*p == ',') + stop = p; /* terminate the option item */ + else if (*(p + 1) == '\0') + stop = p + 1; /* end of optstr */ + if (!start || !stop) + continue; + if (stop <= start) + return -EINVAL; + + if (name) + *name = start; + if (namesz) + *namesz = sep ? sep - start : stop - start; + *optstr = *stop ? stop + 1 : stop; + + if (sep) { + if (value) + *value = sep + 1; + if (valsz) + *valsz = stop - sep - 1; + } + return 0; + } + + return 1; /* end of optstr */ +} + #ifdef TEST_PROGRAM_STRUTILS struct testS { char *name; diff --git a/libmount/src/optstr.c b/libmount/src/optstr.c index 5acc94eaec..5daa511a0c 100644 --- a/libmount/src/optstr.c +++ b/libmount/src/optstr.c @@ -45,78 +45,6 @@ struct libmnt_optloc { #define mnt_optmap_entry_novalue(e) \ (e && (e)->name && !strchr((e)->name, '=') && !((e)->mask & MNT_PREFIX)) -/* - * Parses the first option from @optstr. The @optstr pointer is set to the beginning - * of the next option. - * - * Returns -EINVAL on parse error, 1 at the end of optstr and 0 on success. - */ -static int mnt_optstr_parse_next(char **optstr, char **name, size_t *namesz, - char **value, size_t *valsz) -{ - int open_quote = 0; - char *start = NULL, *stop = NULL, *p, *sep = NULL; - char *optstr0; - - assert(optstr); - assert(*optstr); - - optstr0 = *optstr; - - if (name) - *name = NULL; - if (namesz) - *namesz = 0; - if (value) - *value = NULL; - if (valsz) - *valsz = 0; - - /* trim leading commas as to not invalidate option - * strings with multiple consecutive commas */ - while (optstr0 && *optstr0 == ',') - optstr0++; - - for (p = optstr0; p && *p; p++) { - if (!start) - start = p; /* beginning of the option item */ - if (*p == '"') - open_quote ^= 1; /* reverse the status */ - if (open_quote) - continue; /* still in quoted block */ - if (!sep && p > start && *p == '=') - sep = p; /* name and value separator */ - if (*p == ',') - stop = p; /* terminate the option item */ - else if (*(p + 1) == '\0') - stop = p + 1; /* end of optstr */ - if (!start || !stop) - continue; - if (stop <= start) - goto error; - - if (name) - *name = start; - if (namesz) - *namesz = sep ? sep - start : stop - start; - *optstr = *stop ? stop + 1 : stop; - - if (sep) { - if (value) - *value = sep + 1; - if (valsz) - *valsz = stop - sep - 1; - } - return 0; - } - - return 1; /* end of optstr */ - -error: - DBG(OPTIONS, ul_debug("parse error: \"%s\"", optstr0)); - return -EINVAL; -} - /* * Locates the first option that matches @name. The @end is set to the * char behind the option (it means ',' or \0). @@ -138,7 +66,7 @@ static int mnt_optstr_locate_option(char *optstr, const char *name, namesz = strlen(name); do { - rc = mnt_optstr_parse_next(&optstr, &n, &nsz, + rc = ul_optstr_next(&optstr, &n, &nsz, &ol->value, &ol->valsz); if (rc) break; @@ -172,7 +100,8 @@ int mnt_optstr_next_option(char **optstr, char **name, size_t *namesz, { if (!optstr || !*optstr) return -EINVAL; - return mnt_optstr_parse_next(optstr, name, namesz, value, valuesz); + + return ul_optstr_next(optstr, name, namesz, value, valuesz); } static int __buffer_append_option(struct ul_buffer *buf,