]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/util.c
Merge pull request #4536 from poettering/seccomp-namespaces
[thirdparty/systemd.git] / src / basic / util.c
1 /***
2 This file is part of systemd.
3
4 Copyright 2010 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include <alloca.h>
21 #include <dirent.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <sched.h>
25 #include <signal.h>
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <sys/mman.h>
31 #include <sys/prctl.h>
32 #include <sys/statfs.h>
33 #include <sys/sysmacros.h>
34 #include <sys/types.h>
35 #include <unistd.h>
36
37 #include "alloc-util.h"
38 #include "build.h"
39 #include "cgroup-util.h"
40 #include "def.h"
41 #include "dirent-util.h"
42 #include "fd-util.h"
43 #include "fileio.h"
44 #include "format-util.h"
45 #include "hashmap.h"
46 #include "hostname-util.h"
47 #include "log.h"
48 #include "macro.h"
49 #include "missing.h"
50 #include "parse-util.h"
51 #include "path-util.h"
52 #include "process-util.h"
53 #include "set.h"
54 #include "signal-util.h"
55 #include "stat-util.h"
56 #include "string-util.h"
57 #include "strv.h"
58 #include "time-util.h"
59 #include "umask-util.h"
60 #include "user-util.h"
61 #include "util.h"
62
63 /* Put this test here for a lack of better place */
64 assert_cc(EAGAIN == EWOULDBLOCK);
65
66 int saved_argc = 0;
67 char **saved_argv = NULL;
68 static int saved_in_initrd = -1;
69
70 size_t page_size(void) {
71 static thread_local size_t pgsz = 0;
72 long r;
73
74 if (_likely_(pgsz > 0))
75 return pgsz;
76
77 r = sysconf(_SC_PAGESIZE);
78 assert(r > 0);
79
80 pgsz = (size_t) r;
81 return pgsz;
82 }
83
84 static int do_execute(char **directories, usec_t timeout, char *argv[]) {
85 _cleanup_hashmap_free_free_ Hashmap *pids = NULL;
86 _cleanup_set_free_free_ Set *seen = NULL;
87 char **directory;
88
89 /* We fork this all off from a child process so that we can
90 * somewhat cleanly make use of SIGALRM to set a time limit */
91
92 (void) reset_all_signal_handlers();
93 (void) reset_signal_mask();
94
95 assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
96
97 pids = hashmap_new(NULL);
98 if (!pids)
99 return log_oom();
100
101 seen = set_new(&string_hash_ops);
102 if (!seen)
103 return log_oom();
104
105 STRV_FOREACH(directory, directories) {
106 _cleanup_closedir_ DIR *d;
107 struct dirent *de;
108
109 d = opendir(*directory);
110 if (!d) {
111 if (errno == ENOENT)
112 continue;
113
114 return log_error_errno(errno, "Failed to open directory %s: %m", *directory);
115 }
116
117 FOREACH_DIRENT(de, d, break) {
118 _cleanup_free_ char *path = NULL;
119 pid_t pid;
120 int r;
121
122 if (!dirent_is_file(de))
123 continue;
124
125 if (set_contains(seen, de->d_name)) {
126 log_debug("%1$s/%2$s skipped (%2$s was already seen).", *directory, de->d_name);
127 continue;
128 }
129
130 r = set_put_strdup(seen, de->d_name);
131 if (r < 0)
132 return log_oom();
133
134 path = strjoin(*directory, "/", de->d_name);
135 if (!path)
136 return log_oom();
137
138 if (null_or_empty_path(path)) {
139 log_debug("%s is empty (a mask).", path);
140 continue;
141 }
142
143 pid = fork();
144 if (pid < 0) {
145 log_error_errno(errno, "Failed to fork: %m");
146 continue;
147 } else if (pid == 0) {
148 char *_argv[2];
149
150 assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
151
152 if (!argv) {
153 _argv[0] = path;
154 _argv[1] = NULL;
155 argv = _argv;
156 } else
157 argv[0] = path;
158
159 execv(path, argv);
160 return log_error_errno(errno, "Failed to execute %s: %m", path);
161 }
162
163 log_debug("Spawned %s as " PID_FMT ".", path, pid);
164
165 r = hashmap_put(pids, PID_TO_PTR(pid), path);
166 if (r < 0)
167 return log_oom();
168 path = NULL;
169 }
170 }
171
172 /* Abort execution of this process after the timout. We simply
173 * rely on SIGALRM as default action terminating the process,
174 * and turn on alarm(). */
175
176 if (timeout != USEC_INFINITY)
177 alarm((timeout + USEC_PER_SEC - 1) / USEC_PER_SEC);
178
179 while (!hashmap_isempty(pids)) {
180 _cleanup_free_ char *path = NULL;
181 pid_t pid;
182
183 pid = PTR_TO_PID(hashmap_first_key(pids));
184 assert(pid > 0);
185
186 path = hashmap_remove(pids, PID_TO_PTR(pid));
187 assert(path);
188
189 wait_for_terminate_and_warn(path, pid, true);
190 }
191
192 return 0;
193 }
194
195 void execute_directories(const char* const* directories, usec_t timeout, char *argv[]) {
196 pid_t executor_pid;
197 int r;
198 char *name;
199 char **dirs = (char**) directories;
200
201 assert(!strv_isempty(dirs));
202
203 name = basename(dirs[0]);
204 assert(!isempty(name));
205
206 /* Executes all binaries in the directories in parallel and waits
207 * for them to finish. Optionally a timeout is applied. If a file
208 * with the same name exists in more than one directory, the
209 * earliest one wins. */
210
211 executor_pid = fork();
212 if (executor_pid < 0) {
213 log_error_errno(errno, "Failed to fork: %m");
214 return;
215
216 } else if (executor_pid == 0) {
217 r = do_execute(dirs, timeout, argv);
218 _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
219 }
220
221 wait_for_terminate_and_warn(name, executor_pid, true);
222 }
223
224 bool plymouth_running(void) {
225 return access("/run/plymouth/pid", F_OK) >= 0;
226 }
227
228 bool display_is_local(const char *display) {
229 assert(display);
230
231 return
232 display[0] == ':' &&
233 display[1] >= '0' &&
234 display[1] <= '9';
235 }
236
237 int socket_from_display(const char *display, char **path) {
238 size_t k;
239 char *f, *c;
240
241 assert(display);
242 assert(path);
243
244 if (!display_is_local(display))
245 return -EINVAL;
246
247 k = strspn(display+1, "0123456789");
248
249 f = new(char, strlen("/tmp/.X11-unix/X") + k + 1);
250 if (!f)
251 return -ENOMEM;
252
253 c = stpcpy(f, "/tmp/.X11-unix/X");
254 memcpy(c, display+1, k);
255 c[k] = 0;
256
257 *path = f;
258
259 return 0;
260 }
261
262 int block_get_whole_disk(dev_t d, dev_t *ret) {
263 char *p, *s;
264 int r;
265 unsigned n, m;
266
267 assert(ret);
268
269 /* If it has a queue this is good enough for us */
270 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", major(d), minor(d)) < 0)
271 return -ENOMEM;
272
273 r = access(p, F_OK);
274 free(p);
275
276 if (r >= 0) {
277 *ret = d;
278 return 0;
279 }
280
281 /* If it is a partition find the originating device */
282 if (asprintf(&p, "/sys/dev/block/%u:%u/partition", major(d), minor(d)) < 0)
283 return -ENOMEM;
284
285 r = access(p, F_OK);
286 free(p);
287
288 if (r < 0)
289 return -ENOENT;
290
291 /* Get parent dev_t */
292 if (asprintf(&p, "/sys/dev/block/%u:%u/../dev", major(d), minor(d)) < 0)
293 return -ENOMEM;
294
295 r = read_one_line_file(p, &s);
296 free(p);
297
298 if (r < 0)
299 return r;
300
301 r = sscanf(s, "%u:%u", &m, &n);
302 free(s);
303
304 if (r != 2)
305 return -EINVAL;
306
307 /* Only return this if it is really good enough for us. */
308 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", m, n) < 0)
309 return -ENOMEM;
310
311 r = access(p, F_OK);
312 free(p);
313
314 if (r >= 0) {
315 *ret = makedev(m, n);
316 return 0;
317 }
318
319 return -ENOENT;
320 }
321
322 bool kexec_loaded(void) {
323 bool loaded = false;
324 char *s;
325
326 if (read_one_line_file("/sys/kernel/kexec_loaded", &s) >= 0) {
327 if (s[0] == '1')
328 loaded = true;
329 free(s);
330 }
331 return loaded;
332 }
333
334 int prot_from_flags(int flags) {
335
336 switch (flags & O_ACCMODE) {
337
338 case O_RDONLY:
339 return PROT_READ;
340
341 case O_WRONLY:
342 return PROT_WRITE;
343
344 case O_RDWR:
345 return PROT_READ|PROT_WRITE;
346
347 default:
348 return -EINVAL;
349 }
350 }
351
352 int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
353 bool stdout_is_tty, stderr_is_tty;
354 pid_t parent_pid, agent_pid;
355 sigset_t ss, saved_ss;
356 unsigned n, i;
357 va_list ap;
358 char **l;
359
360 assert(pid);
361 assert(path);
362
363 /* Spawns a temporary TTY agent, making sure it goes away when
364 * we go away */
365
366 parent_pid = getpid();
367
368 /* First we temporarily block all signals, so that the new
369 * child has them blocked initially. This way, we can be sure
370 * that SIGTERMs are not lost we might send to the agent. */
371 assert_se(sigfillset(&ss) >= 0);
372 assert_se(sigprocmask(SIG_SETMASK, &ss, &saved_ss) >= 0);
373
374 agent_pid = fork();
375 if (agent_pid < 0) {
376 assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0);
377 return -errno;
378 }
379
380 if (agent_pid != 0) {
381 assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0);
382 *pid = agent_pid;
383 return 0;
384 }
385
386 /* In the child:
387 *
388 * Make sure the agent goes away when the parent dies */
389 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
390 _exit(EXIT_FAILURE);
391
392 /* Make sure we actually can kill the agent, if we need to, in
393 * case somebody invoked us from a shell script that trapped
394 * SIGTERM or so... */
395 (void) reset_all_signal_handlers();
396 (void) reset_signal_mask();
397
398 /* Check whether our parent died before we were able
399 * to set the death signal and unblock the signals */
400 if (getppid() != parent_pid)
401 _exit(EXIT_SUCCESS);
402
403 /* Don't leak fds to the agent */
404 close_all_fds(except, n_except);
405
406 stdout_is_tty = isatty(STDOUT_FILENO);
407 stderr_is_tty = isatty(STDERR_FILENO);
408
409 if (!stdout_is_tty || !stderr_is_tty) {
410 int fd;
411
412 /* Detach from stdout/stderr. and reopen
413 * /dev/tty for them. This is important to
414 * ensure that when systemctl is started via
415 * popen() or a similar call that expects to
416 * read EOF we actually do generate EOF and
417 * not delay this indefinitely by because we
418 * keep an unused copy of stdin around. */
419 fd = open("/dev/tty", O_WRONLY);
420 if (fd < 0) {
421 log_error_errno(errno, "Failed to open /dev/tty: %m");
422 _exit(EXIT_FAILURE);
423 }
424
425 if (!stdout_is_tty && dup2(fd, STDOUT_FILENO) < 0) {
426 log_error_errno(errno, "Failed to dup2 /dev/tty: %m");
427 _exit(EXIT_FAILURE);
428 }
429
430 if (!stderr_is_tty && dup2(fd, STDERR_FILENO) < 0) {
431 log_error_errno(errno, "Failed to dup2 /dev/tty: %m");
432 _exit(EXIT_FAILURE);
433 }
434
435 if (fd > STDERR_FILENO)
436 close(fd);
437 }
438
439 /* Count arguments */
440 va_start(ap, path);
441 for (n = 0; va_arg(ap, char*); n++)
442 ;
443 va_end(ap);
444
445 /* Allocate strv */
446 l = alloca(sizeof(char *) * (n + 1));
447
448 /* Fill in arguments */
449 va_start(ap, path);
450 for (i = 0; i <= n; i++)
451 l[i] = va_arg(ap, char*);
452 va_end(ap);
453
454 execv(path, l);
455 _exit(EXIT_FAILURE);
456 }
457
458 bool in_initrd(void) {
459 struct statfs s;
460
461 if (saved_in_initrd >= 0)
462 return saved_in_initrd;
463
464 /* We make two checks here:
465 *
466 * 1. the flag file /etc/initrd-release must exist
467 * 2. the root file system must be a memory file system
468 *
469 * The second check is extra paranoia, since misdetecting an
470 * initrd can have bad consequences due the initrd
471 * emptying when transititioning to the main systemd.
472 */
473
474 saved_in_initrd = access("/etc/initrd-release", F_OK) >= 0 &&
475 statfs("/", &s) >= 0 &&
476 is_temporary_fs(&s);
477
478 return saved_in_initrd;
479 }
480
481 void in_initrd_force(bool value) {
482 saved_in_initrd = value;
483 }
484
485 /* hey glibc, APIs with callbacks without a user pointer are so useless */
486 void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
487 int (*compar) (const void *, const void *, void *), void *arg) {
488 size_t l, u, idx;
489 const void *p;
490 int comparison;
491
492 l = 0;
493 u = nmemb;
494 while (l < u) {
495 idx = (l + u) / 2;
496 p = (void *)(((const char *) base) + (idx * size));
497 comparison = compar(key, p, arg);
498 if (comparison < 0)
499 u = idx;
500 else if (comparison > 0)
501 l = idx + 1;
502 else
503 return (void *)p;
504 }
505 return NULL;
506 }
507
508 int on_ac_power(void) {
509 bool found_offline = false, found_online = false;
510 _cleanup_closedir_ DIR *d = NULL;
511
512 d = opendir("/sys/class/power_supply");
513 if (!d)
514 return errno == ENOENT ? true : -errno;
515
516 for (;;) {
517 struct dirent *de;
518 _cleanup_close_ int fd = -1, device = -1;
519 char contents[6];
520 ssize_t n;
521
522 errno = 0;
523 de = readdir(d);
524 if (!de && errno > 0)
525 return -errno;
526
527 if (!de)
528 break;
529
530 if (hidden_or_backup_file(de->d_name))
531 continue;
532
533 device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);
534 if (device < 0) {
535 if (errno == ENOENT || errno == ENOTDIR)
536 continue;
537
538 return -errno;
539 }
540
541 fd = openat(device, "type", O_RDONLY|O_CLOEXEC|O_NOCTTY);
542 if (fd < 0) {
543 if (errno == ENOENT)
544 continue;
545
546 return -errno;
547 }
548
549 n = read(fd, contents, sizeof(contents));
550 if (n < 0)
551 return -errno;
552
553 if (n != 6 || memcmp(contents, "Mains\n", 6))
554 continue;
555
556 safe_close(fd);
557 fd = openat(device, "online", O_RDONLY|O_CLOEXEC|O_NOCTTY);
558 if (fd < 0) {
559 if (errno == ENOENT)
560 continue;
561
562 return -errno;
563 }
564
565 n = read(fd, contents, sizeof(contents));
566 if (n < 0)
567 return -errno;
568
569 if (n != 2 || contents[1] != '\n')
570 return -EIO;
571
572 if (contents[0] == '1') {
573 found_online = true;
574 break;
575 } else if (contents[0] == '0')
576 found_offline = true;
577 else
578 return -EIO;
579 }
580
581 return found_online || !found_offline;
582 }
583
584 int container_get_leader(const char *machine, pid_t *pid) {
585 _cleanup_free_ char *s = NULL, *class = NULL;
586 const char *p;
587 pid_t leader;
588 int r;
589
590 assert(machine);
591 assert(pid);
592
593 if (!machine_name_is_valid(machine))
594 return -EINVAL;
595
596 p = strjoina("/run/systemd/machines/", machine);
597 r = parse_env_file(p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL);
598 if (r == -ENOENT)
599 return -EHOSTDOWN;
600 if (r < 0)
601 return r;
602 if (!s)
603 return -EIO;
604
605 if (!streq_ptr(class, "container"))
606 return -EIO;
607
608 r = parse_pid(s, &leader);
609 if (r < 0)
610 return r;
611 if (leader <= 1)
612 return -EIO;
613
614 *pid = leader;
615 return 0;
616 }
617
618 int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd) {
619 _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, netnsfd = -1, usernsfd = -1;
620 int rfd = -1;
621
622 assert(pid >= 0);
623
624 if (mntns_fd) {
625 const char *mntns;
626
627 mntns = procfs_file_alloca(pid, "ns/mnt");
628 mntnsfd = open(mntns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
629 if (mntnsfd < 0)
630 return -errno;
631 }
632
633 if (pidns_fd) {
634 const char *pidns;
635
636 pidns = procfs_file_alloca(pid, "ns/pid");
637 pidnsfd = open(pidns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
638 if (pidnsfd < 0)
639 return -errno;
640 }
641
642 if (netns_fd) {
643 const char *netns;
644
645 netns = procfs_file_alloca(pid, "ns/net");
646 netnsfd = open(netns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
647 if (netnsfd < 0)
648 return -errno;
649 }
650
651 if (userns_fd) {
652 const char *userns;
653
654 userns = procfs_file_alloca(pid, "ns/user");
655 usernsfd = open(userns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
656 if (usernsfd < 0 && errno != ENOENT)
657 return -errno;
658 }
659
660 if (root_fd) {
661 const char *root;
662
663 root = procfs_file_alloca(pid, "root");
664 rfd = open(root, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
665 if (rfd < 0)
666 return -errno;
667 }
668
669 if (pidns_fd)
670 *pidns_fd = pidnsfd;
671
672 if (mntns_fd)
673 *mntns_fd = mntnsfd;
674
675 if (netns_fd)
676 *netns_fd = netnsfd;
677
678 if (userns_fd)
679 *userns_fd = usernsfd;
680
681 if (root_fd)
682 *root_fd = rfd;
683
684 pidnsfd = mntnsfd = netnsfd = usernsfd = -1;
685
686 return 0;
687 }
688
689 int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd) {
690 if (userns_fd >= 0) {
691 /* Can't setns to your own userns, since then you could
692 * escalate from non-root to root in your own namespace, so
693 * check if namespaces equal before attempting to enter. */
694 _cleanup_free_ char *userns_fd_path = NULL;
695 int r;
696 if (asprintf(&userns_fd_path, "/proc/self/fd/%d", userns_fd) < 0)
697 return -ENOMEM;
698
699 r = files_same(userns_fd_path, "/proc/self/ns/user");
700 if (r < 0)
701 return r;
702 if (r)
703 userns_fd = -1;
704 }
705
706 if (pidns_fd >= 0)
707 if (setns(pidns_fd, CLONE_NEWPID) < 0)
708 return -errno;
709
710 if (mntns_fd >= 0)
711 if (setns(mntns_fd, CLONE_NEWNS) < 0)
712 return -errno;
713
714 if (netns_fd >= 0)
715 if (setns(netns_fd, CLONE_NEWNET) < 0)
716 return -errno;
717
718 if (userns_fd >= 0)
719 if (setns(userns_fd, CLONE_NEWUSER) < 0)
720 return -errno;
721
722 if (root_fd >= 0) {
723 if (fchdir(root_fd) < 0)
724 return -errno;
725
726 if (chroot(".") < 0)
727 return -errno;
728 }
729
730 return reset_uid_gid();
731 }
732
733 uint64_t physical_memory(void) {
734 _cleanup_free_ char *root = NULL, *value = NULL;
735 uint64_t mem, lim;
736 size_t ps;
737 long sc;
738
739 /* We return this as uint64_t in case we are running as 32bit process on a 64bit kernel with huge amounts of
740 * memory.
741 *
742 * In order to support containers nicely that have a configured memory limit we'll take the minimum of the
743 * physically reported amount of memory and the limit configured for the root cgroup, if there is any. */
744
745 sc = sysconf(_SC_PHYS_PAGES);
746 assert(sc > 0);
747
748 ps = page_size();
749 mem = (uint64_t) sc * (uint64_t) ps;
750
751 if (cg_get_root_path(&root) < 0)
752 return mem;
753
754 if (cg_get_attribute("memory", root, "memory.limit_in_bytes", &value))
755 return mem;
756
757 if (safe_atou64(value, &lim) < 0)
758 return mem;
759
760 /* Make sure the limit is a multiple of our own page size */
761 lim /= ps;
762 lim *= ps;
763
764 return MIN(mem, lim);
765 }
766
767 uint64_t physical_memory_scale(uint64_t v, uint64_t max) {
768 uint64_t p, m, ps, r;
769
770 assert(max > 0);
771
772 /* Returns the physical memory size, multiplied by v divided by max. Returns UINT64_MAX on overflow. On success
773 * the result is a multiple of the page size (rounds down). */
774
775 ps = page_size();
776 assert(ps > 0);
777
778 p = physical_memory() / ps;
779 assert(p > 0);
780
781 m = p * v;
782 if (m / p != v)
783 return UINT64_MAX;
784
785 m /= max;
786
787 r = m * ps;
788 if (r / ps != m)
789 return UINT64_MAX;
790
791 return r;
792 }
793
794 uint64_t system_tasks_max(void) {
795
796 #if SIZEOF_PID_T == 4
797 #define TASKS_MAX ((uint64_t) (INT32_MAX-1))
798 #elif SIZEOF_PID_T == 2
799 #define TASKS_MAX ((uint64_t) (INT16_MAX-1))
800 #else
801 #error "Unknown pid_t size"
802 #endif
803
804 _cleanup_free_ char *value = NULL, *root = NULL;
805 uint64_t a = TASKS_MAX, b = TASKS_MAX;
806
807 /* Determine the maximum number of tasks that may run on this system. We check three sources to determine this
808 * limit:
809 *
810 * a) the maximum value for the pid_t type
811 * b) the cgroups pids_max attribute for the system
812 * c) the kernel's configure maximum PID value
813 *
814 * And then pick the smallest of the three */
815
816 if (read_one_line_file("/proc/sys/kernel/pid_max", &value) >= 0)
817 (void) safe_atou64(value, &a);
818
819 if (cg_get_root_path(&root) >= 0) {
820 value = mfree(value);
821
822 if (cg_get_attribute("pids", root, "pids.max", &value) >= 0)
823 (void) safe_atou64(value, &b);
824 }
825
826 return MIN3(TASKS_MAX,
827 a <= 0 ? TASKS_MAX : a,
828 b <= 0 ? TASKS_MAX : b);
829 }
830
831 uint64_t system_tasks_max_scale(uint64_t v, uint64_t max) {
832 uint64_t t, m;
833
834 assert(max > 0);
835
836 /* Multiply the system's task value by the fraction v/max. Hence, if max==100 this calculates percentages
837 * relative to the system's maximum number of tasks. Returns UINT64_MAX on overflow. */
838
839 t = system_tasks_max();
840 assert(t > 0);
841
842 m = t * v;
843 if (m / t != v) /* overflow? */
844 return UINT64_MAX;
845
846 return m / max;
847 }
848
849 int update_reboot_parameter_and_warn(const char *param) {
850 int r;
851
852 if (isempty(param)) {
853 if (unlink("/run/systemd/reboot-param") < 0) {
854 if (errno == ENOENT)
855 return 0;
856
857 return log_warning_errno(errno, "Failed to unlink reboot parameter file: %m");
858 }
859
860 return 0;
861 }
862
863 RUN_WITH_UMASK(0022) {
864 r = write_string_file("/run/systemd/reboot-param", param, WRITE_STRING_FILE_CREATE);
865 if (r < 0)
866 return log_warning_errno(r, "Failed to write reboot parameter file: %m");
867 }
868
869 return 0;
870 }
871
872 int version(void) {
873 puts(PACKAGE_STRING "\n"
874 SYSTEMD_FEATURES);
875 return 0;
876 }