Line data Source code
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 :
22 : #include "bus-util.h"
23 : #include "path-util.h"
24 : #include "cgroup-util.h"
25 : #include "cgroup.h"
26 : #include "dbus-cgroup.h"
27 :
28 0 : static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy, cgroup_device_policy, CGroupDevicePolicy);
29 :
30 0 : 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,
36 : void *userdata,
37 : sd_bus_error *error) {
38 :
39 0 : CGroupContext *c = userdata;
40 : CGroupBlockIODeviceWeight *w;
41 : int r;
42 :
43 0 : assert(bus);
44 0 : assert(reply);
45 0 : assert(c);
46 :
47 0 : r = sd_bus_message_open_container(reply, 'a', "(st)");
48 0 : if (r < 0)
49 0 : return r;
50 :
51 0 : LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
52 0 : r = sd_bus_message_append(reply, "(st)", w->path, w->weight);
53 0 : if (r < 0)
54 0 : return r;
55 : }
56 :
57 0 : return sd_bus_message_close_container(reply);
58 : }
59 :
60 0 : 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,
66 : void *userdata,
67 : sd_bus_error *error) {
68 :
69 0 : CGroupContext *c = userdata;
70 : CGroupBlockIODeviceBandwidth *b;
71 : int r;
72 :
73 0 : assert(bus);
74 0 : assert(reply);
75 0 : assert(c);
76 :
77 0 : r = sd_bus_message_open_container(reply, 'a', "(st)");
78 0 : if (r < 0)
79 0 : return r;
80 :
81 0 : LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
82 :
83 0 : if (streq(property, "BlockIOReadBandwidth") != b->read)
84 0 : continue;
85 :
86 0 : r = sd_bus_message_append(reply, "(st)", b->path, b->bandwidth);
87 0 : if (r < 0)
88 0 : return r;
89 : }
90 :
91 0 : return sd_bus_message_close_container(reply);
92 : }
93 :
94 0 : 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,
100 : void *userdata,
101 : sd_bus_error *error) {
102 :
103 0 : CGroupContext *c = userdata;
104 : CGroupDeviceAllow *a;
105 : int r;
106 :
107 0 : assert(bus);
108 0 : assert(reply);
109 0 : assert(c);
110 :
111 0 : r = sd_bus_message_open_container(reply, 'a', "(ss)");
112 0 : if (r < 0)
113 0 : return r;
114 :
115 0 : LIST_FOREACH(device_allow, a, c->device_allow) {
116 0 : unsigned k = 0;
117 : char rwm[4];
118 :
119 0 : if (a->r)
120 0 : rwm[k++] = 'r';
121 0 : if (a->w)
122 0 : rwm[k++] = 'w';
123 0 : if (a->m)
124 0 : rwm[k++] = 'm';
125 :
126 0 : rwm[k] = 0;
127 :
128 0 : r = sd_bus_message_append(reply, "(ss)", a->path, rwm);
129 0 : if (r < 0)
130 0 : return r;
131 : }
132 :
133 0 : return sd_bus_message_close_container(reply);
134 : }
135 :
136 0 : static int property_get_ulong_as_u64(
137 : sd_bus *bus,
138 : const char *path,
139 : const char *interface,
140 : const char *property,
141 : sd_bus_message *reply,
142 : void *userdata,
143 : sd_bus_error *error) {
144 :
145 0 : unsigned long *ul = userdata;
146 :
147 0 : assert(bus);
148 0 : assert(reply);
149 0 : assert(ul);
150 :
151 0 : return sd_bus_message_append(reply, "t", *ul == (unsigned long) -1 ? (uint64_t) -1 : (uint64_t) *ul);
152 : }
153 :
154 : const sd_bus_vtable bus_cgroup_vtable[] = {
155 : SD_BUS_VTABLE_START(0),
156 : SD_BUS_PROPERTY("Delegate", "b", bus_property_get_bool, offsetof(CGroupContext, delegate), 0),
157 : SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, cpu_accounting), 0),
158 : SD_BUS_PROPERTY("CPUShares", "t", property_get_ulong_as_u64, offsetof(CGroupContext, cpu_shares), 0),
159 : SD_BUS_PROPERTY("StartupCPUShares", "t", property_get_ulong_as_u64, offsetof(CGroupContext, startup_cpu_shares), 0),
160 : SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec, offsetof(CGroupContext, cpu_quota_per_sec_usec), 0),
161 : SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, blockio_accounting), 0),
162 : SD_BUS_PROPERTY("BlockIOWeight", "t", property_get_ulong_as_u64, offsetof(CGroupContext, blockio_weight), 0),
163 : SD_BUS_PROPERTY("StartupBlockIOWeight", "t", property_get_ulong_as_u64, offsetof(CGroupContext, startup_blockio_weight), 0),
164 : SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_device_weight, 0, 0),
165 : SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
166 : SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
167 : SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, memory_accounting), 0),
168 : SD_BUS_PROPERTY("MemoryLimit", "t", NULL, offsetof(CGroupContext, memory_limit), 0),
169 : SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy, offsetof(CGroupContext, device_policy), 0),
170 : SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow, 0, 0),
171 : SD_BUS_VTABLE_END
172 : };
173 :
174 0 : static int bus_cgroup_set_transient_property(
175 : Unit *u,
176 : CGroupContext *c,
177 : const char *name,
178 : sd_bus_message *message,
179 : UnitSetPropertiesMode mode,
180 : sd_bus_error *error) {
181 :
182 : int r;
183 :
184 0 : assert(u);
185 0 : assert(c);
186 0 : assert(name);
187 0 : assert(message);
188 :
189 0 : if (streq(name, "Delegate")) {
190 : int b;
191 :
192 0 : r = sd_bus_message_read(message, "b", &b);
193 0 : if (r < 0)
194 0 : return r;
195 :
196 0 : if (mode != UNIT_CHECK) {
197 0 : c->delegate = b;
198 0 : unit_write_drop_in_private(u, mode, name, b ? "Delegate=yes" : "Delegate=no");
199 : }
200 :
201 0 : return 1;
202 : }
203 :
204 0 : return 0;
205 : }
206 :
207 0 : int bus_cgroup_set_property(
208 : Unit *u,
209 : CGroupContext *c,
210 : const char *name,
211 : sd_bus_message *message,
212 : UnitSetPropertiesMode mode,
213 : sd_bus_error *error) {
214 :
215 : int r;
216 :
217 0 : assert(u);
218 0 : assert(c);
219 0 : assert(name);
220 0 : assert(message);
221 :
222 0 : if (streq(name, "CPUAccounting")) {
223 : int b;
224 :
225 0 : r = sd_bus_message_read(message, "b", &b);
226 0 : if (r < 0)
227 0 : return r;
228 :
229 0 : if (mode != UNIT_CHECK) {
230 0 : c->cpu_accounting = b;
231 0 : u->cgroup_realized_mask &= ~CGROUP_CPUACCT;
232 0 : unit_write_drop_in_private(u, mode, name, b ? "CPUAccounting=yes" : "CPUAccounting=no");
233 : }
234 :
235 0 : return 1;
236 :
237 0 : } else if (streq(name, "CPUShares")) {
238 : uint64_t u64;
239 : unsigned long ul;
240 :
241 0 : r = sd_bus_message_read(message, "t", &u64);
242 0 : if (r < 0)
243 0 : return r;
244 :
245 0 : if (u64 == (uint64_t) -1)
246 0 : ul = (unsigned long) -1;
247 : else {
248 0 : ul = (unsigned long) u64;
249 0 : if (ul <= 0 || (uint64_t) ul != u64)
250 0 : return sd_bus_error_set_errnof(error, EINVAL, "CPUShares value out of range");
251 : }
252 :
253 0 : if (mode != UNIT_CHECK) {
254 0 : c->cpu_shares = ul;
255 0 : u->cgroup_realized_mask &= ~CGROUP_CPU;
256 0 : unit_write_drop_in_private_format(u, mode, name, "CPUShares=%lu", ul);
257 : }
258 :
259 0 : return 1;
260 :
261 0 : } else if (streq(name, "StartupCPUShares")) {
262 : uint64_t u64;
263 : unsigned long ul;
264 :
265 0 : r = sd_bus_message_read(message, "t", &u64);
266 0 : if (r < 0)
267 0 : return r;
268 :
269 0 : if (u64 == (uint64_t) -1)
270 0 : ul = (unsigned long) -1;
271 : else {
272 0 : ul = (unsigned long) u64;
273 0 : if (ul <= 0 || (uint64_t) ul != u64)
274 0 : return sd_bus_error_set_errnof(error, EINVAL, "StartupCPUShares value out of range");
275 : }
276 :
277 0 : if (mode != UNIT_CHECK) {
278 0 : c->startup_cpu_shares = ul;
279 0 : u->cgroup_realized_mask &= ~CGROUP_CPU;
280 0 : unit_write_drop_in_private_format(u, mode, name, "StartupCPUShares=%lu", ul);
281 : }
282 :
283 0 : return 1;
284 :
285 0 : } else if (streq(name, "CPUQuotaPerSecUSec")) {
286 : uint64_t u64;
287 :
288 0 : r = sd_bus_message_read(message, "t", &u64);
289 0 : if (r < 0)
290 0 : return r;
291 :
292 0 : if (u64 <= 0)
293 0 : return sd_bus_error_set_errnof(error, EINVAL, "CPUQuotaPerSecUSec value out of range");
294 :
295 0 : if (mode != UNIT_CHECK) {
296 0 : c->cpu_quota_per_sec_usec = u64;
297 0 : u->cgroup_realized_mask &= ~CGROUP_CPU;
298 0 : unit_write_drop_in_private_format(u, mode, "CPUQuota", "CPUQuota=%0.f%%", (double) (c->cpu_quota_per_sec_usec / 10000));
299 : }
300 :
301 0 : return 1;
302 :
303 0 : } else if (streq(name, "BlockIOAccounting")) {
304 : int b;
305 :
306 0 : r = sd_bus_message_read(message, "b", &b);
307 0 : if (r < 0)
308 0 : return r;
309 :
310 0 : if (mode != UNIT_CHECK) {
311 0 : c->blockio_accounting = b;
312 0 : u->cgroup_realized_mask &= ~CGROUP_BLKIO;
313 0 : unit_write_drop_in_private(u, mode, name, b ? "BlockIOAccounting=yes" : "BlockIOAccounting=no");
314 : }
315 :
316 0 : return 1;
317 :
318 0 : } else if (streq(name, "BlockIOWeight")) {
319 : uint64_t u64;
320 : unsigned long ul;
321 :
322 0 : r = sd_bus_message_read(message, "t", &u64);
323 0 : if (r < 0)
324 0 : return r;
325 :
326 0 : if (u64 == (uint64_t) -1)
327 0 : ul = (unsigned long) -1;
328 : else {
329 0 : ul = (unsigned long) u64;
330 0 : if (ul < 10 || ul > 1000)
331 0 : return sd_bus_error_set_errnof(error, EINVAL, "BlockIOWeight value out of range");
332 : }
333 :
334 0 : if (mode != UNIT_CHECK) {
335 0 : c->blockio_weight = ul;
336 0 : u->cgroup_realized_mask &= ~CGROUP_BLKIO;
337 0 : unit_write_drop_in_private_format(u, mode, name, "BlockIOWeight=%lu", ul);
338 : }
339 :
340 0 : return 1;
341 :
342 0 : } else if (streq(name, "StartupBlockIOWeight")) {
343 : uint64_t u64;
344 : unsigned long ul;
345 :
346 0 : r = sd_bus_message_read(message, "t", &u64);
347 0 : if (r < 0)
348 0 : return r;
349 :
350 0 : if (u64 == (uint64_t) -1)
351 0 : ul = (unsigned long) -1;
352 : else {
353 0 : ul = (unsigned long) u64;
354 0 : if (ul < 10 || ul > 1000)
355 0 : return sd_bus_error_set_errnof(error, EINVAL, "StartupBlockIOWeight value out of range");
356 : }
357 :
358 0 : if (mode != UNIT_CHECK) {
359 0 : c->startup_blockio_weight = ul;
360 0 : u->cgroup_realized_mask &= ~CGROUP_BLKIO;
361 0 : unit_write_drop_in_private_format(u, mode, name, "StartupBlockIOWeight=%lu", ul);
362 : }
363 :
364 0 : return 1;
365 :
366 0 : } else if (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth")) {
367 : const char *path;
368 0 : bool read = true;
369 0 : unsigned n = 0;
370 : uint64_t u64;
371 :
372 0 : if (streq(name, "BlockIOWriteBandwidth"))
373 0 : read = false;
374 :
375 0 : r = sd_bus_message_enter_container(message, 'a', "(st)");
376 0 : if (r < 0)
377 0 : return r;
378 :
379 0 : while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
380 :
381 0 : if (mode != UNIT_CHECK) {
382 0 : CGroupBlockIODeviceBandwidth *a = NULL, *b;
383 :
384 0 : LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
385 0 : if (path_equal(path, b->path) && read == b->read) {
386 0 : a = b;
387 0 : break;
388 : }
389 : }
390 :
391 0 : if (!a) {
392 0 : a = new0(CGroupBlockIODeviceBandwidth, 1);
393 0 : if (!a)
394 0 : return -ENOMEM;
395 :
396 0 : a->read = read;
397 0 : a->path = strdup(path);
398 0 : if (!a->path) {
399 0 : free(a);
400 0 : return -ENOMEM;
401 : }
402 :
403 0 : LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, a);
404 : }
405 :
406 0 : a->bandwidth = u64;
407 : }
408 :
409 0 : n++;
410 : }
411 0 : if (r < 0)
412 0 : return r;
413 :
414 0 : r = sd_bus_message_exit_container(message);
415 0 : if (r < 0)
416 0 : return r;
417 :
418 0 : if (mode != UNIT_CHECK) {
419 : CGroupBlockIODeviceBandwidth *a, *next;
420 0 : _cleanup_free_ char *buf = NULL;
421 0 : _cleanup_fclose_ FILE *f = NULL;
422 0 : size_t size = 0;
423 :
424 0 : if (n == 0) {
425 0 : LIST_FOREACH_SAFE(device_bandwidths, a, next, c->blockio_device_bandwidths)
426 0 : if (a->read == read)
427 0 : cgroup_context_free_blockio_device_bandwidth(c, a);
428 : }
429 :
430 0 : u->cgroup_realized_mask &= ~CGROUP_BLKIO;
431 :
432 0 : f = open_memstream(&buf, &size);
433 0 : if (!f)
434 0 : return -ENOMEM;
435 :
436 0 : if (read) {
437 0 : fputs("BlockIOReadBandwidth=\n", f);
438 0 : LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths)
439 0 : if (a->read)
440 0 : fprintf(f, "BlockIOReadBandwidth=%s %" PRIu64 "\n", a->path, a->bandwidth);
441 : } else {
442 0 : fputs("BlockIOWriteBandwidth=\n", f);
443 0 : LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths)
444 0 : if (!a->read)
445 0 : fprintf(f, "BlockIOWriteBandwidth=%s %" PRIu64 "\n", a->path, a->bandwidth);
446 : }
447 :
448 0 : fflush(f);
449 0 : unit_write_drop_in_private(u, mode, name, buf);
450 : }
451 :
452 0 : return 1;
453 :
454 0 : } else if (streq(name, "BlockIODeviceWeight")) {
455 : const char *path;
456 : uint64_t u64;
457 0 : unsigned n = 0;
458 :
459 0 : r = sd_bus_message_enter_container(message, 'a', "(st)");
460 0 : if (r < 0)
461 0 : return r;
462 :
463 0 : while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
464 0 : unsigned long ul = u64;
465 :
466 0 : if (ul < 10 || ul > 1000)
467 0 : return sd_bus_error_set_errnof(error, EINVAL, "BlockIODeviceWeight out of range");
468 :
469 0 : if (mode != UNIT_CHECK) {
470 0 : CGroupBlockIODeviceWeight *a = NULL, *b;
471 :
472 0 : LIST_FOREACH(device_weights, b, c->blockio_device_weights) {
473 0 : if (path_equal(b->path, path)) {
474 0 : a = b;
475 0 : break;
476 : }
477 : }
478 :
479 0 : if (!a) {
480 0 : a = new0(CGroupBlockIODeviceWeight, 1);
481 0 : if (!a)
482 0 : return -ENOMEM;
483 :
484 0 : a->path = strdup(path);
485 0 : if (!a->path) {
486 0 : free(a);
487 0 : return -ENOMEM;
488 : }
489 0 : LIST_PREPEND(device_weights,c->blockio_device_weights, a);
490 : }
491 :
492 0 : a->weight = ul;
493 : }
494 :
495 0 : n++;
496 : }
497 :
498 0 : r = sd_bus_message_exit_container(message);
499 0 : if (r < 0)
500 0 : return r;
501 :
502 0 : if (mode != UNIT_CHECK) {
503 0 : _cleanup_free_ char *buf = NULL;
504 0 : _cleanup_fclose_ FILE *f = NULL;
505 : CGroupBlockIODeviceWeight *a;
506 0 : size_t size = 0;
507 :
508 0 : if (n == 0) {
509 0 : while (c->blockio_device_weights)
510 0 : cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
511 : }
512 :
513 0 : u->cgroup_realized_mask &= ~CGROUP_BLKIO;
514 :
515 0 : f = open_memstream(&buf, &size);
516 0 : if (!f)
517 0 : return -ENOMEM;
518 :
519 0 : fputs("BlockIODeviceWeight=\n", f);
520 0 : LIST_FOREACH(device_weights, a, c->blockio_device_weights)
521 0 : fprintf(f, "BlockIODeviceWeight=%s %lu\n", a->path, a->weight);
522 :
523 0 : fflush(f);
524 0 : unit_write_drop_in_private(u, mode, name, buf);
525 : }
526 :
527 0 : return 1;
528 :
529 0 : } else if (streq(name, "MemoryAccounting")) {
530 : int b;
531 :
532 0 : r = sd_bus_message_read(message, "b", &b);
533 0 : if (r < 0)
534 0 : return r;
535 :
536 0 : if (mode != UNIT_CHECK) {
537 0 : c->memory_accounting = b;
538 0 : u->cgroup_realized_mask &= ~CGROUP_MEMORY;
539 0 : unit_write_drop_in_private(u, mode, name, b ? "MemoryAccounting=yes" : "MemoryAccounting=no");
540 : }
541 :
542 0 : return 1;
543 :
544 0 : } else if (streq(name, "MemoryLimit")) {
545 : uint64_t limit;
546 :
547 0 : r = sd_bus_message_read(message, "t", &limit);
548 0 : if (r < 0)
549 0 : return r;
550 :
551 0 : if (mode != UNIT_CHECK) {
552 0 : c->memory_limit = limit;
553 0 : u->cgroup_realized_mask &= ~CGROUP_MEMORY;
554 0 : unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu64, name, limit);
555 : }
556 :
557 0 : return 1;
558 :
559 0 : } else if (streq(name, "DevicePolicy")) {
560 : const char *policy;
561 : CGroupDevicePolicy p;
562 :
563 0 : r = sd_bus_message_read(message, "s", &policy);
564 0 : if (r < 0)
565 0 : return r;
566 :
567 0 : p = cgroup_device_policy_from_string(policy);
568 0 : if (p < 0)
569 0 : return -EINVAL;
570 :
571 0 : if (mode != UNIT_CHECK) {
572 : char *buf;
573 :
574 0 : c->device_policy = p;
575 0 : u->cgroup_realized_mask &= ~CGROUP_DEVICE;
576 :
577 0 : buf = strjoina("DevicePolicy=", policy);
578 0 : unit_write_drop_in_private(u, mode, name, buf);
579 : }
580 :
581 0 : return 1;
582 :
583 0 : } else if (streq(name, "DeviceAllow")) {
584 : const char *path, *rwm;
585 0 : unsigned n = 0;
586 :
587 0 : r = sd_bus_message_enter_container(message, 'a', "(ss)");
588 0 : if (r < 0)
589 0 : return r;
590 :
591 0 : while ((r = sd_bus_message_read(message, "(ss)", &path, &rwm)) > 0) {
592 :
593 0 : if ((!startswith(path, "/dev/") &&
594 0 : !startswith(path, "block-") &&
595 0 : !startswith(path, "char-")) ||
596 0 : strpbrk(path, WHITESPACE))
597 0 : return sd_bus_error_set_errnof(error, EINVAL, "DeviceAllow= requires device node");
598 :
599 0 : if (isempty(rwm))
600 0 : rwm = "rwm";
601 :
602 0 : if (!in_charset(rwm, "rwm"))
603 0 : return sd_bus_error_set_errnof(error, EINVAL, "DeviceAllow= requires combination of rwm flags");
604 :
605 0 : if (mode != UNIT_CHECK) {
606 0 : CGroupDeviceAllow *a = NULL, *b;
607 :
608 0 : LIST_FOREACH(device_allow, b, c->device_allow) {
609 0 : if (path_equal(b->path, path)) {
610 0 : a = b;
611 0 : break;
612 : }
613 : }
614 :
615 0 : if (!a) {
616 0 : a = new0(CGroupDeviceAllow, 1);
617 0 : if (!a)
618 0 : return -ENOMEM;
619 :
620 0 : a->path = strdup(path);
621 0 : if (!a->path) {
622 0 : free(a);
623 0 : return -ENOMEM;
624 : }
625 :
626 0 : LIST_PREPEND(device_allow, c->device_allow, a);
627 : }
628 :
629 0 : a->r = !!strchr(rwm, 'r');
630 0 : a->w = !!strchr(rwm, 'w');
631 0 : a->m = !!strchr(rwm, 'm');
632 : }
633 :
634 0 : n++;
635 : }
636 0 : if (r < 0)
637 0 : return r;
638 :
639 0 : r = sd_bus_message_exit_container(message);
640 0 : if (r < 0)
641 0 : return r;
642 :
643 0 : if (mode != UNIT_CHECK) {
644 0 : _cleanup_free_ char *buf = NULL;
645 0 : _cleanup_fclose_ FILE *f = NULL;
646 : CGroupDeviceAllow *a;
647 0 : size_t size = 0;
648 :
649 0 : if (n == 0) {
650 0 : while (c->device_allow)
651 0 : cgroup_context_free_device_allow(c, c->device_allow);
652 : }
653 :
654 0 : u->cgroup_realized_mask &= ~CGROUP_DEVICE;
655 :
656 0 : f = open_memstream(&buf, &size);
657 0 : if (!f)
658 0 : return -ENOMEM;
659 :
660 0 : fputs("DeviceAllow=\n", f);
661 0 : LIST_FOREACH(device_allow, a, c->device_allow)
662 0 : fprintf(f, "DeviceAllow=%s %s%s%s\n", a->path, a->r ? "r" : "", a->w ? "w" : "", a->m ? "m" : "");
663 :
664 0 : fflush(f);
665 0 : unit_write_drop_in_private(u, mode, name, buf);
666 : }
667 :
668 0 : return 1;
669 :
670 : }
671 :
672 0 : if (u->transient && u->load_state == UNIT_STUB) {
673 0 : r = bus_cgroup_set_transient_property(u, c, name, message, mode, error);
674 0 : if (r != 0)
675 0 : return r;
676 :
677 : }
678 :
679 0 : return 0;
680 : }
|