]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/test/test-udev.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / test / test-udev.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
1298001e
KS
2/***
3 This file is part of systemd.
4
5 Copyright 2003-2004 Greg Kroah-Hartman <greg@kroah.com>
6 Copyright 2004-2012 Kay Sievers <kay@vrfy.org>
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
f0083e3d 21
c81b35c0 22#include <errno.h>
4cb72937 23#include <sched.h>
07630cea
LP
24#include <stdio.h>
25#include <stdlib.h>
4cb72937 26#include <sys/mount.h>
2181d30a 27#include <sys/signalfd.h>
07630cea 28#include <unistd.h>
85511f02 29
f4f15635 30#include "fs-util.h"
dbab702a 31#include "log.h"
10efe2cd 32#include "missing.h"
d7b8eec7 33#include "selinux-util.h"
8314de1d 34#include "signal-util.h"
07630cea 35#include "string-util.h"
1ca208fb 36#include "udev-util.h"
07630cea 37#include "udev.h"
f0083e3d 38
4cb72937
KS
39static int fake_filesystems(void) {
40 static const struct fakefs {
41 const char *src;
42 const char *target;
43 const char *error;
ad43ccb0 44 bool ignore_mount_error;
4cb72937 45 } fakefss[] = {
ad43ccb0
EV
46 { "test/tmpfs/sys", "/sys", "failed to mount test /sys", false },
47 { "test/tmpfs/dev", "/dev", "failed to mount test /dev", false },
48 { "test/run", "/run", "failed to mount test /run", false },
49 { "test/run", "/etc/udev/rules.d", "failed to mount empty /etc/udev/rules.d", true },
50 { "test/run", UDEVLIBEXECDIR "/rules.d", "failed to mount empty " UDEVLIBEXECDIR "/rules.d", true },
4cb72937
KS
51 };
52 unsigned int i;
4cb72937 53
dbab702a
EV
54 if (unshare(CLONE_NEWNS) < 0)
55 return log_error_errno(errno, "failed to call unshare(): %m");
04eaa668 56
dbab702a
EV
57 if (mount(NULL, "/", NULL, MS_PRIVATE|MS_REC, NULL) < 0)
58 return log_error_errno(errno, "failed to mount / as private: %m");
4cb72937
KS
59
60 for (i = 0; i < ELEMENTSOF(fakefss); i++) {
dbab702a
EV
61 if (mount(fakefss[i].src, fakefss[i].target, NULL, MS_BIND, NULL) < 0) {
62 log_full_errno(fakefss[i].ignore_mount_error ? LOG_DEBUG : LOG_ERR, errno, "%s: %m", fakefss[i].error);
ad43ccb0 63 if (!fakefss[i].ignore_mount_error)
dbab702a 64 return -errno;
4cb72937
KS
65 }
66 }
dbab702a
EV
67
68 return 0;
4cb72937
KS
69}
70
f168c273 71int main(int argc, char *argv[]) {
1ca208fb
ZJS
72 _cleanup_udev_unref_ struct udev *udev = NULL;
73 _cleanup_udev_event_unref_ struct udev_event *event = NULL;
74 _cleanup_udev_device_unref_ struct udev_device *dev = NULL;
75 _cleanup_udev_rules_unref_ struct udev_rules *rules = NULL;
912541b0
KS
76 char syspath[UTIL_PATH_SIZE];
77 const char *devpath;
78 const char *action;
4cb72937
KS
79 int err;
80
dbab702a
EV
81 log_parse_environment();
82 log_open();
83
4cb72937
KS
84 err = fake_filesystems();
85 if (err < 0)
86 return EXIT_FAILURE;
912541b0
KS
87
88 udev = udev_new();
89 if (udev == NULL)
1ca208fb
ZJS
90 return EXIT_FAILURE;
91
948aaa7c 92 log_debug("version %s", PACKAGE_VERSION);
c3dacc8b 93 mac_selinux_init();
912541b0 94
912541b0
KS
95 action = argv[1];
96 if (action == NULL) {
9f6445e3 97 log_error("action missing");
912541b0
KS
98 goto out;
99 }
100
101 devpath = argv[2];
102 if (devpath == NULL) {
9f6445e3 103 log_error("devpath missing");
912541b0
KS
104 goto out;
105 }
106
107 rules = udev_rules_new(udev, 1);
108
d5a89d7d 109 strscpyl(syspath, sizeof(syspath), "/sys", devpath, NULL);
bf0e00ec 110 dev = udev_device_new_from_synthetic_event(udev, syspath, action);
912541b0 111 if (dev == NULL) {
9f6445e3 112 log_debug("unknown device '%s'", devpath);
912541b0
KS
113 goto out;
114 }
115
912541b0
KS
116 event = udev_event_new(dev);
117
72c0a2c2 118 assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGHUP, SIGCHLD, -1) >= 0);
912541b0
KS
119
120 /* do what devtmpfs usually provides us */
121 if (udev_device_get_devnode(dev) != NULL) {
83cd6b75 122 mode_t mode = 0600;
912541b0 123
090be865 124 if (streq(udev_device_get_subsystem(dev), "block"))
912541b0
KS
125 mode |= S_IFBLK;
126 else
127 mode |= S_IFCHR;
128
090be865 129 if (!streq(action, "remove")) {
d2e54fae 130 mkdir_parents_label(udev_device_get_devnode(dev), 0755);
912541b0
KS
131 mknod(udev_device_get_devnode(dev), mode, udev_device_get_devnum(dev));
132 } else {
133 unlink(udev_device_get_devnode(dev));
37d52274 134 rmdir_parents(udev_device_get_devnode(dev), "/");
912541b0
KS
135 }
136 }
137
adeba500
KS
138 udev_event_execute_rules(event,
139 3 * USEC_PER_SEC, USEC_PER_SEC,
140 NULL,
8314de1d 141 rules);
adeba500 142 udev_event_execute_run(event,
8314de1d 143 3 * USEC_PER_SEC, USEC_PER_SEC);
2181d30a 144out:
cc56fafe 145 mac_selinux_finish();
1ca208fb
ZJS
146
147 return err ? EXIT_FAILURE : EXIT_SUCCESS;
f0083e3d 148}