]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/condition-util.c
firstboot: get rid of firstboot generator again, introduce ConditionFirstBoot= instead
[thirdparty/systemd.git] / src / shared / condition-util.c
CommitLineData
b77c08e0
TG
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"
099524d7 36#include "architecture.h"
b77c08e0
TG
37
38Condition* 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
62void condition_free(Condition *c) {
63 assert(c);
64
65 free(c->parameter);
66 free(c);
67}
68
69void condition_free_list(Condition *first) {
70 Condition *c, *n;
71
72 LIST_FOREACH_SAFE(conditions, c, n, first)
73 condition_free(c);
74}
75
76bool 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
123bool condition_test_virtualization(Condition *c) {
248fab74 124 int b, v;
b77c08e0
TG
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
099524d7
LP
157bool 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
b77c08e0 179bool condition_test_host(Condition *c) {
dc92e62c 180 _cleanup_free_ char *h = NULL;
b77c08e0 181 sd_id128_t x, y;
b77c08e0 182 int r;
b77c08e0
TG
183
184 assert(c);
185 assert(c->parameter);
186 assert(c->type == CONDITION_HOST);
187
188 if (sd_id128_from_string(c->parameter, &x) >= 0) {
189
190 r = sd_id128_get_machine(&y);
191 if (r < 0)
192 return c->negate;
193
099524d7 194 return sd_id128_equal(x, y) == !c->negate;
b77c08e0
TG
195 }
196
197 h = gethostname_malloc();
198 if (!h)
199 return c->negate;
200
dc92e62c 201 return (fnmatch(c->parameter, h, FNM_CASEFOLD) == 0) == !c->negate;
b77c08e0
TG
202}
203
204bool condition_test_ac_power(Condition *c) {
205 int r;
206
207 assert(c);
208 assert(c->parameter);
209 assert(c->type == CONDITION_AC_POWER);
210
211 r = parse_boolean(c->parameter);
212 if (r < 0)
213 return !c->negate;
214
215 return ((on_ac_power() != 0) == !!r) == !c->negate;
216}
217
218void condition_dump(Condition *c, FILE *f, const char *prefix) {
219 assert(c);
220 assert(f);
221
222 if (!prefix)
223 prefix = "";
224
225 fprintf(f,
226 "%s\t%s: %s%s%s %s\n",
227 prefix,
228 condition_type_to_string(c->type),
229 c->trigger ? "|" : "",
230 c->negate ? "!" : "",
231 c->parameter,
232 c->state < 0 ? "failed" : c->state > 0 ? "succeeded" : "untested");
233}
234
235void condition_dump_list(Condition *first, FILE *f, const char *prefix) {
236 Condition *c;
237
238 LIST_FOREACH(conditions, c, first)
239 condition_dump(c, f, prefix);
240}
241
242static const char* const condition_type_table[_CONDITION_TYPE_MAX] = {
243 [CONDITION_PATH_EXISTS] = "ConditionPathExists",
244 [CONDITION_PATH_EXISTS_GLOB] = "ConditionPathExistsGlob",
245 [CONDITION_PATH_IS_DIRECTORY] = "ConditionPathIsDirectory",
246 [CONDITION_PATH_IS_SYMBOLIC_LINK] = "ConditionPathIsSymbolicLink",
247 [CONDITION_PATH_IS_MOUNT_POINT] = "ConditionPathIsMountPoint",
248 [CONDITION_PATH_IS_READ_WRITE] = "ConditionPathIsReadWrite",
249 [CONDITION_DIRECTORY_NOT_EMPTY] = "ConditionDirectoryNotEmpty",
250 [CONDITION_FILE_NOT_EMPTY] = "ConditionFileNotEmpty",
251 [CONDITION_FILE_IS_EXECUTABLE] = "ConditionFileIsExecutable",
252 [CONDITION_KERNEL_COMMAND_LINE] = "ConditionKernelCommandLine",
253 [CONDITION_VIRTUALIZATION] = "ConditionVirtualization",
254 [CONDITION_SECURITY] = "ConditionSecurity",
255 [CONDITION_CAPABILITY] = "ConditionCapability",
256 [CONDITION_HOST] = "ConditionHost",
257 [CONDITION_AC_POWER] = "ConditionACPower",
099524d7 258 [CONDITION_ARCHITECTURE] = "ConditionArchitecture",
a55654d5 259 [CONDITION_NEEDS_UPDATE] = "ConditionNeedsUpdate",
e2680723 260 [CONDITION_FIRST_BOOT] = "ConditionFirstBoot",
b77c08e0
TG
261 [CONDITION_NULL] = "ConditionNull"
262};
263
264DEFINE_STRING_TABLE_LOOKUP(condition_type, ConditionType);