]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/test/test-udev.c
tests: when running a manager object in a test, migrate to private cgroup subroot...
[thirdparty/systemd.git] / src / test / test-udev.c
CommitLineData
1298001e
KS
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***/
f0083e3d 20
c81b35c0 21#include <errno.h>
4cb72937 22#include <sched.h>
07630cea
LP
23#include <stdio.h>
24#include <stdlib.h>
4cb72937 25#include <sys/mount.h>
2181d30a 26#include <sys/signalfd.h>
07630cea 27#include <unistd.h>
85511f02 28
f4f15635 29#include "fs-util.h"
dbab702a 30#include "log.h"
10efe2cd 31#include "missing.h"
d7b8eec7 32#include "selinux-util.h"
8314de1d 33#include "signal-util.h"
07630cea 34#include "string-util.h"
1ca208fb 35#include "udev-util.h"
07630cea 36#include "udev.h"
f0083e3d 37
4cb72937
KS
38static int fake_filesystems(void) {
39 static const struct fakefs {
40 const char *src;
41 const char *target;
42 const char *error;
ad43ccb0 43 bool ignore_mount_error;
4cb72937 44 } fakefss[] = {
ad43ccb0
EV
45 { "test/tmpfs/sys", "/sys", "failed to mount test /sys", false },
46 { "test/tmpfs/dev", "/dev", "failed to mount test /dev", false },
47 { "test/run", "/run", "failed to mount test /run", false },
48 { "test/run", "/etc/udev/rules.d", "failed to mount empty /etc/udev/rules.d", true },
49 { "test/run", UDEVLIBEXECDIR "/rules.d", "failed to mount empty " UDEVLIBEXECDIR "/rules.d", true },
4cb72937
KS
50 };
51 unsigned int i;
4cb72937 52
dbab702a
EV
53 if (unshare(CLONE_NEWNS) < 0)
54 return log_error_errno(errno, "failed to call unshare(): %m");
04eaa668 55
dbab702a
EV
56 if (mount(NULL, "/", NULL, MS_PRIVATE|MS_REC, NULL) < 0)
57 return log_error_errno(errno, "failed to mount / as private: %m");
4cb72937
KS
58
59 for (i = 0; i < ELEMENTSOF(fakefss); i++) {
dbab702a
EV
60 if (mount(fakefss[i].src, fakefss[i].target, NULL, MS_BIND, NULL) < 0) {
61 log_full_errno(fakefss[i].ignore_mount_error ? LOG_DEBUG : LOG_ERR, errno, "%s: %m", fakefss[i].error);
ad43ccb0 62 if (!fakefss[i].ignore_mount_error)
dbab702a 63 return -errno;
4cb72937
KS
64 }
65 }
dbab702a
EV
66
67 return 0;
4cb72937
KS
68}
69
f168c273 70int main(int argc, char *argv[]) {
1ca208fb
ZJS
71 _cleanup_udev_unref_ struct udev *udev = NULL;
72 _cleanup_udev_event_unref_ struct udev_event *event = NULL;
73 _cleanup_udev_device_unref_ struct udev_device *dev = NULL;
74 _cleanup_udev_rules_unref_ struct udev_rules *rules = NULL;
912541b0
KS
75 char syspath[UTIL_PATH_SIZE];
76 const char *devpath;
77 const char *action;
4cb72937
KS
78 int err;
79
dbab702a
EV
80 log_parse_environment();
81 log_open();
82
4cb72937
KS
83 err = fake_filesystems();
84 if (err < 0)
85 return EXIT_FAILURE;
912541b0
KS
86
87 udev = udev_new();
88 if (udev == NULL)
1ca208fb
ZJS
89 return EXIT_FAILURE;
90
948aaa7c 91 log_debug("version %s", PACKAGE_VERSION);
c3dacc8b 92 mac_selinux_init();
912541b0 93
912541b0
KS
94 action = argv[1];
95 if (action == NULL) {
9f6445e3 96 log_error("action missing");
912541b0
KS
97 goto out;
98 }
99
100 devpath = argv[2];
101 if (devpath == NULL) {
9f6445e3 102 log_error("devpath missing");
912541b0
KS
103 goto out;
104 }
105
106 rules = udev_rules_new(udev, 1);
107
d5a89d7d 108 strscpyl(syspath, sizeof(syspath), "/sys", devpath, NULL);
bf0e00ec 109 dev = udev_device_new_from_synthetic_event(udev, syspath, action);
912541b0 110 if (dev == NULL) {
9f6445e3 111 log_debug("unknown device '%s'", devpath);
912541b0
KS
112 goto out;
113 }
114
912541b0
KS
115 event = udev_event_new(dev);
116
72c0a2c2 117 assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGHUP, SIGCHLD, -1) >= 0);
912541b0
KS
118
119 /* do what devtmpfs usually provides us */
120 if (udev_device_get_devnode(dev) != NULL) {
83cd6b75 121 mode_t mode = 0600;
912541b0 122
090be865 123 if (streq(udev_device_get_subsystem(dev), "block"))
912541b0
KS
124 mode |= S_IFBLK;
125 else
126 mode |= S_IFCHR;
127
090be865 128 if (!streq(action, "remove")) {
d2e54fae 129 mkdir_parents_label(udev_device_get_devnode(dev), 0755);
912541b0
KS
130 mknod(udev_device_get_devnode(dev), mode, udev_device_get_devnum(dev));
131 } else {
132 unlink(udev_device_get_devnode(dev));
37d52274 133 rmdir_parents(udev_device_get_devnode(dev), "/");
912541b0
KS
134 }
135 }
136
adeba500
KS
137 udev_event_execute_rules(event,
138 3 * USEC_PER_SEC, USEC_PER_SEC,
139 NULL,
8314de1d 140 rules);
adeba500 141 udev_event_execute_run(event,
8314de1d 142 3 * USEC_PER_SEC, USEC_PER_SEC);
2181d30a 143out:
cc56fafe 144 mac_selinux_finish();
1ca208fb
ZJS
145
146 return err ? EXIT_FAILURE : EXIT_SUCCESS;
f0083e3d 147}