libmount: move optstr parsing to lib/

Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Karel Zak 2022-03-22 11:09:07 +01:00
parent 866d922bf8
commit 6c513f3c54
3 changed files with 75 additions and 74 deletions

View File

@ -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

View File

@ -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;

View File

@ -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,