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