]> git.proxmox.com Git - systemd.git/blame - src/shared/condition-util.c
Imported Upstream version 217
[systemd.git] / src / shared / condition-util.c
CommitLineData
60f067b4
JS
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
5eef597e 29#include "systemd/sd-id128.h"
60f067b4
JS
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
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) {
5eef597e
MP
77 char *line, *word = NULL;
78 const char *w, *state;
60f067b4
JS
79 bool equal;
80 int r;
81 size_t l, pl;
82 bool found = false;
83
84 assert(c);
85 assert(c->parameter);
86 assert(c->type == CONDITION_KERNEL_COMMAND_LINE);
87
88 r = proc_cmdline(&line);
89 if (r < 0)
90 log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
91 if (r <= 0)
92 return c->negate;
93
94 equal = !!strchr(c->parameter, '=');
95 pl = strlen(c->parameter);
96
97 FOREACH_WORD_QUOTED(w, l, line, state) {
98
99 free(word);
100 word = strndup(w, l);
101 if (!word)
102 break;
103
104 if (equal) {
105 if (streq(word, c->parameter)) {
106 found = true;
107 break;
108 }
109 } else {
110 if (startswith(word, c->parameter) && (word[pl] == '=' || word[pl] == 0)) {
111 found = true;
112 break;
113 }
114 }
115
116 }
5eef597e
MP
117 if (!isempty(state))
118 log_warning("Trailing garbage and the end of kernel commandline, ignoring.");
60f067b4
JS
119
120 free(word);
121 free(line);
122
123 return found == !c->negate;
124}
125
126bool condition_test_virtualization(Condition *c) {
127 int b, v;
128 const char *id;
129
130 assert(c);
131 assert(c->parameter);
132 assert(c->type == CONDITION_VIRTUALIZATION);
133
134 v = detect_virtualization(&id);
135 if (v < 0) {
136 log_warning("Failed to detect virtualization, ignoring: %s", strerror(-v));
137 return c->negate;
138 }
139
140 /* First, compare with yes/no */
141 b = parse_boolean(c->parameter);
142
143 if (v > 0 && b > 0)
144 return !c->negate;
145
146 if (v == 0 && b == 0)
147 return !c->negate;
148
149 /* Then, compare categorization */
150 if (v == VIRTUALIZATION_VM && streq(c->parameter, "vm"))
151 return !c->negate;
152
153 if (v == VIRTUALIZATION_CONTAINER && streq(c->parameter, "container"))
154 return !c->negate;
155
156 /* Finally compare id */
157 return (v > 0 && streq(c->parameter, id)) == !c->negate;
158}
159
160bool condition_test_architecture(Condition *c) {
161 Architecture a, b;
162
163 assert(c);
164 assert(c->parameter);
165 assert(c->type == CONDITION_ARCHITECTURE);
166
167 a = uname_architecture();
168 if (a < 0)
169 return c->negate;
170
171 if (streq(c->parameter, "native"))
172 b = native_architecture();
173 else
174 b = architecture_from_string(c->parameter);
175
176 if (b < 0)
177 return c->negate;
178
179 return (a == b) == !c->negate;
180}
181
182bool condition_test_host(Condition *c) {
e842803a 183 _cleanup_free_ char *h = NULL;
60f067b4 184 sd_id128_t x, y;
60f067b4 185 int r;
60f067b4
JS
186
187 assert(c);
188 assert(c->parameter);
189 assert(c->type == CONDITION_HOST);
190
191 if (sd_id128_from_string(c->parameter, &x) >= 0) {
192
193 r = sd_id128_get_machine(&y);
194 if (r < 0)
195 return c->negate;
196
197 return sd_id128_equal(x, y) == !c->negate;
198 }
199
200 h = gethostname_malloc();
201 if (!h)
202 return c->negate;
203
e842803a 204 return (fnmatch(c->parameter, h, FNM_CASEFOLD) == 0) == !c->negate;
60f067b4
JS
205}
206
207bool condition_test_ac_power(Condition *c) {
208 int r;
209
210 assert(c);
211 assert(c->parameter);
212 assert(c->type == CONDITION_AC_POWER);
213
214 r = parse_boolean(c->parameter);
215 if (r < 0)
216 return !c->negate;
217
218 return ((on_ac_power() != 0) == !!r) == !c->negate;
219}
220
221void condition_dump(Condition *c, FILE *f, const char *prefix) {
222 assert(c);
223 assert(f);
224
225 if (!prefix)
226 prefix = "";
227
228 fprintf(f,
229 "%s\t%s: %s%s%s %s\n",
230 prefix,
231 condition_type_to_string(c->type),
232 c->trigger ? "|" : "",
233 c->negate ? "!" : "",
234 c->parameter,
235 c->state < 0 ? "failed" : c->state > 0 ? "succeeded" : "untested");
236}
237
238void condition_dump_list(Condition *first, FILE *f, const char *prefix) {
239 Condition *c;
240
241 LIST_FOREACH(conditions, c, first)
242 condition_dump(c, f, prefix);
243}
244
245static const char* const condition_type_table[_CONDITION_TYPE_MAX] = {
246 [CONDITION_PATH_EXISTS] = "ConditionPathExists",
247 [CONDITION_PATH_EXISTS_GLOB] = "ConditionPathExistsGlob",
248 [CONDITION_PATH_IS_DIRECTORY] = "ConditionPathIsDirectory",
249 [CONDITION_PATH_IS_SYMBOLIC_LINK] = "ConditionPathIsSymbolicLink",
250 [CONDITION_PATH_IS_MOUNT_POINT] = "ConditionPathIsMountPoint",
251 [CONDITION_PATH_IS_READ_WRITE] = "ConditionPathIsReadWrite",
252 [CONDITION_DIRECTORY_NOT_EMPTY] = "ConditionDirectoryNotEmpty",
253 [CONDITION_FILE_NOT_EMPTY] = "ConditionFileNotEmpty",
254 [CONDITION_FILE_IS_EXECUTABLE] = "ConditionFileIsExecutable",
255 [CONDITION_KERNEL_COMMAND_LINE] = "ConditionKernelCommandLine",
256 [CONDITION_VIRTUALIZATION] = "ConditionVirtualization",
257 [CONDITION_SECURITY] = "ConditionSecurity",
258 [CONDITION_CAPABILITY] = "ConditionCapability",
259 [CONDITION_HOST] = "ConditionHost",
260 [CONDITION_AC_POWER] = "ConditionACPower",
261 [CONDITION_ARCHITECTURE] = "ConditionArchitecture",
e842803a 262 [CONDITION_NEEDS_UPDATE] = "ConditionNeedsUpdate",
5eef597e 263 [CONDITION_FIRST_BOOT] = "ConditionFirstBoot",
60f067b4
JS
264 [CONDITION_NULL] = "ConditionNull"
265};
266
267DEFINE_STRING_TABLE_LOOKUP(condition_type, ConditionType);