]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/condition.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / shared / condition.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
b77c08e0
TG
2/***
3 This file is part of systemd.
4
5 Copyright 2010 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
b77c08e0 21#include <errno.h>
a8fbdf54 22#include <fcntl.h>
84ac7bea 23#include <fnmatch.h>
a8fbdf54 24#include <limits.h>
84ac7bea 25#include <stdlib.h>
b77c08e0 26#include <string.h>
a8fbdf54 27#include <sys/stat.h>
c465a29f 28#include <sys/types.h>
a8fbdf54 29#include <time.h>
b77c08e0 30#include <unistd.h>
b77c08e0 31
d1bddcec 32#include "sd-id128.h"
84ac7bea 33
b5efdb8a 34#include "alloc-util.h"
d1bddcec 35#include "apparmor-util.h"
84ac7bea 36#include "architecture.h"
430f0182 37#include "audit-util.h"
2822da4f 38#include "cap-list.h"
3ffd4af2 39#include "condition.h"
84ac7bea 40#include "extract-word.h"
3ffd4af2 41#include "fd-util.h"
fb8b0869 42#include "fileio.h"
7d50b32a 43#include "glob-util.h"
958b66ea 44#include "hostname-util.h"
84ac7bea 45#include "ima-util.h"
a8fbdf54
TA
46#include "list.h"
47#include "macro.h"
4349cd7c 48#include "mount-util.h"
6bedfcbb 49#include "parse-util.h"
84ac7bea 50#include "path-util.h"
4e731273 51#include "proc-cmdline.h"
df0ff127 52#include "process-util.h"
84ac7bea
LP
53#include "selinux-util.h"
54#include "smack-util.h"
8fcde012 55#include "stat-util.h"
8b43440b 56#include "string-table.h"
07630cea 57#include "string-util.h"
ed440f6b 58#include "tomoyo-util.h"
c465a29f 59#include "user-util.h"
84ac7bea
LP
60#include "util.h"
61#include "virt.h"
b77c08e0
TG
62
63Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate) {
64 Condition *c;
d1bddcec 65 int r;
b77c08e0 66
b80ba1da 67 assert(type >= 0);
b77c08e0 68 assert(type < _CONDITION_TYPE_MAX);
8a9c6071 69 assert((!parameter) == (type == CONDITION_NULL));
b77c08e0
TG
70
71 c = new0(Condition, 1);
72 if (!c)
73 return NULL;
74
75 c->type = type;
76 c->trigger = trigger;
77 c->negate = negate;
78
d1bddcec
LP
79 r = free_and_strdup(&c->parameter, parameter);
80 if (r < 0) {
81 free(c);
82 return NULL;
b77c08e0
TG
83 }
84
85 return c;
86}
87
88void condition_free(Condition *c) {
89 assert(c);
90
91 free(c->parameter);
92 free(c);
93}
94
447021aa 95Condition* condition_free_list(Condition *first) {
b77c08e0
TG
96 Condition *c, *n;
97
98 LIST_FOREACH_SAFE(conditions, c, n, first)
99 condition_free(c);
447021aa
ZJS
100
101 return NULL;
b77c08e0
TG
102}
103
a4705396 104static int condition_test_kernel_command_line(Condition *c) {
07318c29
LP
105 _cleanup_free_ char *line = NULL;
106 const char *p;
b77c08e0
TG
107 bool equal;
108 int r;
b77c08e0
TG
109
110 assert(c);
111 assert(c->parameter);
112 assert(c->type == CONDITION_KERNEL_COMMAND_LINE);
113
114 r = proc_cmdline(&line);
115 if (r < 0)
592fd144 116 return r;
b77c08e0
TG
117
118 equal = !!strchr(c->parameter, '=');
07318c29 119
c58bd76a 120 for (p = line;;) {
07318c29
LP
121 _cleanup_free_ char *word = NULL;
122 bool found;
123
12ba2c44 124 r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX);
592fd144
LP
125 if (r < 0)
126 return r;
127 if (r == 0)
a4705396 128 break;
07318c29
LP
129
130 if (equal)
131 found = streq(word, c->parameter);
132 else {
133 const char *f;
134
135 f = startswith(word, c->parameter);
4c701096 136 found = f && IN_SET(*f, 0, '=');
b77c08e0
TG
137 }
138
07318c29 139 if (found)
a4705396 140 return true;
b77c08e0 141 }
b77c08e0 142
a4705396 143 return false;
b77c08e0
TG
144}
145
c465a29f
FS
146static int condition_test_user(Condition *c) {
147 uid_t id;
148 int r;
149 _cleanup_free_ char *username = NULL;
150 const char *u;
151
152 assert(c);
153 assert(c->parameter);
154 assert(c->type == CONDITION_USER);
155
156 r = parse_uid(c->parameter, &id);
157 if (r >= 0)
158 return id == getuid() || id == geteuid();
159
534bab66
FS
160 if (streq("@system", c->parameter))
161 return getuid() <= SYSTEM_UID_MAX || geteuid() <= SYSTEM_UID_MAX;
162
c465a29f
FS
163 username = getusername_malloc();
164 if (!username)
165 return -ENOMEM;
166
167 if (streq(username, c->parameter))
168 return 1;
169
df0ff127 170 if (getpid_cached() == 1)
c465a29f
FS
171 return streq(c->parameter, "root");
172
173 u = c->parameter;
174 r = get_user_creds(&u, &id, NULL, NULL, NULL);
175 if (r < 0)
176 return 0;
177
178 return id == getuid() || id == geteuid();
179}
180
181static int condition_test_group(Condition *c) {
182 gid_t id;
183 int r;
184
185 assert(c);
186 assert(c->parameter);
187 assert(c->type == CONDITION_GROUP);
188
189 r = parse_gid(c->parameter, &id);
190 if (r >= 0)
191 return in_gid(id);
192
193 /* Avoid any NSS lookups if we are PID1 */
df0ff127 194 if (getpid_cached() == 1)
c465a29f
FS
195 return streq(c->parameter, "root");
196
197 return in_group(c->parameter) > 0;
198}
199
a4705396 200static int condition_test_virtualization(Condition *c) {
248fab74 201 int b, v;
b77c08e0
TG
202
203 assert(c);
204 assert(c->parameter);
205 assert(c->type == CONDITION_VIRTUALIZATION);
206
239a5707
ZJS
207 if (streq(c->parameter, "private-users"))
208 return running_in_userns();
209
75f86906 210 v = detect_virtualization();
592fd144
LP
211 if (v < 0)
212 return v;
b77c08e0
TG
213
214 /* First, compare with yes/no */
215 b = parse_boolean(c->parameter);
0809d774
ZJS
216 if (b >= 0)
217 return b == !!v;
b77c08e0
TG
218
219 /* Then, compare categorization */
0809d774
ZJS
220 if (streq(c->parameter, "vm"))
221 return VIRTUALIZATION_IS_VM(v);
b77c08e0 222
0809d774
ZJS
223 if (streq(c->parameter, "container"))
224 return VIRTUALIZATION_IS_CONTAINER(v);
b77c08e0
TG
225
226 /* Finally compare id */
75f86906 227 return v != VIRTUALIZATION_NONE && streq(c->parameter, virtualization_to_string(v));
b77c08e0
TG
228}
229
a4705396 230static int condition_test_architecture(Condition *c) {
592fd144 231 int a, b;
099524d7
LP
232
233 assert(c);
234 assert(c->parameter);
235 assert(c->type == CONDITION_ARCHITECTURE);
236
237 a = uname_architecture();
238 if (a < 0)
592fd144 239 return a;
099524d7
LP
240
241 if (streq(c->parameter, "native"))
242 b = native_architecture();
2cb62395 243 else {
099524d7 244 b = architecture_from_string(c->parameter);
2cb62395
LP
245 if (b < 0) /* unknown architecture? Then it's definitely not ours */
246 return false;
247 }
099524d7 248
a4705396 249 return a == b;
099524d7
LP
250}
251
a4705396 252static int condition_test_host(Condition *c) {
dc92e62c 253 _cleanup_free_ char *h = NULL;
b77c08e0 254 sd_id128_t x, y;
b77c08e0 255 int r;
b77c08e0
TG
256
257 assert(c);
258 assert(c->parameter);
259 assert(c->type == CONDITION_HOST);
260
261 if (sd_id128_from_string(c->parameter, &x) >= 0) {
262
263 r = sd_id128_get_machine(&y);
264 if (r < 0)
592fd144 265 return r;
b77c08e0 266
a4705396 267 return sd_id128_equal(x, y);
b77c08e0
TG
268 }
269
270 h = gethostname_malloc();
271 if (!h)
592fd144 272 return -ENOMEM;
b77c08e0 273
a4705396 274 return fnmatch(c->parameter, h, FNM_CASEFOLD) == 0;
b77c08e0
TG
275}
276
a4705396 277static int condition_test_ac_power(Condition *c) {
b77c08e0
TG
278 int r;
279
280 assert(c);
281 assert(c->parameter);
282 assert(c->type == CONDITION_AC_POWER);
283
284 r = parse_boolean(c->parameter);
285 if (r < 0)
592fd144 286 return r;
b77c08e0 287
a4705396 288 return (on_ac_power() != 0) == !!r;
b77c08e0
TG
289}
290
d1bddcec
LP
291static int condition_test_security(Condition *c) {
292 assert(c);
293 assert(c->parameter);
294 assert(c->type == CONDITION_SECURITY);
295
296 if (streq(c->parameter, "selinux"))
6d395665 297 return mac_selinux_use();
d1bddcec 298 if (streq(c->parameter, "smack"))
a4705396 299 return mac_smack_use();
d1bddcec 300 if (streq(c->parameter, "apparmor"))
a4705396 301 return mac_apparmor_use();
d1bddcec 302 if (streq(c->parameter, "audit"))
a4705396 303 return use_audit();
d1bddcec 304 if (streq(c->parameter, "ima"))
a4705396 305 return use_ima();
ed440f6b
SL
306 if (streq(c->parameter, "tomoyo"))
307 return mac_tomoyo_use();
d1bddcec 308
a4705396 309 return false;
d1bddcec
LP
310}
311
312static int condition_test_capability(Condition *c) {
313 _cleanup_fclose_ FILE *f = NULL;
2822da4f 314 int value;
d1bddcec
LP
315 char line[LINE_MAX];
316 unsigned long long capabilities = -1;
317
318 assert(c);
319 assert(c->parameter);
320 assert(c->type == CONDITION_CAPABILITY);
321
322 /* If it's an invalid capability, we don't have it */
2822da4f
LP
323 value = capability_from_name(c->parameter);
324 if (value < 0)
d1bddcec
LP
325 return -EINVAL;
326
327 /* If it's a valid capability we default to assume
328 * that we have it */
329
330 f = fopen("/proc/self/status", "re");
331 if (!f)
332 return -errno;
333
334 while (fgets(line, sizeof(line), f)) {
335 truncate_nl(line);
336
337 if (startswith(line, "CapBnd:")) {
338 (void) sscanf(line+7, "%llx", &capabilities);
339 break;
340 }
341 }
342
a4705396 343 return !!(capabilities & (1ULL << value));
d1bddcec
LP
344}
345
346static int condition_test_needs_update(Condition *c) {
347 const char *p;
348 struct stat usr, other;
349
350 assert(c);
351 assert(c->parameter);
352 assert(c->type == CONDITION_NEEDS_UPDATE);
353
354 /* If the file system is read-only we shouldn't suggest an update */
355 if (path_is_read_only_fs(c->parameter) > 0)
a4705396 356 return false;
d1bddcec
LP
357
358 /* Any other failure means we should allow the condition to be true,
96d49011 359 * so that we rather invoke too many update tools than too
d1bddcec
LP
360 * few. */
361
362 if (!path_is_absolute(c->parameter))
a4705396 363 return true;
d1bddcec 364
63c372cb 365 p = strjoina(c->parameter, "/.updated");
d1bddcec 366 if (lstat(p, &other) < 0)
a4705396 367 return true;
d1bddcec
LP
368
369 if (lstat("/usr/", &usr) < 0)
a4705396 370 return true;
d1bddcec 371
fb8b0869
IS
372 /*
373 * First, compare seconds as they are always accurate...
374 */
375 if (usr.st_mtim.tv_sec != other.st_mtim.tv_sec)
376 return usr.st_mtim.tv_sec > other.st_mtim.tv_sec;
377
378 /*
379 * ...then compare nanoseconds.
380 *
381 * A false positive is only possible when /usr's nanoseconds > 0
382 * (otherwise /usr cannot be strictly newer than the target file)
383 * AND the target file's nanoseconds == 0
384 * (otherwise the filesystem supports nsec timestamps, see stat(2)).
385 */
386 if (usr.st_mtim.tv_nsec > 0 && other.st_mtim.tv_nsec == 0) {
387 _cleanup_free_ char *timestamp_str = NULL;
388 uint64_t timestamp;
389 int r;
390
ec2ebfd5 391 r = parse_env_file(p, NULL, "TIMESTAMP_NSEC", &timestamp_str, NULL);
fb8b0869 392 if (r < 0) {
ec2ebfd5 393 log_error_errno(r, "Failed to parse timestamp file '%s', using mtime: %m", p);
fb8b0869
IS
394 return true;
395 } else if (r == 0) {
396 log_debug("No data in timestamp file '%s', using mtime", p);
397 return true;
398 }
399
400 r = safe_atou64(timestamp_str, &timestamp);
401 if (r < 0) {
ec2ebfd5 402 log_error_errno(r, "Failed to parse timestamp value '%s' in file '%s', using mtime: %m", timestamp_str, p);
fb8b0869
IS
403 return true;
404 }
405
ec2ebfd5 406 timespec_store(&other.st_mtim, timestamp);
fb8b0869
IS
407 }
408
409 return usr.st_mtim.tv_nsec > other.st_mtim.tv_nsec;
d1bddcec
LP
410}
411
412static int condition_test_first_boot(Condition *c) {
413 int r;
414
415 assert(c);
416 assert(c->parameter);
417 assert(c->type == CONDITION_FIRST_BOOT);
418
419 r = parse_boolean(c->parameter);
420 if (r < 0)
421 return r;
422
a4705396 423 return (access("/run/systemd/first-boot", F_OK) >= 0) == !!r;
d1bddcec
LP
424}
425
426static int condition_test_path_exists(Condition *c) {
427 assert(c);
428 assert(c->parameter);
429 assert(c->type == CONDITION_PATH_EXISTS);
430
a4705396 431 return access(c->parameter, F_OK) >= 0;
d1bddcec
LP
432}
433
434static int condition_test_path_exists_glob(Condition *c) {
435 assert(c);
436 assert(c->parameter);
437 assert(c->type == CONDITION_PATH_EXISTS_GLOB);
438
a4705396 439 return glob_exists(c->parameter) > 0;
d1bddcec
LP
440}
441
442static int condition_test_path_is_directory(Condition *c) {
443 assert(c);
444 assert(c->parameter);
445 assert(c->type == CONDITION_PATH_IS_DIRECTORY);
446
a4705396 447 return is_dir(c->parameter, true) > 0;
d1bddcec
LP
448}
449
450static int condition_test_path_is_symbolic_link(Condition *c) {
451 assert(c);
452 assert(c->parameter);
453 assert(c->type == CONDITION_PATH_IS_SYMBOLIC_LINK);
454
a4705396 455 return is_symlink(c->parameter) > 0;
d1bddcec
LP
456}
457
458static int condition_test_path_is_mount_point(Condition *c) {
459 assert(c);
460 assert(c->parameter);
461 assert(c->type == CONDITION_PATH_IS_MOUNT_POINT);
462
e1873695 463 return path_is_mount_point(c->parameter, NULL, AT_SYMLINK_FOLLOW) > 0;
d1bddcec
LP
464}
465
466static int condition_test_path_is_read_write(Condition *c) {
467 assert(c);
468 assert(c->parameter);
469 assert(c->type == CONDITION_PATH_IS_READ_WRITE);
470
a4705396 471 return path_is_read_only_fs(c->parameter) <= 0;
d1bddcec
LP
472}
473
474static int condition_test_directory_not_empty(Condition *c) {
475 int r;
476
477 assert(c);
478 assert(c->parameter);
479 assert(c->type == CONDITION_DIRECTORY_NOT_EMPTY);
480
481 r = dir_is_empty(c->parameter);
a4705396 482 return r <= 0 && r != -ENOENT;
d1bddcec
LP
483}
484
485static int condition_test_file_not_empty(Condition *c) {
486 struct stat st;
487
488 assert(c);
489 assert(c->parameter);
490 assert(c->type == CONDITION_FILE_NOT_EMPTY);
491
492 return (stat(c->parameter, &st) >= 0 &&
493 S_ISREG(st.st_mode) &&
a4705396 494 st.st_size > 0);
d1bddcec
LP
495}
496
497static int condition_test_file_is_executable(Condition *c) {
498 struct stat st;
499
500 assert(c);
501 assert(c->parameter);
502 assert(c->type == CONDITION_FILE_IS_EXECUTABLE);
503
504 return (stat(c->parameter, &st) >= 0 &&
505 S_ISREG(st.st_mode) &&
a4705396 506 (st.st_mode & 0111));
d1bddcec
LP
507}
508
509static int condition_test_null(Condition *c) {
510 assert(c);
d1bddcec
LP
511 assert(c->type == CONDITION_NULL);
512
513 /* Note that during parsing we already evaluate the string and
514 * store it in c->negate */
a4705396 515 return true;
d1bddcec
LP
516}
517
518int condition_test(Condition *c) {
519
520 static int (*const condition_tests[_CONDITION_TYPE_MAX])(Condition *c) = {
521 [CONDITION_PATH_EXISTS] = condition_test_path_exists,
522 [CONDITION_PATH_EXISTS_GLOB] = condition_test_path_exists_glob,
523 [CONDITION_PATH_IS_DIRECTORY] = condition_test_path_is_directory,
524 [CONDITION_PATH_IS_SYMBOLIC_LINK] = condition_test_path_is_symbolic_link,
525 [CONDITION_PATH_IS_MOUNT_POINT] = condition_test_path_is_mount_point,
526 [CONDITION_PATH_IS_READ_WRITE] = condition_test_path_is_read_write,
527 [CONDITION_DIRECTORY_NOT_EMPTY] = condition_test_directory_not_empty,
528 [CONDITION_FILE_NOT_EMPTY] = condition_test_file_not_empty,
529 [CONDITION_FILE_IS_EXECUTABLE] = condition_test_file_is_executable,
530 [CONDITION_KERNEL_COMMAND_LINE] = condition_test_kernel_command_line,
531 [CONDITION_VIRTUALIZATION] = condition_test_virtualization,
532 [CONDITION_SECURITY] = condition_test_security,
533 [CONDITION_CAPABILITY] = condition_test_capability,
534 [CONDITION_HOST] = condition_test_host,
535 [CONDITION_AC_POWER] = condition_test_ac_power,
536 [CONDITION_ARCHITECTURE] = condition_test_architecture,
537 [CONDITION_NEEDS_UPDATE] = condition_test_needs_update,
538 [CONDITION_FIRST_BOOT] = condition_test_first_boot,
c465a29f
FS
539 [CONDITION_USER] = condition_test_user,
540 [CONDITION_GROUP] = condition_test_group,
d1bddcec
LP
541 [CONDITION_NULL] = condition_test_null,
542 };
cc50ef13
LP
543
544 int r, b;
d1bddcec
LP
545
546 assert(c);
547 assert(c->type >= 0);
548 assert(c->type < _CONDITION_TYPE_MAX);
549
a4705396 550 r = condition_tests[c->type](c);
cc50ef13
LP
551 if (r < 0) {
552 c->result = CONDITION_ERROR;
a4705396 553 return r;
cc50ef13 554 }
a4705396 555
cc50ef13
LP
556 b = (r > 0) == !c->negate;
557 c->result = b ? CONDITION_SUCCEEDED : CONDITION_FAILED;
558 return b;
d1bddcec
LP
559}
560
59fccdc5 561void condition_dump(Condition *c, FILE *f, const char *prefix, const char *(*to_string)(ConditionType t)) {
b77c08e0
TG
562 assert(c);
563 assert(f);
564
565 if (!prefix)
566 prefix = "";
567
568 fprintf(f,
569 "%s\t%s: %s%s%s %s\n",
570 prefix,
59fccdc5 571 to_string(c->type),
b77c08e0
TG
572 c->trigger ? "|" : "",
573 c->negate ? "!" : "",
574 c->parameter,
cc50ef13 575 condition_result_to_string(c->result));
b77c08e0
TG
576}
577
59fccdc5 578void condition_dump_list(Condition *first, FILE *f, const char *prefix, const char *(*to_string)(ConditionType t)) {
b77c08e0
TG
579 Condition *c;
580
581 LIST_FOREACH(conditions, c, first)
59fccdc5 582 condition_dump(c, f, prefix, to_string);
b77c08e0
TG
583}
584
585static const char* const condition_type_table[_CONDITION_TYPE_MAX] = {
651c3318
LP
586 [CONDITION_ARCHITECTURE] = "ConditionArchitecture",
587 [CONDITION_VIRTUALIZATION] = "ConditionVirtualization",
588 [CONDITION_HOST] = "ConditionHost",
589 [CONDITION_KERNEL_COMMAND_LINE] = "ConditionKernelCommandLine",
590 [CONDITION_SECURITY] = "ConditionSecurity",
591 [CONDITION_CAPABILITY] = "ConditionCapability",
592 [CONDITION_AC_POWER] = "ConditionACPower",
593 [CONDITION_NEEDS_UPDATE] = "ConditionNeedsUpdate",
594 [CONDITION_FIRST_BOOT] = "ConditionFirstBoot",
b77c08e0
TG
595 [CONDITION_PATH_EXISTS] = "ConditionPathExists",
596 [CONDITION_PATH_EXISTS_GLOB] = "ConditionPathExistsGlob",
597 [CONDITION_PATH_IS_DIRECTORY] = "ConditionPathIsDirectory",
598 [CONDITION_PATH_IS_SYMBOLIC_LINK] = "ConditionPathIsSymbolicLink",
599 [CONDITION_PATH_IS_MOUNT_POINT] = "ConditionPathIsMountPoint",
600 [CONDITION_PATH_IS_READ_WRITE] = "ConditionPathIsReadWrite",
601 [CONDITION_DIRECTORY_NOT_EMPTY] = "ConditionDirectoryNotEmpty",
602 [CONDITION_FILE_NOT_EMPTY] = "ConditionFileNotEmpty",
603 [CONDITION_FILE_IS_EXECUTABLE] = "ConditionFileIsExecutable",
c465a29f
FS
604 [CONDITION_USER] = "ConditionUser",
605 [CONDITION_GROUP] = "ConditionGroup",
b77c08e0
TG
606 [CONDITION_NULL] = "ConditionNull"
607};
608
609DEFINE_STRING_TABLE_LOOKUP(condition_type, ConditionType);
cc50ef13 610
59fccdc5 611static const char* const assert_type_table[_CONDITION_TYPE_MAX] = {
651c3318
LP
612 [CONDITION_ARCHITECTURE] = "AssertArchitecture",
613 [CONDITION_VIRTUALIZATION] = "AssertVirtualization",
614 [CONDITION_HOST] = "AssertHost",
615 [CONDITION_KERNEL_COMMAND_LINE] = "AssertKernelCommandLine",
616 [CONDITION_SECURITY] = "AssertSecurity",
617 [CONDITION_CAPABILITY] = "AssertCapability",
618 [CONDITION_AC_POWER] = "AssertACPower",
619 [CONDITION_NEEDS_UPDATE] = "AssertNeedsUpdate",
620 [CONDITION_FIRST_BOOT] = "AssertFirstBoot",
59fccdc5
LP
621 [CONDITION_PATH_EXISTS] = "AssertPathExists",
622 [CONDITION_PATH_EXISTS_GLOB] = "AssertPathExistsGlob",
623 [CONDITION_PATH_IS_DIRECTORY] = "AssertPathIsDirectory",
624 [CONDITION_PATH_IS_SYMBOLIC_LINK] = "AssertPathIsSymbolicLink",
625 [CONDITION_PATH_IS_MOUNT_POINT] = "AssertPathIsMountPoint",
626 [CONDITION_PATH_IS_READ_WRITE] = "AssertPathIsReadWrite",
627 [CONDITION_DIRECTORY_NOT_EMPTY] = "AssertDirectoryNotEmpty",
628 [CONDITION_FILE_NOT_EMPTY] = "AssertFileNotEmpty",
629 [CONDITION_FILE_IS_EXECUTABLE] = "AssertFileIsExecutable",
c465a29f
FS
630 [CONDITION_USER] = "AssertUser",
631 [CONDITION_GROUP] = "AssertGroup",
59fccdc5
LP
632 [CONDITION_NULL] = "AssertNull"
633};
634
635DEFINE_STRING_TABLE_LOOKUP(assert_type, ConditionType);
636
cc50ef13
LP
637static const char* const condition_result_table[_CONDITION_RESULT_MAX] = {
638 [CONDITION_UNTESTED] = "untested",
639 [CONDITION_SUCCEEDED] = "succeeded",
640 [CONDITION_FAILED] = "failed",
641 [CONDITION_ERROR] = "error",
642};
643
644DEFINE_STRING_TABLE_LOOKUP(condition_result, ConditionResult);