chiark / gitweb /
exit-status: fix URL in comment
[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, *word = NULL;
78         const char *w, *state;
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         }
117         if (!isempty(state))
118                 log_warning("Trailing garbage and the end of kernel commandline, ignoring.");
119
120         free(word);
121         free(line);
122
123         return found == !c->negate;
124 }
125
126 bool 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
160 bool 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
182 bool condition_test_host(Condition *c) {
183         _cleanup_free_ char *h = NULL;
184         sd_id128_t x, y;
185         int r;
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
204         return (fnmatch(c->parameter, h, FNM_CASEFOLD) == 0) == !c->negate;
205 }
206
207 bool 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
221 void 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
238 void 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
245 static 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",
262         [CONDITION_NEEDS_UPDATE] = "ConditionNeedsUpdate",
263         [CONDITION_FIRST_BOOT] = "ConditionFirstBoot",
264         [CONDITION_NULL] = "ConditionNull"
265 };
266
267 DEFINE_STRING_TABLE_LOOKUP(condition_type, ConditionType);