summaryrefslogtreecommitdiffstats
path: root/libmount/src/optstr.c
diff options
context:
space:
mode:
Diffstat (limited to 'libmount/src/optstr.c')
-rw-r--r--libmount/src/optstr.c130
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" },