]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/condition.c
build-sys: prefer using ln --relative -s where appropriate
[thirdparty/systemd.git] / src / core / condition.c
CommitLineData
52661efd
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
f23c09b0 6 Copyright 2010 Lennart Poettering
52661efd
LP
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
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
52661efd
LP
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
5430f7f2 16 Lesser General Public License for more details.
52661efd 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
52661efd
LP
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>
62590f23 26#include <sys/capability.h>
d0516109 27#include <sys/statvfs.h>
c0d6e764 28#include <fnmatch.h>
52661efd 29
c0d6e764 30#include <systemd/sd-id128.h>
52661efd
LP
31#include "util.h"
32#include "condition.h"
8095200d 33#include "virt.h"
9eb977db 34#include "path-util.h"
a5c32cff 35#include "fileio.h"
4b744dfa 36#include "unit.h"
d682b3a7
LP
37#include "smack-util.h"
38#include "apparmor-util.h"
39#include "ima-util.h"
40#include "selinux-util.h"
52661efd 41
afc50ea8
TG
42static bool condition_test_security(Condition *c) {
43 assert(c);
44 assert(c->parameter);
45 assert(c->type == CONDITION_SECURITY);
46
47 if (streq(c->parameter, "selinux"))
48 return use_selinux() == !c->negate;
49 if (streq(c->parameter, "apparmor"))
50 return use_apparmor() == !c->negate;
51 if (streq(c->parameter, "ima"))
52 return use_ima() == !c->negate;
53 if (streq(c->parameter, "smack"))
54 return use_smack() == !c->negate;
55 return c->negate;
07e833bc
MS
56}
57
afc50ea8 58static bool condition_test_capability(Condition *c) {
62590f23
LP
59 cap_value_t value;
60 FILE *f;
61 char line[LINE_MAX];
62 unsigned long long capabilities = (unsigned long long) -1;
63
afc50ea8
TG
64 assert(c);
65 assert(c->parameter);
66 assert(c->type == CONDITION_CAPABILITY);
67
62590f23
LP
68 /* If it's an invalid capability, we don't have it */
69
afc50ea8
TG
70 if (cap_from_name(c->parameter, &value) < 0)
71 return c->negate;
62590f23
LP
72
73 /* If it's a valid capability we default to assume
74 * that we have it */
75
76 f = fopen("/proc/self/status", "re");
77 if (!f)
afc50ea8 78 return !c->negate;
62590f23
LP
79
80 while (fgets(line, sizeof(line), f)) {
81 truncate_nl(line);
82
83 if (startswith(line, "CapBnd:")) {
84 (void) sscanf(line+7, "%llx", &capabilities);
85 break;
86 }
87 }
88
7670e5a2
TJ
89 fclose(f);
90
afc50ea8 91 return !!(capabilities & (1ULL << value)) == !c->negate;
62590f23
LP
92}
93
52990c2e 94static bool condition_test(Condition *c) {
52661efd
LP
95 assert(c);
96
97 switch(c->type) {
98
99 case CONDITION_PATH_EXISTS:
100 return (access(c->parameter, F_OK) >= 0) == !c->negate;
101
8092a428
LP
102 case CONDITION_PATH_EXISTS_GLOB:
103 return (glob_exists(c->parameter) > 0) == !c->negate;
104
2b583ce6
KS
105 case CONDITION_PATH_IS_DIRECTORY: {
106 struct stat st;
107
8571962c 108 if (stat(c->parameter, &st) < 0)
1f8fef5a 109 return c->negate;
2b583ce6
KS
110 return S_ISDIR(st.st_mode) == !c->negate;
111 }
112
0d60602c
MS
113 case CONDITION_PATH_IS_SYMBOLIC_LINK: {
114 struct stat st;
115
116 if (lstat(c->parameter, &st) < 0)
1f8fef5a 117 return c->negate;
0d60602c
MS
118 return S_ISLNK(st.st_mode) == !c->negate;
119 }
120
ab7f148f
LP
121 case CONDITION_PATH_IS_MOUNT_POINT:
122 return (path_is_mount_point(c->parameter, true) > 0) == !c->negate;
123
3d9a4122
LP
124 case CONDITION_PATH_IS_READ_WRITE:
125 return (path_is_read_only_fs(c->parameter) > 0) == c->negate;
d0516109 126
36af55d9
LP
127 case CONDITION_DIRECTORY_NOT_EMPTY: {
128 int k;
129
130 k = dir_is_empty(c->parameter);
131 return !(k == -ENOENT || k > 0) == !c->negate;
132 }
133
742a862b
LP
134 case CONDITION_FILE_NOT_EMPTY: {
135 struct stat st;
136
137 if (stat(c->parameter, &st) < 0)
138 return c->negate;
139
140 return (S_ISREG(st.st_mode) && st.st_size > 0) == !c->negate;
141 }
142
82e487c5
LP
143 case CONDITION_FILE_IS_EXECUTABLE: {
144 struct stat st;
145
34a2dc4b 146 if (stat(c->parameter, &st) < 0)
1f8fef5a 147 return c->negate;
82e487c5
LP
148
149 return (S_ISREG(st.st_mode) && (st.st_mode & 0111)) == !c->negate;
150 }
151
52661efd 152 case CONDITION_KERNEL_COMMAND_LINE:
afc50ea8 153 return condition_test_kernel_command_line(c);
52661efd 154
039655a4 155 case CONDITION_VIRTUALIZATION:
afc50ea8 156 return condition_test_virtualization(c);
039655a4 157
07e833bc 158 case CONDITION_SECURITY:
afc50ea8 159 return condition_test_security(c);
07e833bc 160
62590f23 161 case CONDITION_CAPABILITY:
afc50ea8 162 return condition_test_capability(c);
62590f23 163
c0d6e764 164 case CONDITION_HOST:
afc50ea8 165 return condition_test_host(c);
c0d6e764 166
240dbaa4 167 case CONDITION_AC_POWER:
afc50ea8 168 return condition_test_ac_power(c);
240dbaa4 169
099524d7
LP
170 case CONDITION_ARCHITECTURE:
171 return condition_test_architecture(c);
172
d257ddef
LP
173 case CONDITION_NULL:
174 return !c->negate;
175
52661efd
LP
176 default:
177 assert_not_reached("Invalid condition type.");
178 }
179}
180
4b744dfa 181bool condition_test_list(const char *unit, Condition *first) {
52661efd 182 Condition *c;
267632f0 183 int triggered = -1;
52661efd
LP
184
185 /* If the condition list is empty, then it is true */
186 if (!first)
187 return true;
188
267632f0
LP
189 /* Otherwise, if all of the non-trigger conditions apply and
190 * if any of the trigger conditions apply (unless there are
191 * none) we return true */
192 LIST_FOREACH(conditions, c, first) {
193 bool b;
194
195 b = condition_test(c);
4b744dfa
ZJS
196 if (unit)
197 log_debug_unit(unit,
198 "%s=%s%s%s %s for %s.",
199 condition_type_to_string(c->type),
200 c->trigger ? "|" : "",
201 c->negate ? "!" : "",
202 c->parameter,
203 b ? "succeeded" : "failed",
204 unit);
52990c2e 205 c->state = b ? 1 : -1;
267632f0
LP
206
207 if (!c->trigger && !b)
208 return false;
209
210 if (c->trigger && triggered <= 0)
211 triggered = b;
212 }
52661efd 213
267632f0 214 return triggered != 0;
52661efd 215}