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