]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
edfea9fe ZJS |
2 | |
3 | #include <stdlib.h> | |
4 | ||
e82116e5 | 5 | #include "analyze.h" |
edfea9fe | 6 | #include "analyze-condition.h" |
f2562398 | 7 | #include "analyze-verify-util.h" |
edfea9fe ZJS |
8 | #include "condition.h" |
9 | #include "conf-parser.h" | |
10 | #include "load-fragment.h" | |
11 | #include "service.h" | |
12 | ||
edfea9fe | 13 | static int parse_condition(Unit *u, const char *line) { |
625a1640 LP |
14 | assert(u); |
15 | assert(line); | |
16 | ||
17 | for (ConditionType t = 0; t < _CONDITION_TYPE_MAX; t++) { | |
18 | ConfigParserCallback callback; | |
19 | Condition **target; | |
20 | const char *p, *name; | |
21 | ||
22 | name = condition_type_to_string(t); | |
23 | p = startswith(line, name); | |
24 | if (p) | |
25 | target = &u->conditions; | |
26 | else { | |
27 | name = assert_type_to_string(t); | |
28 | p = startswith(line, name); | |
29 | if (!p) | |
30 | continue; | |
31 | ||
32 | target = &u->asserts; | |
33 | } | |
08ef6886 | 34 | |
edfea9fe | 35 | p += strspn(p, WHITESPACE); |
08ef6886 | 36 | |
edfea9fe | 37 | if (*p != '=') |
08ef6886 LP |
38 | continue; |
39 | p++; | |
edfea9fe | 40 | |
08ef6886 | 41 | p += strspn(p, WHITESPACE); |
edfea9fe | 42 | |
476cfe62 | 43 | if (condition_takes_path(t)) |
625a1640 LP |
44 | callback = config_parse_unit_condition_path; |
45 | else | |
46 | callback = config_parse_unit_condition_string; | |
47 | ||
48 | return callback(NULL, "(cmdline)", 0, NULL, 0, name, t, p, target, u); | |
edfea9fe ZJS |
49 | } |
50 | ||
51 | return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot parse \"%s\".", line); | |
52 | } | |
53 | ||
54 | _printf_(7, 8) | |
55 | static int log_helper(void *userdata, int level, int error, const char *file, int line, const char *func, const char *format, ...) { | |
56 | Unit *u = userdata; | |
57 | va_list ap; | |
58 | int r; | |
59 | ||
60 | assert(u); | |
61 | ||
62 | /* "upgrade" debug messages */ | |
63 | level = MIN(LOG_INFO, level); | |
64 | ||
65 | va_start(ap, format); | |
66 | r = log_object_internalv(level, error, file, line, func, | |
67 | NULL, | |
68 | u->id, | |
69 | NULL, | |
70 | NULL, | |
71 | format, ap); | |
72 | va_end(ap); | |
73 | ||
74 | return r; | |
75 | } | |
76 | ||
b380b643 | 77 | static int verify_conditions(char **lines, LookupScope scope, const char *unit, const char *root) { |
edfea9fe ZJS |
78 | _cleanup_(manager_freep) Manager *m = NULL; |
79 | Unit *u; | |
edfea9fe ZJS |
80 | int r, q = 1; |
81 | ||
8de7929d DDM |
82 | if (unit) { |
83 | _cleanup_strv_free_ char **filenames = NULL; | |
84 | _cleanup_free_ char *var = NULL; | |
85 | ||
86 | filenames = strv_new(unit); | |
87 | if (!filenames) | |
88 | return log_oom(); | |
89 | ||
90 | r = verify_generate_path(&var, filenames); | |
91 | if (r < 0) | |
92 | return log_error_errno(r, "Failed to generate unit load path: %m"); | |
93 | ||
94 | assert_se(set_unit_path(var) >= 0); | |
95 | } | |
96 | ||
edfea9fe ZJS |
97 | r = manager_new(scope, MANAGER_TEST_RUN_MINIMAL, &m); |
98 | if (r < 0) | |
99 | return log_error_errno(r, "Failed to initialize manager: %m"); | |
100 | ||
101 | log_debug("Starting manager..."); | |
8de7929d | 102 | r = manager_startup(m, /* serialization= */ NULL, /* fds= */ NULL, root); |
edfea9fe ZJS |
103 | if (r < 0) |
104 | return r; | |
105 | ||
8de7929d DDM |
106 | if (unit) { |
107 | _cleanup_free_ char *prepared = NULL; | |
edfea9fe | 108 | |
8de7929d DDM |
109 | r = verify_prepare_filename(unit, &prepared); |
110 | if (r < 0) | |
111 | return log_error_errno(r, "Failed to prepare filename %s: %m", unit); | |
112 | ||
113 | r = manager_load_startable_unit_or_warn(m, NULL, prepared, &u); | |
edfea9fe ZJS |
114 | if (r < 0) |
115 | return r; | |
8de7929d | 116 | } else { |
8de7929d DDM |
117 | r = unit_new_for_name(m, sizeof(Service), "test.service", &u); |
118 | if (r < 0) | |
119 | return log_error_errno(r, "Failed to create test.service: %m"); | |
120 | ||
121 | STRV_FOREACH(line, lines) { | |
122 | r = parse_condition(u, *line); | |
123 | if (r < 0) | |
124 | return r; | |
125 | } | |
edfea9fe ZJS |
126 | } |
127 | ||
a0b191b7 | 128 | r = condition_test_list(u->asserts, environ, assert_type_to_string, log_helper, u); |
edfea9fe ZJS |
129 | if (u->asserts) |
130 | log_notice("Asserts %s.", r > 0 ? "succeeded" : "failed"); | |
131 | ||
a0b191b7 | 132 | q = condition_test_list(u->conditions, environ, condition_type_to_string, log_helper, u); |
edfea9fe ZJS |
133 | if (u->conditions) |
134 | log_notice("Conditions %s.", q > 0 ? "succeeded" : "failed"); | |
135 | ||
136 | return r > 0 && q > 0 ? 0 : -EIO; | |
137 | } | |
e82116e5 | 138 | |
ef38bedb | 139 | int verb_condition(int argc, char *argv[], void *userdata) { |
e82116e5 LP |
140 | return verify_conditions(strv_skip(argv, 1), arg_scope, arg_unit, arg_root); |
141 | } |