]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/condition-util.c
man: document ARM root partition types
[thirdparty/systemd.git] / src / shared / condition-util.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <stdlib.h>
23 #include <errno.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <sys/statvfs.h>
27 #include <fnmatch.h>
28
29 #include <systemd/sd-id128.h>
30 #include "util.h"
31 #include "condition-util.h"
32 #include "virt.h"
33 #include "path-util.h"
34 #include "fileio.h"
35 #include "unit.h"
36 #include "architecture.h"
37
38 Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate) {
39 Condition *c;
40
41 assert(type < _CONDITION_TYPE_MAX);
42
43 c = new0(Condition, 1);
44 if (!c)
45 return NULL;
46
47 c->type = type;
48 c->trigger = trigger;
49 c->negate = negate;
50
51 if (parameter) {
52 c->parameter = strdup(parameter);
53 if (!c->parameter) {
54 free(c);
55 return NULL;
56 }
57 }
58
59 return c;
60 }
61
62 void condition_free(Condition *c) {
63 assert(c);
64
65 free(c->parameter);
66 free(c);
67 }
68
69 void condition_free_list(Condition *first) {
70 Condition *c, *n;
71
72 LIST_FOREACH_SAFE(conditions, c, n, first)
73 condition_free(c);
74 }
75
76 bool condition_test_kernel_command_line(Condition *c) {
77 char *line, *w, *state, *word = NULL;
78 bool equal;
79 int r;
80 size_t l, pl;
81 bool found = false;
82
83 assert(c);
84 assert(c->parameter);
85 assert(c->type == CONDITION_KERNEL_COMMAND_LINE);
86
87 r = proc_cmdline(&line);
88 if (r < 0)
89 log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
90 if (r <= 0)
91 return c->negate;
92
93 equal = !!strchr(c->parameter, '=');
94 pl = strlen(c->parameter);
95
96 FOREACH_WORD_QUOTED(w, l, line, state) {
97
98 free(word);
99 word = strndup(w, l);
100 if (!word)
101 break;
102
103 if (equal) {
104 if (streq(word, c->parameter)) {
105 found = true;
106 break;
107 }
108 } else {
109 if (startswith(word, c->parameter) && (word[pl] == '=' || word[pl] == 0)) {
110 found = true;
111 break;
112 }
113 }
114
115 }
116
117 free(word);
118 free(line);
119
120 return found == !c->negate;
121 }
122
123 bool condition_test_virtualization(Condition *c) {
124 int b, v;
125 const char *id;
126
127 assert(c);
128 assert(c->parameter);
129 assert(c->type == CONDITION_VIRTUALIZATION);
130
131 v = detect_virtualization(&id);
132 if (v < 0) {
133 log_warning("Failed to detect virtualization, ignoring: %s", strerror(-v));
134 return c->negate;
135 }
136
137 /* First, compare with yes/no */
138 b = parse_boolean(c->parameter);
139
140 if (v > 0 && b > 0)
141 return !c->negate;
142
143 if (v == 0 && b == 0)
144 return !c->negate;
145
146 /* Then, compare categorization */
147 if (v == VIRTUALIZATION_VM && streq(c->parameter, "vm"))
148 return !c->negate;
149
150 if (v == VIRTUALIZATION_CONTAINER && streq(c->parameter, "container"))
151 return !c->negate;
152
153 /* Finally compare id */
154 return (v > 0 && streq(c->parameter, id)) == !c->negate;
155 }
156
157 bool condition_test_architecture(Condition *c) {
158 Architecture a, b;
159
160 assert(c);
161 assert(c->parameter);
162 assert(c->type == CONDITION_ARCHITECTURE);
163
164 a = uname_architecture();
165 if (a < 0)
166 return c->negate;
167
168 if (streq(c->parameter, "native"))
169 b = native_architecture();
170 else
171 b = architecture_from_string(c->parameter);
172
173 if (b < 0)
174 return c->negate;
175
176 return (a == b) == !c->negate;
177 }
178
179 bool condition_test_host(Condition *c) {
180 sd_id128_t x, y;
181 char *h;
182 int r;
183 bool b;
184
185 assert(c);
186 assert(c->parameter);
187 assert(c->type == CONDITION_HOST);
188
189 if (sd_id128_from_string(c->parameter, &x) >= 0) {
190
191 r = sd_id128_get_machine(&y);
192 if (r < 0)
193 return c->negate;
194
195 return sd_id128_equal(x, y) == !c->negate;
196 }
197
198 h = gethostname_malloc();
199 if (!h)
200 return c->negate;
201
202 b = fnmatch(c->parameter, h, FNM_CASEFOLD) == 0;
203 free(h);
204
205 return b == !c->negate;
206 }
207
208 bool condition_test_ac_power(Condition *c) {
209 int r;
210
211 assert(c);
212 assert(c->parameter);
213 assert(c->type == CONDITION_AC_POWER);
214
215 r = parse_boolean(c->parameter);
216 if (r < 0)
217 return !c->negate;
218
219 return ((on_ac_power() != 0) == !!r) == !c->negate;
220 }
221
222 void condition_dump(Condition *c, FILE *f, const char *prefix) {
223 assert(c);
224 assert(f);
225
226 if (!prefix)
227 prefix = "";
228
229 fprintf(f,
230 "%s\t%s: %s%s%s %s\n",
231 prefix,
232 condition_type_to_string(c->type),
233 c->trigger ? "|" : "",
234 c->negate ? "!" : "",
235 c->parameter,
236 c->state < 0 ? "failed" : c->state > 0 ? "succeeded" : "untested");
237 }
238
239 void condition_dump_list(Condition *first, FILE *f, const char *prefix) {
240 Condition *c;
241
242 LIST_FOREACH(conditions, c, first)
243 condition_dump(c, f, prefix);
244 }
245
246 static const char* const condition_type_table[_CONDITION_TYPE_MAX] = {
247 [CONDITION_PATH_EXISTS] = "ConditionPathExists",
248 [CONDITION_PATH_EXISTS_GLOB] = "ConditionPathExistsGlob",
249 [CONDITION_PATH_IS_DIRECTORY] = "ConditionPathIsDirectory",
250 [CONDITION_PATH_IS_SYMBOLIC_LINK] = "ConditionPathIsSymbolicLink",
251 [CONDITION_PATH_IS_MOUNT_POINT] = "ConditionPathIsMountPoint",
252 [CONDITION_PATH_IS_READ_WRITE] = "ConditionPathIsReadWrite",
253 [CONDITION_DIRECTORY_NOT_EMPTY] = "ConditionDirectoryNotEmpty",
254 [CONDITION_FILE_NOT_EMPTY] = "ConditionFileNotEmpty",
255 [CONDITION_FILE_IS_EXECUTABLE] = "ConditionFileIsExecutable",
256 [CONDITION_KERNEL_COMMAND_LINE] = "ConditionKernelCommandLine",
257 [CONDITION_VIRTUALIZATION] = "ConditionVirtualization",
258 [CONDITION_SECURITY] = "ConditionSecurity",
259 [CONDITION_CAPABILITY] = "ConditionCapability",
260 [CONDITION_HOST] = "ConditionHost",
261 [CONDITION_AC_POWER] = "ConditionACPower",
262 [CONDITION_ARCHITECTURE] = "ConditionArchitecture",
263 [CONDITION_NULL] = "ConditionNull"
264 };
265
266 DEFINE_STRING_TABLE_LOOKUP(condition_type, ConditionType);