]>
Commit | Line | Data |
---|---|---|
4ad49000 LP |
1 | /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ |
2 | ||
3 | /*** | |
4 | This file is part of systemd. | |
5 | ||
6 | Copyright 2013 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 | ||
718db961 | 22 | #include "bus-util.h" |
7041efe9 | 23 | #include "path-util.h" |
718db961 LP |
24 | #include "cgroup-util.h" |
25 | #include "cgroup.h" | |
4ad49000 LP |
26 | #include "dbus-cgroup.h" |
27 | ||
718db961 LP |
28 | static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy, cgroup_device_policy, CGroupDevicePolicy); |
29 | ||
30 | static int property_get_blockio_device_weight( | |
31 | sd_bus *bus, | |
32 | const char *path, | |
33 | const char *interface, | |
34 | const char *property, | |
35 | sd_bus_message *reply, | |
ebcf1f97 LP |
36 | void *userdata, |
37 | sd_bus_error *error) { | |
4ad49000 | 38 | |
718db961 | 39 | CGroupContext *c = userdata; |
4ad49000 | 40 | CGroupBlockIODeviceWeight *w; |
718db961 | 41 | int r; |
4ad49000 | 42 | |
718db961 LP |
43 | assert(bus); |
44 | assert(reply); | |
4ad49000 LP |
45 | assert(c); |
46 | ||
718db961 LP |
47 | r = sd_bus_message_open_container(reply, 'a', "(st)"); |
48 | if (r < 0) | |
49 | return r; | |
4ad49000 LP |
50 | |
51 | LIST_FOREACH(device_weights, w, c->blockio_device_weights) { | |
718db961 LP |
52 | r = sd_bus_message_append(reply, "(st)", w->path, w->weight); |
53 | if (r < 0) | |
54 | return r; | |
4ad49000 LP |
55 | } |
56 | ||
718db961 | 57 | return sd_bus_message_close_container(reply); |
4ad49000 LP |
58 | } |
59 | ||
718db961 LP |
60 | static int property_get_blockio_device_bandwidths( |
61 | sd_bus *bus, | |
62 | const char *path, | |
63 | const char *interface, | |
64 | const char *property, | |
65 | sd_bus_message *reply, | |
ebcf1f97 LP |
66 | void *userdata, |
67 | sd_bus_error *error) { | |
718db961 LP |
68 | |
69 | CGroupContext *c = userdata; | |
4ad49000 | 70 | CGroupBlockIODeviceBandwidth *b; |
718db961 | 71 | int r; |
4ad49000 | 72 | |
718db961 LP |
73 | assert(bus); |
74 | assert(reply); | |
4ad49000 LP |
75 | assert(c); |
76 | ||
718db961 LP |
77 | r = sd_bus_message_open_container(reply, 'a', "(st)"); |
78 | if (r < 0) | |
79 | return r; | |
4ad49000 LP |
80 | |
81 | LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) { | |
82 | ||
83 | if (streq(property, "BlockIOReadBandwidth") != b->read) | |
84 | continue; | |
85 | ||
718db961 LP |
86 | r = sd_bus_message_append(reply, "(st)", b->path, b->bandwidth); |
87 | if (r < 0) | |
88 | return r; | |
4ad49000 LP |
89 | } |
90 | ||
718db961 | 91 | return sd_bus_message_close_container(reply); |
4ad49000 LP |
92 | } |
93 | ||
718db961 LP |
94 | static int property_get_device_allow( |
95 | sd_bus *bus, | |
96 | const char *path, | |
97 | const char *interface, | |
98 | const char *property, | |
99 | sd_bus_message *reply, | |
ebcf1f97 LP |
100 | void *userdata, |
101 | sd_bus_error *error) { | |
718db961 LP |
102 | |
103 | CGroupContext *c = userdata; | |
4ad49000 | 104 | CGroupDeviceAllow *a; |
718db961 | 105 | int r; |
4ad49000 | 106 | |
718db961 LP |
107 | assert(bus); |
108 | assert(reply); | |
4ad49000 LP |
109 | assert(c); |
110 | ||
718db961 LP |
111 | r = sd_bus_message_open_container(reply, 'a', "(ss)"); |
112 | if (r < 0) | |
113 | return r; | |
4ad49000 LP |
114 | |
115 | LIST_FOREACH(device_allow, a, c->device_allow) { | |
4ad49000 | 116 | unsigned k = 0; |
718db961 | 117 | char rwm[4]; |
4ad49000 LP |
118 | |
119 | if (a->r) | |
718db961 | 120 | rwm[k++] = 'r'; |
4ad49000 | 121 | if (a->w) |
718db961 | 122 | rwm[k++] = 'w'; |
4ad49000 | 123 | if (a->m) |
718db961 | 124 | rwm[k++] = 'm'; |
4ad49000 | 125 | |
718db961 | 126 | rwm[k] = 0; |
4ad49000 | 127 | |
718db961 LP |
128 | r = sd_bus_message_append(reply, "(ss)", a->path, rwm); |
129 | if (r < 0) | |
130 | return r; | |
4ad49000 LP |
131 | } |
132 | ||
718db961 | 133 | return sd_bus_message_close_container(reply); |
4ad49000 LP |
134 | } |
135 | ||
718db961 LP |
136 | const sd_bus_vtable bus_cgroup_vtable[] = { |
137 | SD_BUS_VTABLE_START(0), | |
610f780c LP |
138 | SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, cpu_accounting), 0), |
139 | SD_BUS_PROPERTY("CPUShares", "t", bus_property_get_ulong, offsetof(CGroupContext, cpu_shares), 0), | |
140 | SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, blockio_accounting), 0), | |
141 | SD_BUS_PROPERTY("BlockIOWeight", "t", bus_property_get_ulong, offsetof(CGroupContext, blockio_weight), 0), | |
142 | SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_device_weight, 0, 0), | |
143 | SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0), | |
144 | SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0), | |
145 | SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, memory_accounting), 0), | |
146 | SD_BUS_PROPERTY("MemoryLimit", "t", NULL, offsetof(CGroupContext, memory_limit), 0), | |
147 | SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy, offsetof(CGroupContext, device_policy), 0), | |
148 | SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow, 0, 0), | |
718db961 | 149 | SD_BUS_VTABLE_END |
4ad49000 | 150 | }; |
8e2af478 LP |
151 | |
152 | int bus_cgroup_set_property( | |
153 | Unit *u, | |
154 | CGroupContext *c, | |
155 | const char *name, | |
718db961 | 156 | sd_bus_message *message, |
8e2af478 | 157 | UnitSetPropertiesMode mode, |
718db961 LP |
158 | sd_bus_error *error) { |
159 | ||
160 | int r; | |
8e2af478 | 161 | |
8e2af478 LP |
162 | assert(u); |
163 | assert(c); | |
718db961 LP |
164 | assert(name); |
165 | assert(message); | |
8e2af478 LP |
166 | |
167 | if (streq(name, "CPUAccounting")) { | |
718db961 | 168 | int b; |
8e2af478 | 169 | |
718db961 LP |
170 | r = sd_bus_message_read(message, "b", &b); |
171 | if (r < 0) | |
172 | return r; | |
8e2af478 LP |
173 | |
174 | if (mode != UNIT_CHECK) { | |
8e2af478 | 175 | c->cpu_accounting = b; |
3051f187 | 176 | u->cgroup_realized_mask &= ~CGROUP_CPUACCT; |
b9ec9359 | 177 | unit_write_drop_in_private(u, mode, name, b ? "CPUAccounting=yes" : "CPUAccounting=no"); |
b42defe3 LP |
178 | } |
179 | ||
180 | return 1; | |
181 | ||
182 | } else if (streq(name, "CPUShares")) { | |
183 | uint64_t u64; | |
184 | unsigned long ul; | |
185 | ||
718db961 LP |
186 | r = sd_bus_message_read(message, "t", &u64); |
187 | if (r < 0) | |
188 | return r; | |
b42defe3 | 189 | |
b42defe3 | 190 | ul = (unsigned long) u64; |
718db961 LP |
191 | if (ul <= 0 || (uint64_t) ul != u64) |
192 | return sd_bus_error_set_errnof(error, EINVAL, "CPUShares value out of range"); | |
b42defe3 LP |
193 | |
194 | if (mode != UNIT_CHECK) { | |
b42defe3 | 195 | c->cpu_shares = ul; |
3051f187 | 196 | u->cgroup_realized_mask &= ~CGROUP_CPU; |
b9ec9359 | 197 | unit_write_drop_in_private_format(u, mode, name, "CPUShares=%lu", ul); |
8e2af478 LP |
198 | } |
199 | ||
200 | return 1; | |
201 | ||
202 | } else if (streq(name, "BlockIOAccounting")) { | |
718db961 | 203 | int b; |
8e2af478 | 204 | |
718db961 LP |
205 | r = sd_bus_message_read(message, "b", &b); |
206 | if (r < 0) | |
207 | return r; | |
8e2af478 LP |
208 | |
209 | if (mode != UNIT_CHECK) { | |
8e2af478 | 210 | c->blockio_accounting = b; |
3051f187 | 211 | u->cgroup_realized_mask &= ~CGROUP_BLKIO; |
b9ec9359 | 212 | unit_write_drop_in_private(u, mode, name, b ? "BlockIOAccounting=yes" : "BlockIOAccounting=no"); |
8e2af478 LP |
213 | } |
214 | ||
215 | return 1; | |
b42defe3 LP |
216 | |
217 | } else if (streq(name, "BlockIOWeight")) { | |
218 | uint64_t u64; | |
219 | unsigned long ul; | |
220 | ||
718db961 LP |
221 | r = sd_bus_message_read(message, "t", &u64); |
222 | if (r < 0) | |
223 | return r; | |
b42defe3 | 224 | |
b42defe3 | 225 | ul = (unsigned long) u64; |
718db961 LP |
226 | if (ul < 10 || ul > 1000) |
227 | return sd_bus_error_set_errnof(error, EINVAL, "BlockIOWeight value out of range"); | |
b42defe3 LP |
228 | |
229 | if (mode != UNIT_CHECK) { | |
f2369103 | 230 | c->blockio_weight = ul; |
3051f187 | 231 | u->cgroup_realized_mask &= ~CGROUP_BLKIO; |
b9ec9359 | 232 | unit_write_drop_in_private_format(u, mode, name, "BlockIOWeight=%lu", ul); |
b42defe3 LP |
233 | } |
234 | ||
235 | return 1; | |
236 | ||
f004c2ca | 237 | } else if (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth")) { |
718db961 | 238 | const char *path; |
f004c2ca | 239 | bool read = true; |
718db961 LP |
240 | unsigned n = 0; |
241 | uint64_t u64; | |
f004c2ca G |
242 | |
243 | if (streq(name, "BlockIOWriteBandwidth")) | |
244 | read = false; | |
245 | ||
718db961 LP |
246 | r = sd_bus_message_enter_container(message, 'a', "(st)"); |
247 | if (r < 0) | |
248 | return r; | |
f004c2ca | 249 | |
718db961 | 250 | while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) { |
f004c2ca G |
251 | |
252 | if (mode != UNIT_CHECK) { | |
718db961 | 253 | CGroupBlockIODeviceBandwidth *a = NULL, *b; |
f004c2ca G |
254 | |
255 | LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) { | |
256 | if (path_equal(path, b->path) && read == b->read) { | |
257 | a = b; | |
f004c2ca G |
258 | break; |
259 | } | |
260 | } | |
261 | ||
718db961 | 262 | if (!a) { |
f004c2ca G |
263 | a = new0(CGroupBlockIODeviceBandwidth, 1); |
264 | if (!a) | |
265 | return -ENOMEM; | |
266 | ||
267 | a->read = read; | |
268 | a->path = strdup(path); | |
269 | if (!a->path) { | |
270 | free(a); | |
271 | return -ENOMEM; | |
272 | } | |
718db961 LP |
273 | |
274 | LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, a); | |
f004c2ca G |
275 | } |
276 | ||
277 | a->bandwidth = u64; | |
f004c2ca G |
278 | } |
279 | ||
280 | n++; | |
f004c2ca | 281 | } |
718db961 LP |
282 | if (r < 0) |
283 | return r; | |
f004c2ca | 284 | |
9c96019d LP |
285 | r = sd_bus_message_exit_container(message); |
286 | if (r < 0) | |
287 | return r; | |
288 | ||
f004c2ca | 289 | if (mode != UNIT_CHECK) { |
718db961 | 290 | CGroupBlockIODeviceBandwidth *a, *next; |
f004c2ca G |
291 | _cleanup_free_ char *buf = NULL; |
292 | _cleanup_fclose_ FILE *f = NULL; | |
f004c2ca G |
293 | size_t size = 0; |
294 | ||
295 | if (n == 0) { | |
296 | LIST_FOREACH_SAFE(device_bandwidths, a, next, c->blockio_device_bandwidths) | |
297 | if (a->read == read) | |
298 | cgroup_context_free_blockio_device_bandwidth(c, a); | |
299 | } | |
300 | ||
3051f187 LP |
301 | u->cgroup_realized_mask &= ~CGROUP_BLKIO; |
302 | ||
f004c2ca G |
303 | f = open_memstream(&buf, &size); |
304 | if (!f) | |
305 | return -ENOMEM; | |
306 | ||
307 | if (read) { | |
308 | fputs("BlockIOReadBandwidth=\n", f); | |
309 | LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths) | |
310 | if (a->read) | |
311 | fprintf(f, "BlockIOReadBandwidth=%s %" PRIu64 "\n", a->path, a->bandwidth); | |
312 | } else { | |
313 | fputs("BlockIOWriteBandwidth=\n", f); | |
314 | LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths) | |
315 | if (!a->read) | |
316 | fprintf(f, "BlockIOWriteBandwidth=%s %" PRIu64 "\n", a->path, a->bandwidth); | |
317 | } | |
318 | ||
6f68ecb4 G |
319 | fflush(f); |
320 | unit_write_drop_in_private(u, mode, name, buf); | |
321 | } | |
322 | ||
323 | return 1; | |
324 | ||
325 | } else if (streq(name, "BlockIODeviceWeight")) { | |
718db961 LP |
326 | const char *path; |
327 | uint64_t u64; | |
6f68ecb4 G |
328 | unsigned n = 0; |
329 | ||
718db961 LP |
330 | r = sd_bus_message_enter_container(message, 'a', "(st)"); |
331 | if (r < 0) | |
332 | return r; | |
6f68ecb4 | 333 | |
ccd06097 ZJS |
334 | while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) { |
335 | unsigned long ul = u64; | |
6f68ecb4 | 336 | |
6f68ecb4 | 337 | if (ul < 10 || ul > 1000) |
718db961 | 338 | return sd_bus_error_set_errnof(error, EINVAL, "BlockIODeviceWeight out of range"); |
6f68ecb4 G |
339 | |
340 | if (mode != UNIT_CHECK) { | |
718db961 | 341 | CGroupBlockIODeviceWeight *a = NULL, *b; |
6f68ecb4 G |
342 | |
343 | LIST_FOREACH(device_weights, b, c->blockio_device_weights) { | |
344 | if (path_equal(b->path, path)) { | |
345 | a = b; | |
6f68ecb4 G |
346 | break; |
347 | } | |
348 | } | |
349 | ||
718db961 | 350 | if (!a) { |
6f68ecb4 G |
351 | a = new0(CGroupBlockIODeviceWeight, 1); |
352 | if (!a) | |
353 | return -ENOMEM; | |
354 | ||
355 | a->path = strdup(path); | |
356 | if (!a->path) { | |
357 | free(a); | |
358 | return -ENOMEM; | |
359 | } | |
718db961 | 360 | LIST_PREPEND(device_weights,c->blockio_device_weights, a); |
6f68ecb4 G |
361 | } |
362 | ||
363 | a->weight = ul; | |
6f68ecb4 G |
364 | } |
365 | ||
366 | n++; | |
6f68ecb4 G |
367 | } |
368 | ||
9c96019d LP |
369 | r = sd_bus_message_exit_container(message); |
370 | if (r < 0) | |
371 | return r; | |
372 | ||
6f68ecb4 G |
373 | if (mode != UNIT_CHECK) { |
374 | _cleanup_free_ char *buf = NULL; | |
375 | _cleanup_fclose_ FILE *f = NULL; | |
376 | CGroupBlockIODeviceWeight *a; | |
377 | size_t size = 0; | |
378 | ||
379 | if (n == 0) { | |
380 | while (c->blockio_device_weights) | |
381 | cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights); | |
382 | } | |
383 | ||
3051f187 LP |
384 | u->cgroup_realized_mask &= ~CGROUP_BLKIO; |
385 | ||
6f68ecb4 G |
386 | f = open_memstream(&buf, &size); |
387 | if (!f) | |
388 | return -ENOMEM; | |
389 | ||
390 | fputs("BlockIODeviceWeight=\n", f); | |
391 | LIST_FOREACH(device_weights, a, c->blockio_device_weights) | |
392 | fprintf(f, "BlockIODeviceWeight=%s %lu\n", a->path, a->weight); | |
393 | ||
f004c2ca G |
394 | fflush(f); |
395 | unit_write_drop_in_private(u, mode, name, buf); | |
396 | } | |
397 | ||
398 | return 1; | |
399 | ||
8e2af478 | 400 | } else if (streq(name, "MemoryAccounting")) { |
718db961 | 401 | int b; |
8e2af478 | 402 | |
718db961 LP |
403 | r = sd_bus_message_read(message, "b", &b); |
404 | if (r < 0) | |
405 | return r; | |
8e2af478 LP |
406 | |
407 | if (mode != UNIT_CHECK) { | |
b42defe3 | 408 | c->memory_accounting = b; |
3051f187 | 409 | u->cgroup_realized_mask &= ~CGROUP_MEMORY; |
b9ec9359 | 410 | unit_write_drop_in_private(u, mode, name, b ? "MemoryAccounting=yes" : "MemoryAccounting=no"); |
8e2af478 LP |
411 | } |
412 | ||
413 | return 1; | |
8e2af478 | 414 | |
ddca82ac | 415 | } else if (streq(name, "MemoryLimit")) { |
718db961 | 416 | uint64_t limit; |
b42defe3 | 417 | |
718db961 LP |
418 | r = sd_bus_message_read(message, "t", &limit); |
419 | if (r < 0) | |
420 | return r; | |
b42defe3 LP |
421 | |
422 | if (mode != UNIT_CHECK) { | |
ddca82ac | 423 | c->memory_limit = limit; |
3051f187 | 424 | u->cgroup_realized_mask &= ~CGROUP_MEMORY; |
b9ec9359 | 425 | unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu64, name, limit); |
b42defe3 LP |
426 | } |
427 | ||
7041efe9 LP |
428 | return 1; |
429 | ||
430 | } else if (streq(name, "DevicePolicy")) { | |
431 | const char *policy; | |
432 | CGroupDevicePolicy p; | |
433 | ||
718db961 LP |
434 | r = sd_bus_message_read(message, "s", &policy); |
435 | if (r < 0) | |
436 | return r; | |
7041efe9 | 437 | |
7041efe9 LP |
438 | p = cgroup_device_policy_from_string(policy); |
439 | if (p < 0) | |
440 | return -EINVAL; | |
441 | ||
442 | if (mode != UNIT_CHECK) { | |
443 | char *buf; | |
444 | ||
445 | c->device_policy = p; | |
3051f187 | 446 | u->cgroup_realized_mask &= ~CGROUP_DEVICE; |
7041efe9 LP |
447 | |
448 | buf = strappenda("DevicePolicy=", policy); | |
b9ec9359 | 449 | unit_write_drop_in_private(u, mode, name, buf); |
7041efe9 LP |
450 | } |
451 | ||
452 | return 1; | |
453 | ||
454 | } else if (streq(name, "DeviceAllow")) { | |
718db961 | 455 | const char *path, *rwm; |
7041efe9 LP |
456 | unsigned n = 0; |
457 | ||
718db961 LP |
458 | r = sd_bus_message_enter_container(message, 'a', "(ss)"); |
459 | if (r < 0) | |
460 | return r; | |
7041efe9 | 461 | |
718db961 | 462 | while ((r = sd_bus_message_read(message, "(ss)", &path, &rwm)) > 0) { |
7041efe9 | 463 | |
90060676 LP |
464 | if ((!startswith(path, "/dev/") && |
465 | !startswith(path, "block-") && | |
466 | !startswith(path, "char-")) || | |
467 | strpbrk(path, WHITESPACE)) | |
468 | return sd_bus_error_set_errnof(error, EINVAL, "DeviceAllow= requires device node"); | |
7041efe9 LP |
469 | |
470 | if (isempty(rwm)) | |
471 | rwm = "rwm"; | |
472 | ||
718db961 LP |
473 | if (!in_charset(rwm, "rwm")) |
474 | return sd_bus_error_set_errnof(error, EINVAL, "DeviceAllow= requires combination of rwm flags"); | |
7041efe9 | 475 | |
7041efe9 | 476 | if (mode != UNIT_CHECK) { |
718db961 | 477 | CGroupDeviceAllow *a = NULL, *b; |
ad7bfffd G |
478 | |
479 | LIST_FOREACH(device_allow, b, c->device_allow) { | |
06eb4e3b | 480 | if (path_equal(b->path, path)) { |
ad7bfffd | 481 | a = b; |
ad7bfffd G |
482 | break; |
483 | } | |
484 | } | |
485 | ||
718db961 | 486 | if (!a) { |
ad7bfffd G |
487 | a = new0(CGroupDeviceAllow, 1); |
488 | if (!a) | |
489 | return -ENOMEM; | |
490 | ||
491 | a->path = strdup(path); | |
492 | if (!a->path) { | |
493 | free(a); | |
494 | return -ENOMEM; | |
495 | } | |
718db961 LP |
496 | |
497 | LIST_PREPEND(device_allow, c->device_allow, a); | |
7041efe9 LP |
498 | } |
499 | ||
500 | a->r = !!strchr(rwm, 'r'); | |
501 | a->w = !!strchr(rwm, 'w'); | |
502 | a->m = !!strchr(rwm, 'm'); | |
7041efe9 LP |
503 | } |
504 | ||
c2756a68 | 505 | n++; |
7041efe9 | 506 | } |
43a99a7a LP |
507 | if (r < 0) |
508 | return r; | |
7041efe9 | 509 | |
9c96019d LP |
510 | r = sd_bus_message_exit_container(message); |
511 | if (r < 0) | |
512 | return r; | |
513 | ||
7041efe9 LP |
514 | if (mode != UNIT_CHECK) { |
515 | _cleanup_free_ char *buf = NULL; | |
516 | _cleanup_fclose_ FILE *f = NULL; | |
517 | CGroupDeviceAllow *a; | |
518 | size_t size = 0; | |
519 | ||
520 | if (n == 0) { | |
521 | while (c->device_allow) | |
522 | cgroup_context_free_device_allow(c, c->device_allow); | |
523 | } | |
524 | ||
3051f187 LP |
525 | u->cgroup_realized_mask &= ~CGROUP_DEVICE; |
526 | ||
7041efe9 LP |
527 | f = open_memstream(&buf, &size); |
528 | if (!f) | |
529 | return -ENOMEM; | |
530 | ||
531 | fputs("DeviceAllow=\n", f); | |
532 | LIST_FOREACH(device_allow, a, c->device_allow) | |
533 | fprintf(f, "DeviceAllow=%s %s%s%s\n", a->path, a->r ? "r" : "", a->w ? "w" : "", a->m ? "m" : ""); | |
534 | ||
535 | fflush(f); | |
b9ec9359 | 536 | unit_write_drop_in_private(u, mode, name, buf); |
7041efe9 LP |
537 | } |
538 | ||
b42defe3 LP |
539 | return 1; |
540 | } | |
8e2af478 LP |
541 | |
542 | return 0; | |
543 | } |