chiark / gitweb /
virt: make Virtualization an anonymous enum
[elogind.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);