blob: b29fc0cd71b53ff2d59640e461ad7509580cbdd5 [file] [log] [blame]
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <stdlib.h>
#include "analyze.h"
#include "analyze-condition.h"
#include "analyze-verify-util.h"
#include "condition.h"
#include "conf-parser.h"
#include "load-fragment.h"
#include "service.h"
static int parse_condition(Unit *u, const char *line) {
assert(u);
assert(line);
for (ConditionType t = 0; t < _CONDITION_TYPE_MAX; t++) {
ConfigParserCallback callback;
Condition **target;
const char *p, *name;
name = condition_type_to_string(t);
p = startswith(line, name);
if (p)
target = &u->conditions;
else {
name = assert_type_to_string(t);
p = startswith(line, name);
if (!p)
continue;
target = &u->asserts;
}
p += strspn(p, WHITESPACE);
if (*p != '=')
continue;
p++;
p += strspn(p, WHITESPACE);
if (condition_takes_path(t))
callback = config_parse_unit_condition_path;
else
callback = config_parse_unit_condition_string;
return callback(NULL, "(cmdline)", 0, NULL, 0, name, t, p, target, u);
}
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot parse \"%s\".", line);
}
_printf_(7, 8)
static int log_helper(void *userdata, int level, int error, const char *file, int line, const char *func, const char *format, ...) {
Unit *u = ASSERT_PTR(userdata);
va_list ap;
int r;
/* "upgrade" debug messages */
level = MIN(LOG_INFO, level);
va_start(ap, format);
r = log_object_internalv(level, error, file, line, func,
NULL,
u->id,
NULL,
NULL,
format, ap);
va_end(ap);
return r;
}
static int verify_conditions(char **lines, LookupScope scope, const char *unit, const char *root) {
_cleanup_(manager_freep) Manager *m = NULL;
Unit *u;
int r, q = 1;
if (unit) {
_cleanup_strv_free_ char **filenames = NULL;
_cleanup_free_ char *var = NULL;
filenames = strv_new(unit);
if (!filenames)
return log_oom();
r = verify_generate_path(&var, filenames);
if (r < 0)
return log_error_errno(r, "Failed to generate unit load path: %m");
assert_se(set_unit_path(var) >= 0);
}
r = manager_new(scope, MANAGER_TEST_RUN_MINIMAL, &m);
if (r < 0)
return log_error_errno(r, "Failed to initialize manager: %m");
log_debug("Starting manager...");
r = manager_startup(m, /* serialization= */ NULL, /* fds= */ NULL, root);
if (r < 0)
return r;
if (unit) {
_cleanup_free_ char *prepared = NULL;
r = verify_prepare_filename(unit, &prepared);
if (r < 0)
return log_error_errno(r, "Failed to prepare filename %s: %m", unit);
r = manager_load_startable_unit_or_warn(m, NULL, prepared, &u);
if (r < 0)
return r;
} else {
r = unit_new_for_name(m, sizeof(Service), "test.service", &u);
if (r < 0)
return log_error_errno(r, "Failed to create test.service: %m");
STRV_FOREACH(line, lines) {
r = parse_condition(u, *line);
if (r < 0)
return r;
}
}
r = condition_test_list(u->asserts, environ, assert_type_to_string, log_helper, u);
if (u->asserts)
log_notice("Asserts %s.", r > 0 ? "succeeded" : "failed");
q = condition_test_list(u->conditions, environ, condition_type_to_string, log_helper, u);
if (u->conditions)
log_notice("Conditions %s.", q > 0 ? "succeeded" : "failed");
return r > 0 && q > 0 ? 0 : -EIO;
}
int verb_condition(int argc, char *argv[], void *userdata) {
int r;
r = verify_conditions(strv_skip(argv, 1), arg_scope, arg_unit, arg_root);
if (r < 0)
return r;
return EXIT_SUCCESS;
}