chiark / gitweb /
Reject invalid quoted strings
[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
118         free(word);
119         free(line);
120
121         return found == !c->negate;
122 }
123
124 bool condition_test_virtualization(Condition *c) {
125         int b, v;
126         const char *id;
127
128         assert(c);
129         assert(c->parameter);
130         assert(c->type == CONDITION_VIRTUALIZATION);
131
132         v = detect_virtualization(&id);
133         if (v < 0) {
134                 log_warning("Failed to detect virtualization, ignoring: %s", strerror(-v));
135                 return c->negate;
136         }
137
138         /* First, compare with yes/no */
139         b = parse_boolean(c->parameter);
140
141         if (v > 0 && b > 0)
142                 return !c->negate;
143
144         if (v == 0 && b == 0)
145                 return !c->negate;
146
147         /* Then, compare categorization */
148         if (v == VIRTUALIZATION_VM && streq(c->parameter, "vm"))
149                 return !c->negate;
150
151         if (v == VIRTUALIZATION_CONTAINER && streq(c->parameter, "container"))
152                 return !c->negate;
153
154         /* Finally compare id */
155         return (v > 0 && streq(c->parameter, id)) == !c->negate;
156 }
157
158 bool condition_test_architecture(Condition *c) {
159         Architecture a, b;
160
161         assert(c);
162         assert(c->parameter);
163         assert(c->type == CONDITION_ARCHITECTURE);
164
165         a = uname_architecture();
166         if (a < 0)
167                 return c->negate;
168
169         if (streq(c->parameter, "native"))
170                 b = native_architecture();
171         else
172                 b = architecture_from_string(c->parameter);
173
174         if (b < 0)
175                 return c->negate;
176
177         return (a == b) == !c->negate;
178 }
179
180 bool condition_test_host(Condition *c) {
181         _cleanup_free_ char *h = NULL;
182         sd_id128_t x, y;
183         int r;
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         return (fnmatch(c->parameter, h, FNM_CASEFOLD) == 0) == !c->negate;
203 }
204
205 bool condition_test_ac_power(Condition *c) {
206         int r;
207
208         assert(c);
209         assert(c->parameter);
210         assert(c->type == CONDITION_AC_POWER);
211
212         r = parse_boolean(c->parameter);
213         if (r < 0)
214                 return !c->negate;
215
216         return ((on_ac_power() != 0) == !!r) == !c->negate;
217 }
218
219 void condition_dump(Condition *c, FILE *f, const char *prefix) {
220         assert(c);
221         assert(f);
222
223         if (!prefix)
224                 prefix = "";
225
226         fprintf(f,
227                 "%s\t%s: %s%s%s %s\n",
228                 prefix,
229                 condition_type_to_string(c->type),
230                 c->trigger ? "|" : "",
231                 c->negate ? "!" : "",
232                 c->parameter,
233                 c->state < 0 ? "failed" : c->state > 0 ? "succeeded" : "untested");
234 }
235
236 void condition_dump_list(Condition *first, FILE *f, const char *prefix) {
237         Condition *c;
238
239         LIST_FOREACH(conditions, c, first)
240                 condition_dump(c, f, prefix);
241 }
242
243 static const char* const condition_type_table[_CONDITION_TYPE_MAX] = {
244         [CONDITION_PATH_EXISTS] = "ConditionPathExists",
245         [CONDITION_PATH_EXISTS_GLOB] = "ConditionPathExistsGlob",
246         [CONDITION_PATH_IS_DIRECTORY] = "ConditionPathIsDirectory",
247         [CONDITION_PATH_IS_SYMBOLIC_LINK] = "ConditionPathIsSymbolicLink",
248         [CONDITION_PATH_IS_MOUNT_POINT] = "ConditionPathIsMountPoint",
249         [CONDITION_PATH_IS_READ_WRITE] = "ConditionPathIsReadWrite",
250         [CONDITION_DIRECTORY_NOT_EMPTY] = "ConditionDirectoryNotEmpty",
251         [CONDITION_FILE_NOT_EMPTY] = "ConditionFileNotEmpty",
252         [CONDITION_FILE_IS_EXECUTABLE] = "ConditionFileIsExecutable",
253         [CONDITION_KERNEL_COMMAND_LINE] = "ConditionKernelCommandLine",
254         [CONDITION_VIRTUALIZATION] = "ConditionVirtualization",
255         [CONDITION_SECURITY] = "ConditionSecurity",
256         [CONDITION_CAPABILITY] = "ConditionCapability",
257         [CONDITION_HOST] = "ConditionHost",
258         [CONDITION_AC_POWER] = "ConditionACPower",
259         [CONDITION_ARCHITECTURE] = "ConditionArchitecture",
260         [CONDITION_NEEDS_UPDATE] = "ConditionNeedsUpdate",
261         [CONDITION_FIRST_BOOT] = "ConditionFirstBoot",
262         [CONDITION_NULL] = "ConditionNull"
263 };
264
265 DEFINE_STRING_TABLE_LOOKUP(condition_type, ConditionType);