2 This file is part of systemd.
4 Copyright 2003-2004 Greg Kroah-Hartman <greg@kroah.com>
5 Copyright 2004-2012 Kay Sievers <kay@vrfy.org>
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.
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.
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/>.
32 #include <sys/mount.h>
33 #include <sys/signalfd.h>
38 void udev_main_log(struct udev *udev, int priority,
39 const char *file, int line, const char *fn,
40 const char *format, va_list args) {}
42 static int fake_filesystems(void) {
43 static const struct fakefs {
48 { "test/sys", "/sys", "failed to mount test /sys" },
49 { "test/dev", "/dev", "failed to mount test /dev" },
50 { "test/run", "/run", "failed to mount test /run" },
51 { "test/run", "/etc/udev/rules.d", "failed to mount empty /etc/udev/rules.d" },
52 { "test/run", "/usr/lib/udev/rules.d", "failed to mount empty /usr/lib/udev/rules.d" },
57 err = unshare(CLONE_NEWNS);
60 fprintf(stderr, "failed to call unshare(): %m\n");
64 if (mount(NULL, "/", NULL, MS_PRIVATE|MS_REC, NULL) < 0) {
66 fprintf(stderr, "failed to mount / as private: %m\n");
70 for (i = 0; i < ELEMENTSOF(fakefss); i++) {
71 err = mount(fakefss[i].src, fakefss[i].target, NULL, MS_BIND, NULL);
74 fprintf(stderr, "%s %m", fakefss[i].error);
83 int main(int argc, char *argv[])
86 struct udev_event *event = NULL;
87 struct udev_device *dev = NULL;
88 struct udev_rules *rules = NULL;
89 char syspath[UTIL_PATH_SIZE];
92 sigset_t mask, sigmask_orig;
95 err = fake_filesystems();
102 log_debug("version %s\n", VERSION);
105 sigprocmask(SIG_SETMASK, NULL, &sigmask_orig);
108 if (action == NULL) {
109 log_error("action missing\n");
114 if (devpath == NULL) {
115 log_error("devpath missing\n");
119 rules = udev_rules_new(udev, 1);
121 strscpyl(syspath, sizeof(syspath), "/sys", devpath, NULL);
122 dev = udev_device_new_from_syspath(udev, syspath);
124 log_debug("unknown device '%s'\n", devpath);
128 udev_device_set_action(dev, action);
129 event = udev_event_new(dev);
132 sigprocmask(SIG_SETMASK, &mask, &sigmask_orig);
133 event->fd_signal = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
134 if (event->fd_signal < 0) {
135 fprintf(stderr, "error creating signalfd\n");
139 /* do what devtmpfs usually provides us */
140 if (udev_device_get_devnode(dev) != NULL) {
143 if (streq(udev_device_get_subsystem(dev), "block"))
148 if (!streq(action, "remove")) {
149 mkdir_parents_label(udev_device_get_devnode(dev), 0755);
150 mknod(udev_device_get_devnode(dev), mode, udev_device_get_devnum(dev));
152 unlink(udev_device_get_devnode(dev));
153 util_delete_path(udev, udev_device_get_devnode(dev));
157 err = udev_event_execute_rules(event, rules, &sigmask_orig);
159 udev_event_execute_run(event, NULL);
161 if (event != NULL && event->fd_signal >= 0)
162 close(event->fd_signal);
163 udev_event_unref(event);
164 udev_device_unref(dev);
165 udev_rules_unref(rules);