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