]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/analyze/analyze-condition.c
coding style: document how to break a function declaration
[thirdparty/systemd.git] / src / analyze / analyze-condition.c
CommitLineData
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
11typedef struct condition_definition {
12 const char *name;
13 ConfigParserCallback parser;
14 ConditionType type;
15} condition_definition;
16
17static 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
71static 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)
104static 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
126int 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}