]>
Commit | Line | Data |
---|---|---|
edfea9fe ZJS |
1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
2 | ||
3 | #include <stdlib.h> | |
4 | ||
5 | #include "analyze-condition.h" | |
6 | #include "condition.h" | |
7 | #include "conf-parser.h" | |
8 | #include "load-fragment.h" | |
9 | #include "service.h" | |
10 | ||
11 | typedef struct condition_definition { | |
12 | const char *name; | |
13 | ConfigParserCallback parser; | |
14 | ConditionType type; | |
15 | } condition_definition; | |
16 | ||
17 | static const condition_definition condition_definitions[] = { | |
18 | { "ConditionPathExists", config_parse_unit_condition_path, CONDITION_PATH_EXISTS }, | |
19 | { "ConditionPathExistsGlob", config_parse_unit_condition_path, CONDITION_PATH_EXISTS_GLOB }, | |
20 | { "ConditionPathIsDirectory", config_parse_unit_condition_path, CONDITION_PATH_IS_DIRECTORY }, | |
21 | { "ConditionPathIsSymbolicLink", config_parse_unit_condition_path, CONDITION_PATH_IS_SYMBOLIC_LINK }, | |
22 | { "ConditionPathIsMountPoint", config_parse_unit_condition_path, CONDITION_PATH_IS_MOUNT_POINT }, | |
23 | { "ConditionPathIsReadWrite", config_parse_unit_condition_path, CONDITION_PATH_IS_READ_WRITE }, | |
7f19247b | 24 | { "ConditionPathIsEncrypted", config_parse_unit_condition_path, CONDITION_PATH_IS_ENCRYPTED }, |
edfea9fe ZJS |
25 | { "ConditionDirectoryNotEmpty", config_parse_unit_condition_path, CONDITION_DIRECTORY_NOT_EMPTY }, |
26 | { "ConditionFileNotEmpty", config_parse_unit_condition_path, CONDITION_FILE_NOT_EMPTY }, | |
27 | { "ConditionFileIsExecutable", config_parse_unit_condition_path, CONDITION_FILE_IS_EXECUTABLE }, | |
28 | { "ConditionNeedsUpdate", config_parse_unit_condition_path, CONDITION_NEEDS_UPDATE }, | |
29 | { "ConditionFirstBoot", config_parse_unit_condition_string, CONDITION_FIRST_BOOT }, | |
30 | { "ConditionKernelCommandLine", config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE }, | |
31 | { "ConditionKernelVersion", config_parse_unit_condition_string, CONDITION_KERNEL_VERSION }, | |
32 | { "ConditionArchitecture", config_parse_unit_condition_string, CONDITION_ARCHITECTURE }, | |
33 | { "ConditionVirtualization", config_parse_unit_condition_string, CONDITION_VIRTUALIZATION }, | |
34 | { "ConditionSecurity", config_parse_unit_condition_string, CONDITION_SECURITY }, | |
35 | { "ConditionCapability", config_parse_unit_condition_string, CONDITION_CAPABILITY }, | |
36 | { "ConditionHost", config_parse_unit_condition_string, CONDITION_HOST }, | |
37 | { "ConditionACPower", config_parse_unit_condition_string, CONDITION_AC_POWER }, | |
38 | { "ConditionUser", config_parse_unit_condition_string, CONDITION_USER }, | |
39 | { "ConditionGroup", config_parse_unit_condition_string, CONDITION_GROUP }, | |
40 | { "ConditionControlGroupController", config_parse_unit_condition_string, CONDITION_CONTROL_GROUP_CONTROLLER }, | |
41 | ||
42 | { "AssertPathExists", config_parse_unit_condition_path, CONDITION_PATH_EXISTS }, | |
43 | { "AssertPathExistsGlob", config_parse_unit_condition_path, CONDITION_PATH_EXISTS_GLOB }, | |
44 | { "AssertPathIsDirectory", config_parse_unit_condition_path, CONDITION_PATH_IS_DIRECTORY }, | |
45 | { "AssertPathIsSymbolicLink", config_parse_unit_condition_path, CONDITION_PATH_IS_SYMBOLIC_LINK }, | |
46 | { "AssertPathIsMountPoint", config_parse_unit_condition_path, CONDITION_PATH_IS_MOUNT_POINT }, | |
47 | { "AssertPathIsReadWrite", config_parse_unit_condition_path, CONDITION_PATH_IS_READ_WRITE }, | |
7f19247b | 48 | { "AssertPathIsEncrypted", config_parse_unit_condition_path, CONDITION_PATH_IS_ENCRYPTED }, |
edfea9fe ZJS |
49 | { "AssertDirectoryNotEmpty", config_parse_unit_condition_path, CONDITION_DIRECTORY_NOT_EMPTY }, |
50 | { "AssertFileNotEmpty", config_parse_unit_condition_path, CONDITION_FILE_NOT_EMPTY }, | |
51 | { "AssertFileIsExecutable", config_parse_unit_condition_path, CONDITION_FILE_IS_EXECUTABLE }, | |
52 | { "AssertNeedsUpdate", config_parse_unit_condition_path, CONDITION_NEEDS_UPDATE }, | |
53 | { "AssertFirstBoot", config_parse_unit_condition_string, CONDITION_FIRST_BOOT }, | |
54 | { "AssertKernelCommandLine", config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE }, | |
55 | { "AssertKernelVersion", config_parse_unit_condition_string, CONDITION_KERNEL_VERSION }, | |
56 | { "AssertArchitecture", config_parse_unit_condition_string, CONDITION_ARCHITECTURE }, | |
57 | { "AssertVirtualization", config_parse_unit_condition_string, CONDITION_VIRTUALIZATION }, | |
58 | { "AssertSecurity", config_parse_unit_condition_string, CONDITION_SECURITY }, | |
59 | { "AssertCapability", config_parse_unit_condition_string, CONDITION_CAPABILITY }, | |
60 | { "AssertHost", config_parse_unit_condition_string, CONDITION_HOST }, | |
61 | { "AssertACPower", config_parse_unit_condition_string, CONDITION_AC_POWER }, | |
62 | { "AssertUser", config_parse_unit_condition_string, CONDITION_USER }, | |
63 | { "AssertGroup", config_parse_unit_condition_string, CONDITION_GROUP }, | |
64 | { "AssertControlGroupController", config_parse_unit_condition_string, CONDITION_CONTROL_GROUP_CONTROLLER }, | |
65 | ||
66 | /* deprecated, but we should still parse them */ | |
67 | { "ConditionNull", config_parse_unit_condition_null, 0 }, | |
68 | { "AssertNull", config_parse_unit_condition_null, 0 }, | |
69 | }; | |
70 | ||
71 | static int parse_condition(Unit *u, const char *line) { | |
72 | const char *p; | |
73 | Condition **target; | |
74 | ||
75 | if ((p = startswith(line, "Condition"))) | |
76 | target = &u->conditions; | |
77 | else if ((p = startswith(line, "Assert"))) | |
78 | target = &u->asserts; | |
79 | else | |
80 | return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot parse \"%s\".", line); | |
81 | ||
82 | for (size_t i = 0; i < ELEMENTSOF(condition_definitions); i++) { | |
83 | const condition_definition *c = &condition_definitions[i]; | |
84 | ||
85 | p = startswith(line, c->name); | |
86 | if (!p) | |
87 | continue; | |
08ef6886 | 88 | |
edfea9fe | 89 | p += strspn(p, WHITESPACE); |
08ef6886 | 90 | |
edfea9fe | 91 | if (*p != '=') |
08ef6886 LP |
92 | continue; |
93 | p++; | |
edfea9fe | 94 | |
08ef6886 | 95 | p += strspn(p, WHITESPACE); |
edfea9fe ZJS |
96 | |
97 | return c->parser(NULL, "(stdin)", 0, NULL, 0, c->name, c->type, p, target, u); | |
98 | } | |
99 | ||
100 | return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot parse \"%s\".", line); | |
101 | } | |
102 | ||
103 | _printf_(7, 8) | |
104 | static int log_helper(void *userdata, int level, int error, const char *file, int line, const char *func, const char *format, ...) { | |
105 | Unit *u = userdata; | |
106 | va_list ap; | |
107 | int r; | |
108 | ||
109 | assert(u); | |
110 | ||
111 | /* "upgrade" debug messages */ | |
112 | level = MIN(LOG_INFO, level); | |
113 | ||
114 | va_start(ap, format); | |
115 | r = log_object_internalv(level, error, file, line, func, | |
116 | NULL, | |
117 | u->id, | |
118 | NULL, | |
119 | NULL, | |
120 | format, ap); | |
121 | va_end(ap); | |
122 | ||
123 | return r; | |
124 | } | |
125 | ||
126 | int verify_conditions(char **lines, UnitFileScope scope) { | |
127 | _cleanup_(manager_freep) Manager *m = NULL; | |
128 | Unit *u; | |
129 | char **line; | |
130 | int r, q = 1; | |
131 | ||
132 | r = manager_new(scope, MANAGER_TEST_RUN_MINIMAL, &m); | |
133 | if (r < 0) | |
134 | return log_error_errno(r, "Failed to initialize manager: %m"); | |
135 | ||
136 | log_debug("Starting manager..."); | |
137 | r = manager_startup(m, NULL, NULL); | |
138 | if (r < 0) | |
139 | return r; | |
140 | ||
141 | r = unit_new_for_name(m, sizeof(Service), "test.service", &u); | |
142 | if (r < 0) | |
143 | return log_error_errno(r, "Failed to create test.service: %m"); | |
144 | ||
145 | STRV_FOREACH(line, lines) { | |
146 | r = parse_condition(u, *line); | |
147 | if (r < 0) | |
148 | return r; | |
149 | } | |
150 | ||
a0b191b7 | 151 | r = condition_test_list(u->asserts, environ, assert_type_to_string, log_helper, u); |
edfea9fe ZJS |
152 | if (u->asserts) |
153 | log_notice("Asserts %s.", r > 0 ? "succeeded" : "failed"); | |
154 | ||
a0b191b7 | 155 | q = condition_test_list(u->conditions, environ, condition_type_to_string, log_helper, u); |
edfea9fe ZJS |
156 | if (u->conditions) |
157 | log_notice("Conditions %s.", q > 0 ? "succeeded" : "failed"); | |
158 | ||
159 | return r > 0 && q > 0 ? 0 : -EIO; | |
160 | } |