]>
Commit | Line | Data |
---|---|---|
53e1b683 | 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
1298001e | 2 | /*** |
96b2fb93 | 3 | Copyright © 2003-2004 Greg Kroah-Hartman <greg@kroah.com> |
1298001e | 4 | ***/ |
f0083e3d | 5 | |
c81b35c0 | 6 | #include <errno.h> |
4cb72937 | 7 | #include <sched.h> |
07630cea LP |
8 | #include <stdio.h> |
9 | #include <stdlib.h> | |
4cb72937 | 10 | #include <sys/mount.h> |
2181d30a | 11 | #include <sys/signalfd.h> |
07630cea | 12 | #include <unistd.h> |
85511f02 | 13 | |
b74a0b6a | 14 | #include "device-private.h" |
f4f15635 | 15 | #include "fs-util.h" |
dbab702a | 16 | #include "log.h" |
8d38b8ad | 17 | #include "main-func.h" |
10efe2cd | 18 | #include "missing.h" |
5ea78a39 | 19 | #include "mkdir.h" |
d7b8eec7 | 20 | #include "selinux-util.h" |
8314de1d | 21 | #include "signal-util.h" |
07630cea | 22 | #include "string-util.h" |
465815aa | 23 | #include "tests.h" |
07630cea | 24 | #include "udev.h" |
f0083e3d | 25 | |
4cb72937 KS |
26 | static int fake_filesystems(void) { |
27 | static const struct fakefs { | |
28 | const char *src; | |
29 | const char *target; | |
30 | const char *error; | |
ad43ccb0 | 31 | bool ignore_mount_error; |
4cb72937 | 32 | } fakefss[] = { |
465815aa ZJS |
33 | { "test/tmpfs/sys", "/sys", "Failed to mount test /sys", false }, |
34 | { "test/tmpfs/dev", "/dev", "Failed to mount test /dev", false }, | |
35 | { "test/run", "/run", "Failed to mount test /run", false }, | |
36 | { "test/run", "/etc/udev/rules.d", "Failed to mount empty /etc/udev/rules.d", true }, | |
37 | { "test/run", UDEVLIBEXECDIR "/rules.d", "Failed to mount empty " UDEVLIBEXECDIR "/rules.d", true }, | |
4cb72937 | 38 | }; |
465815aa | 39 | unsigned i; |
4cb72937 | 40 | |
dbab702a | 41 | if (unshare(CLONE_NEWNS) < 0) |
465815aa | 42 | return log_error_errno(errno, "Failed to call unshare(): %m"); |
04eaa668 | 43 | |
74bf45bb | 44 | if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0) |
465815aa | 45 | return log_error_errno(errno, "Failed to mount / as private: %m"); |
4cb72937 | 46 | |
465815aa | 47 | for (i = 0; i < ELEMENTSOF(fakefss); i++) |
dbab702a EV |
48 | if (mount(fakefss[i].src, fakefss[i].target, NULL, MS_BIND, NULL) < 0) { |
49 | log_full_errno(fakefss[i].ignore_mount_error ? LOG_DEBUG : LOG_ERR, errno, "%s: %m", fakefss[i].error); | |
ad43ccb0 | 50 | if (!fakefss[i].ignore_mount_error) |
dbab702a | 51 | return -errno; |
4cb72937 | 52 | } |
dbab702a EV |
53 | |
54 | return 0; | |
4cb72937 KS |
55 | } |
56 | ||
8d38b8ad | 57 | static int run(int argc, char *argv[]) { |
9a07157d | 58 | _cleanup_(udev_rules_freep) UdevRules *rules = NULL; |
2e088715 | 59 | _cleanup_(udev_event_freep) UdevEvent *event = NULL; |
b74a0b6a YW |
60 | _cleanup_(sd_device_unrefp) sd_device *dev = NULL; |
61 | const char *devpath, *devname, *action; | |
62 | int r; | |
4cb72937 | 63 | |
465815aa | 64 | test_setup_logging(LOG_INFO); |
dbab702a | 65 | |
110a1320 EV |
66 | if (!IN_SET(argc, 2, 3)) { |
67 | log_error("This program needs one or two arguments, %d given", argc - 1); | |
8d38b8ad | 68 | return -EINVAL; |
ac1a3726 ZJS |
69 | } |
70 | ||
8d38b8ad ZJS |
71 | r = fake_filesystems(); |
72 | if (r < 0) | |
73 | return r; | |
912541b0 | 74 | |
acc1bc99 YW |
75 | if (argc == 2) { |
76 | if (!streq(argv[1], "check")) { | |
77 | log_error("Unknown argument: %s", argv[1]); | |
8d38b8ad | 78 | return -EINVAL; |
acc1bc99 YW |
79 | } |
80 | ||
8d38b8ad | 81 | return 0; |
acc1bc99 | 82 | } |
110a1320 | 83 | |
948aaa7c | 84 | log_debug("version %s", PACKAGE_VERSION); |
c3dacc8b | 85 | mac_selinux_init(); |
912541b0 | 86 | |
912541b0 | 87 | action = argv[1]; |
912541b0 | 88 | devpath = argv[2]; |
912541b0 | 89 | |
1d791281 | 90 | assert_se(udev_rules_new(&rules, RESOLVE_NAME_EARLY) == 0); |
912541b0 | 91 | |
465815aa | 92 | const char *syspath = strjoina("/sys", devpath); |
b74a0b6a | 93 | r = device_new_from_synthetic_event(&dev, syspath, action); |
8d38b8ad ZJS |
94 | if (r < 0) |
95 | return log_debug_errno(r, "Failed to open device '%s'", devpath); | |
912541b0 | 96 | |
b74a0b6a | 97 | assert_se(event = udev_event_new(dev, 0, NULL)); |
912541b0 | 98 | |
72c0a2c2 | 99 | assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGHUP, SIGCHLD, -1) >= 0); |
912541b0 KS |
100 | |
101 | /* do what devtmpfs usually provides us */ | |
b74a0b6a YW |
102 | if (sd_device_get_devname(dev, &devname) >= 0) { |
103 | const char *subsystem; | |
83cd6b75 | 104 | mode_t mode = 0600; |
912541b0 | 105 | |
b74a0b6a | 106 | if (sd_device_get_subsystem(dev, &subsystem) >= 0 && streq(subsystem, "block")) |
912541b0 KS |
107 | mode |= S_IFBLK; |
108 | else | |
109 | mode |= S_IFCHR; | |
110 | ||
090be865 | 111 | if (!streq(action, "remove")) { |
b74a0b6a YW |
112 | dev_t devnum = makedev(0, 0); |
113 | ||
114 | (void) mkdir_parents_label(devname, 0755); | |
115 | (void) sd_device_get_devnum(dev, &devnum); | |
a680beb2 AB |
116 | if (mknod(devname, mode, devnum) < 0) |
117 | return log_error_errno(errno, "mknod() failed for '%s': %m", devname); | |
912541b0 | 118 | } else { |
a680beb2 AB |
119 | if (unlink(devname) < 0) |
120 | return log_error_errno(errno, "unlink('%s') failed: %m", devname); | |
b74a0b6a | 121 | (void) rmdir_parents(devname, "/"); |
912541b0 KS |
122 | } |
123 | } | |
124 | ||
66f737b4 ZJS |
125 | udev_event_execute_rules(event, 3 * USEC_PER_SEC, NULL, rules); |
126 | udev_event_execute_run(event, 3 * USEC_PER_SEC); | |
1ca208fb | 127 | |
8d38b8ad | 128 | return 0; |
f0083e3d | 129 | } |
8d38b8ad ZJS |
130 | |
131 | DEFINE_MAIN_FUNCTION(run); |