Move config_parse_join_controllers to shared, add test

config_parse_join_controllers would free the destination argument on failure,
which is contrary to our normal style, where failed parsing has no effect.
Moving it to shared also allows a test to be added.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2018-02-19 15:02:13 +01:00
parent b48382e4e0
commit 9ecdba8cb7
6 changed files with 145 additions and 102 deletions
+105
View File
@@ -1021,3 +1021,108 @@ int config_parse_ip_port(
return 0;
}
int config_parse_join_controllers(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
char ****ret = data;
const char *whole_rvalue = rvalue;
unsigned n = 0;
_cleanup_(strv_free_freep) char ***controllers = NULL;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(ret);
for (;;) {
_cleanup_free_ char *word = NULL;
char **l;
int r;
r = extract_first_word(&rvalue, &word, NULL, EXTRACT_QUOTES);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Invalid value for %s: %s", lvalue, whole_rvalue);
return r;
}
if (r == 0)
break;
l = strv_split(word, ",");
if (!l)
return log_oom();
strv_uniq(l);
if (strv_length(l) <= 1) {
strv_free(l);
continue;
}
if (!controllers) {
controllers = new(char**, 2);
if (!controllers) {
strv_free(l);
return log_oom();
}
controllers[0] = l;
controllers[1] = NULL;
n = 1;
} else {
char ***a;
char ***t;
t = new0(char**, n+2);
if (!t) {
strv_free(l);
return log_oom();
}
n = 0;
for (a = controllers; *a; a++)
if (strv_overlap(*a, l)) {
if (strv_extend_strv(&l, *a, false) < 0) {
strv_free(l);
strv_free_free(t);
return log_oom();
}
} else {
char **c;
c = strv_copy(*a);
if (!c) {
strv_free(l);
strv_free_free(t);
return log_oom();
}
t[n++] = c;
}
t[n++] = strv_uniq(l);
strv_free_free(controllers);
controllers = t;
}
}
if (!isempty(rvalue))
log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring.");
strv_free_free(*ret);
*ret = controllers;
controllers = NULL;
return 0;
}