]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-udev.c
Merge pull request #756 from ldzhong/fix
[thirdparty/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 <stdlib.h>
23 #include <errno.h>
24 #include <unistd.h>
25 #include <sched.h>
26 #include <sys/mount.h>
27 #include <sys/signalfd.h>
28
29 #include "missing.h"
30 #include "selinux-util.h"
31 #include "signal-util.h"
32 #include "udev.h"
33 #include "udev-util.h"
34
35 static int fake_filesystems(void) {
36 static const struct fakefs {
37 const char *src;
38 const char *target;
39 const char *error;
40 } fakefss[] = {
41 { "test/sys", "/sys", "failed to mount test /sys" },
42 { "test/dev", "/dev", "failed to mount test /dev" },
43 { "test/run", "/run", "failed to mount test /run" },
44 { "test/run", "/etc/udev/rules.d", "failed to mount empty /etc/udev/rules.d" },
45 { "test/run", "/usr/lib/udev/rules.d", "failed to mount empty /usr/lib/udev/rules.d" },
46 };
47 unsigned int i;
48 int err;
49
50 err = unshare(CLONE_NEWNS);
51 if (err < 0) {
52 err = -errno;
53 fprintf(stderr, "failed to call unshare(): %m\n");
54 goto out;
55 }
56
57 if (mount(NULL, "/", NULL, MS_PRIVATE|MS_REC, NULL) < 0) {
58 err = -errno;
59 fprintf(stderr, "failed to mount / as private: %m\n");
60 goto out;
61 }
62
63 for (i = 0; i < ELEMENTSOF(fakefss); i++) {
64 err = mount(fakefss[i].src, fakefss[i].target, NULL, MS_BIND, NULL);
65 if (err < 0) {
66 err = -errno;
67 fprintf(stderr, "%s %m", fakefss[i].error);
68 return err;
69 }
70 }
71 out:
72 return err;
73 }
74
75 int main(int argc, char *argv[]) {
76 _cleanup_udev_unref_ struct udev *udev = NULL;
77 _cleanup_udev_event_unref_ struct udev_event *event = NULL;
78 _cleanup_udev_device_unref_ struct udev_device *dev = NULL;
79 _cleanup_udev_rules_unref_ struct udev_rules *rules = NULL;
80 char syspath[UTIL_PATH_SIZE];
81 const char *devpath;
82 const char *action;
83 int err;
84
85 err = fake_filesystems();
86 if (err < 0)
87 return EXIT_FAILURE;
88
89 udev = udev_new();
90 if (udev == NULL)
91 return EXIT_FAILURE;
92
93 log_debug("version %s", VERSION);
94 mac_selinux_init("/dev");
95
96 action = argv[1];
97 if (action == NULL) {
98 log_error("action missing");
99 goto out;
100 }
101
102 devpath = argv[2];
103 if (devpath == NULL) {
104 log_error("devpath missing");
105 goto out;
106 }
107
108 rules = udev_rules_new(udev, 1);
109
110 strscpyl(syspath, sizeof(syspath), "/sys", devpath, NULL);
111 dev = udev_device_new_from_synthetic_event(udev, syspath, action);
112 if (dev == NULL) {
113 log_debug("unknown device '%s'", devpath);
114 goto out;
115 }
116
117 event = udev_event_new(dev);
118
119 assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGHUP, SIGCHLD, -1) >= 0);
120
121 /* do what devtmpfs usually provides us */
122 if (udev_device_get_devnode(dev) != NULL) {
123 mode_t mode = 0600;
124
125 if (streq(udev_device_get_subsystem(dev), "block"))
126 mode |= S_IFBLK;
127 else
128 mode |= S_IFCHR;
129
130 if (!streq(action, "remove")) {
131 mkdir_parents_label(udev_device_get_devnode(dev), 0755);
132 mknod(udev_device_get_devnode(dev), mode, udev_device_get_devnum(dev));
133 } else {
134 unlink(udev_device_get_devnode(dev));
135 rmdir_parents(udev_device_get_devnode(dev), "/");
136 }
137 }
138
139 udev_event_execute_rules(event,
140 3 * USEC_PER_SEC, USEC_PER_SEC,
141 NULL,
142 rules);
143 udev_event_execute_run(event,
144 3 * USEC_PER_SEC, USEC_PER_SEC);
145 out:
146 mac_selinux_finish();
147
148 return err ? EXIT_FAILURE : EXIT_SUCCESS;
149 }