]> git.proxmox.com Git - systemd.git/blame - src/test/test-udev.c
Imported Upstream version 219
[systemd.git] / src / test / test-udev.c
CommitLineData
663996b3
MS
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>
663996b3
MS
29#include <grp.h>
30#include <sched.h>
31#include <sys/mount.h>
32#include <sys/signalfd.h>
33
34#include "missing.h"
e735f4d4 35#include "selinux-util.h"
663996b3 36#include "udev.h"
60f067b4 37#include "udev-util.h"
663996b3 38
663996b3
MS
39static int fake_filesystems(void) {
40 static const struct fakefs {
41 const char *src;
42 const char *target;
43 const char *error;
44 } fakefss[] = {
45 { "test/sys", "/sys", "failed to mount test /sys" },
46 { "test/dev", "/dev", "failed to mount test /dev" },
47 { "test/run", "/run", "failed to mount test /run" },
48 { "test/run", "/etc/udev/rules.d", "failed to mount empty /etc/udev/rules.d" },
49 { "test/run", "/usr/lib/udev/rules.d", "failed to mount empty /usr/lib/udev/rules.d" },
50 };
51 unsigned int i;
52 int err;
53
54 err = unshare(CLONE_NEWNS);
55 if (err < 0) {
56 err = -errno;
57 fprintf(stderr, "failed to call unshare(): %m\n");
58 goto out;
59 }
60
61 if (mount(NULL, "/", NULL, MS_PRIVATE|MS_REC, NULL) < 0) {
62 err = -errno;
63 fprintf(stderr, "failed to mount / as private: %m\n");
64 goto out;
65 }
66
67 for (i = 0; i < ELEMENTSOF(fakefss); i++) {
68 err = mount(fakefss[i].src, fakefss[i].target, NULL, MS_BIND, NULL);
69 if (err < 0) {
70 err = -errno;
71 fprintf(stderr, "%s %m", fakefss[i].error);
72 return err;
73 }
74 }
75out:
76 return err;
77}
78
60f067b4
JS
79int main(int argc, char *argv[]) {
80 _cleanup_udev_unref_ struct udev *udev = NULL;
81 _cleanup_udev_event_unref_ struct udev_event *event = NULL;
82 _cleanup_udev_device_unref_ struct udev_device *dev = NULL;
83 _cleanup_udev_rules_unref_ struct udev_rules *rules = NULL;
663996b3
MS
84 char syspath[UTIL_PATH_SIZE];
85 const char *devpath;
86 const char *action;
87 sigset_t mask, sigmask_orig;
88 int err;
89
90 err = fake_filesystems();
91 if (err < 0)
92 return EXIT_FAILURE;
93
94 udev = udev_new();
95 if (udev == NULL)
60f067b4
JS
96 return EXIT_FAILURE;
97
98 log_debug("version %s", VERSION);
5eef597e 99 mac_selinux_init("/dev");
663996b3
MS
100
101 sigprocmask(SIG_SETMASK, NULL, &sigmask_orig);
102
103 action = argv[1];
104 if (action == NULL) {
60f067b4 105 log_error("action missing");
663996b3
MS
106 goto out;
107 }
108
109 devpath = argv[2];
110 if (devpath == NULL) {
60f067b4 111 log_error("devpath missing");
663996b3
MS
112 goto out;
113 }
114
115 rules = udev_rules_new(udev, 1);
116
117 strscpyl(syspath, sizeof(syspath), "/sys", devpath, NULL);
118 dev = udev_device_new_from_syspath(udev, syspath);
119 if (dev == NULL) {
60f067b4 120 log_debug("unknown device '%s'", devpath);
663996b3
MS
121 goto out;
122 }
123
124 udev_device_set_action(dev, action);
125 event = udev_event_new(dev);
126
127 sigfillset(&mask);
128 sigprocmask(SIG_SETMASK, &mask, &sigmask_orig);
129 event->fd_signal = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
130 if (event->fd_signal < 0) {
131 fprintf(stderr, "error creating signalfd\n");
132 goto out;
133 }
134
135 /* do what devtmpfs usually provides us */
136 if (udev_device_get_devnode(dev) != NULL) {
137 mode_t mode = 0600;
138
139 if (streq(udev_device_get_subsystem(dev), "block"))
140 mode |= S_IFBLK;
141 else
142 mode |= S_IFCHR;
143
144 if (!streq(action, "remove")) {
145 mkdir_parents_label(udev_device_get_devnode(dev), 0755);
146 mknod(udev_device_get_devnode(dev), mode, udev_device_get_devnum(dev));
147 } else {
148 unlink(udev_device_get_devnode(dev));
5eef597e 149 rmdir_parents(udev_device_get_devnode(dev), "/");
663996b3
MS
150 }
151 }
152
f47781d8
MP
153 udev_event_execute_rules(event,
154 3 * USEC_PER_SEC, USEC_PER_SEC,
155 NULL,
156 rules,
157 &sigmask_orig);
158 udev_event_execute_run(event,
159 3 * USEC_PER_SEC, USEC_PER_SEC,
160 NULL);
663996b3
MS
161out:
162 if (event != NULL && event->fd_signal >= 0)
163 close(event->fd_signal);
5eef597e 164 mac_selinux_finish();
60f067b4
JS
165
166 return err ? EXIT_FAILURE : EXIT_SUCCESS;
663996b3 167}