]> git.proxmox.com Git - systemd.git/blob - src/test/test-udev.c
52b61b42061c73c79d5dddb3eb5007aeb402185a
[systemd.git] / src / test / test-udev.c
1 /***
2 This file is part of systemd.
3
4 Copyright 2003-2004 Greg Kroah-Hartman <greg@kroah.com>
5 Copyright 2004-2012 Kay Sievers <kay@vrfy.org>
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 <stdio.h>
22 #include <stddef.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <fcntl.h>
26 #include <ctype.h>
27 #include <errno.h>
28 #include <unistd.h>
29 #include <syslog.h>
30 #include <grp.h>
31 #include <sched.h>
32 #include <sys/mount.h>
33 #include <sys/signalfd.h>
34
35 #include "missing.h"
36 #include "udev.h"
37
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) {}
41
42 static int fake_filesystems(void) {
43 static const struct fakefs {
44 const char *src;
45 const char *target;
46 const char *error;
47 } fakefss[] = {
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" },
53 };
54 unsigned int i;
55 int err;
56
57 err = unshare(CLONE_NEWNS);
58 if (err < 0) {
59 err = -errno;
60 fprintf(stderr, "failed to call unshare(): %m\n");
61 goto out;
62 }
63
64 if (mount(NULL, "/", NULL, MS_PRIVATE|MS_REC, NULL) < 0) {
65 err = -errno;
66 fprintf(stderr, "failed to mount / as private: %m\n");
67 goto out;
68 }
69
70 for (i = 0; i < ELEMENTSOF(fakefss); i++) {
71 err = mount(fakefss[i].src, fakefss[i].target, NULL, MS_BIND, NULL);
72 if (err < 0) {
73 err = -errno;
74 fprintf(stderr, "%s %m", fakefss[i].error);
75 return err;
76 }
77 }
78 out:
79 return err;
80 }
81
82
83 int main(int argc, char *argv[])
84 {
85 struct udev *udev;
86 struct udev_event *event = NULL;
87 struct udev_device *dev = NULL;
88 struct udev_rules *rules = NULL;
89 char syspath[UTIL_PATH_SIZE];
90 const char *devpath;
91 const char *action;
92 sigset_t mask, sigmask_orig;
93 int err;
94
95 err = fake_filesystems();
96 if (err < 0)
97 return EXIT_FAILURE;
98
99 udev = udev_new();
100 if (udev == NULL)
101 exit(EXIT_FAILURE);
102 log_debug("version %s\n", VERSION);
103 label_init("/dev");
104
105 sigprocmask(SIG_SETMASK, NULL, &sigmask_orig);
106
107 action = argv[1];
108 if (action == NULL) {
109 log_error("action missing\n");
110 goto out;
111 }
112
113 devpath = argv[2];
114 if (devpath == NULL) {
115 log_error("devpath missing\n");
116 goto out;
117 }
118
119 rules = udev_rules_new(udev, 1);
120
121 strscpyl(syspath, sizeof(syspath), "/sys", devpath, NULL);
122 dev = udev_device_new_from_syspath(udev, syspath);
123 if (dev == NULL) {
124 log_debug("unknown device '%s'\n", devpath);
125 goto out;
126 }
127
128 udev_device_set_action(dev, action);
129 event = udev_event_new(dev);
130
131 sigfillset(&mask);
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");
136 goto out;
137 }
138
139 /* do what devtmpfs usually provides us */
140 if (udev_device_get_devnode(dev) != NULL) {
141 mode_t mode = 0600;
142
143 if (streq(udev_device_get_subsystem(dev), "block"))
144 mode |= S_IFBLK;
145 else
146 mode |= S_IFCHR;
147
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));
151 } else {
152 unlink(udev_device_get_devnode(dev));
153 util_delete_path(udev, udev_device_get_devnode(dev));
154 }
155 }
156
157 err = udev_event_execute_rules(event, rules, &sigmask_orig);
158 if (err == 0)
159 udev_event_execute_run(event, NULL);
160 out:
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);
166 label_finish();
167 udev_unref(udev);
168 if (err != 0)
169 return EXIT_FAILURE;
170 return EXIT_SUCCESS;
171 }