mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-11 05:17:44 +03:00
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:
parent
b48382e4e0
commit
9ecdba8cb7
@ -179,6 +179,7 @@ static inline bool strv_fnmatch_or_empty(char* const* patterns, const char *s, i
|
||||
}
|
||||
|
||||
char ***strv_free_free(char ***l);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(char***, strv_free_free);
|
||||
|
||||
char **strv_skip(char **l, size_t n);
|
||||
|
||||
|
101
src/core/main.c
101
src/core/main.c
@ -652,107 +652,6 @@ static int config_parse_crash_chvt(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static 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) {
|
||||
|
||||
const char *whole_rvalue = rvalue;
|
||||
unsigned n = 0;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
|
||||
arg_join_controllers = strv_free_free(arg_join_controllers);
|
||||
|
||||
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 (!arg_join_controllers) {
|
||||
arg_join_controllers = new(char**, 2);
|
||||
if (!arg_join_controllers) {
|
||||
strv_free(l);
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
arg_join_controllers[0] = l;
|
||||
arg_join_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 = arg_join_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(arg_join_controllers);
|
||||
arg_join_controllers = t;
|
||||
}
|
||||
}
|
||||
if (!isempty(rvalue))
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_config_file(void) {
|
||||
|
||||
const ConfigTableItem items[] = {
|
||||
|
@ -2710,7 +2710,6 @@ void manager_send_unit_plymouth(Manager *m, Unit *u) {
|
||||
}
|
||||
|
||||
if (connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) {
|
||||
|
||||
if (!IN_SET(errno, EPIPE, EAGAIN, ENOENT, ECONNREFUSED, ECONNRESET, ECONNABORTED))
|
||||
log_error_errno(errno, "connect() failed: %m");
|
||||
return;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -157,6 +157,7 @@ int config_parse_signal(GENERIC_PARSER_ARGS);
|
||||
int config_parse_personality(GENERIC_PARSER_ARGS);
|
||||
int config_parse_ifname(GENERIC_PARSER_ARGS);
|
||||
int config_parse_ip_port(GENERIC_PARSER_ARGS);
|
||||
int config_parse_join_controllers(GENERIC_PARSER_ARGS);
|
||||
|
||||
#define DEFINE_CONFIG_PARSE_ENUM(function,name,type,msg) \
|
||||
int function(GENERIC_PARSER_ARGS) { \
|
||||
|
@ -226,6 +226,43 @@ static void test_config_parse_iec_uint64(void) {
|
||||
assert_se(config_parse_iec_uint64(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4.5M", &offset, NULL) == 0);
|
||||
}
|
||||
|
||||
static void test_config_parse_join_controllers(void) {
|
||||
int r;
|
||||
_cleanup_(strv_free_freep) char ***c = NULL;
|
||||
char ***c2;
|
||||
|
||||
/* Test normal operation */
|
||||
r = config_parse_join_controllers(NULL, "example.conf", 11, "Section", 10, "JoinControllers", 0, "cpu,cpuacct net_cls,netprio", &c, NULL);
|
||||
assert_se(r == 0);
|
||||
assert_se(c);
|
||||
assert_se(strv_length(c[0]) == 2);
|
||||
assert_se(strv_equal(c[0], STRV_MAKE("cpu", "cpuacct")));
|
||||
assert_se(strv_length(c[1]) == 2);
|
||||
assert_se(strv_equal(c[1], STRV_MAKE("net_cls", "netprio")));
|
||||
assert_se(c[2] == NULL);
|
||||
|
||||
/* Test special case of no mounted controllers */
|
||||
r = config_parse_join_controllers(NULL, "example.conf", 12, "Section", 10, "JoinControllers", 0, "", &c, NULL);
|
||||
assert_se(r == 0);
|
||||
assert_se(c == NULL);
|
||||
|
||||
/* Test merging of overlapping lists */
|
||||
r = config_parse_join_controllers(NULL, "example.conf", 13, "Section", 10, "JoinControllers", 0, "a,b b,c", &c, NULL);
|
||||
assert_se(r == 0);
|
||||
assert_se(c);
|
||||
assert_se(strv_length(c[0]) == 3);
|
||||
assert_se(strv_contains(c[0], "a"));
|
||||
assert_se(strv_contains(c[0], "b"));
|
||||
assert_se(strv_contains(c[0], "c"));
|
||||
assert_se(c[1] == NULL);
|
||||
|
||||
/* Test ignoring of bad lines */
|
||||
c2 = c;
|
||||
r = config_parse_join_controllers(NULL, "example.conf", 14, "Section", 10, "JoinControllers", 0, "a,\"b ", &c, NULL);
|
||||
assert_se(r < 0);
|
||||
assert_se(c == c2);
|
||||
}
|
||||
|
||||
#define x10(x) x x x x x x x x x x
|
||||
#define x100(x) x10(x10(x))
|
||||
#define x1000(x) x10(x100(x))
|
||||
@ -365,6 +402,7 @@ int main(int argc, char **argv) {
|
||||
test_config_parse_sec();
|
||||
test_config_parse_nsec();
|
||||
test_config_parse_iec_uint64();
|
||||
test_config_parse_join_controllers();
|
||||
|
||||
for (i = 0; i < ELEMENTSOF(config_file); i++)
|
||||
test_config_parse(i, config_file[i]);
|
||||
|
Loading…
Reference in New Issue
Block a user