]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/test/test-udev.c
Merge pull request #11827 from keszybz/pkgconfig-variables
[thirdparty/systemd.git] / src / test / test-udev.c
index bed51c1270873e0c73757c57a90956202b7d46e8..ab31f5a2f1bbaa25c363aa97068bac51550eb70f 100644 (file)
 #include <sys/signalfd.h>
 #include <unistd.h>
 
+#include "build.h"
+#include "device-private.h"
 #include "fs-util.h"
 #include "log.h"
+#include "main-func.h"
 #include "missing.h"
+#include "mkdir.h"
 #include "selinux-util.h"
 #include "signal-util.h"
 #include "string-util.h"
-#include "udev-util.h"
+#include "tests.h"
 #include "udev.h"
 
 static int fake_filesystems(void) {
@@ -27,106 +31,102 @@ static int fake_filesystems(void) {
                 const char *error;
                 bool ignore_mount_error;
         } fakefss[] = {
-                { "test/tmpfs/sys", "/sys",                    "failed to mount test /sys",                        false },
-                { "test/tmpfs/dev", "/dev",                    "failed to mount test /dev",                        false },
-                { "test/run",       "/run",                    "failed to mount test /run",                        false },
-                { "test/run",       "/etc/udev/rules.d",       "failed to mount empty /etc/udev/rules.d",          true },
-                { "test/run",       UDEVLIBEXECDIR "/rules.d", "failed to mount empty " UDEVLIBEXECDIR "/rules.d", true },
+                { "test/tmpfs/sys", "/sys",                    "Failed to mount test /sys",                        false },
+                { "test/tmpfs/dev", "/dev",                    "Failed to mount test /dev",                        false },
+                { "test/run",       "/run",                    "Failed to mount test /run",                        false },
+                { "test/run",       "/etc/udev/rules.d",       "Failed to mount empty /etc/udev/rules.d",          true },
+                { "test/run",       UDEVLIBEXECDIR "/rules.d", "Failed to mount empty " UDEVLIBEXECDIR "/rules.d", true },
         };
-        unsigned int i;
+        unsigned i;
 
         if (unshare(CLONE_NEWNS) < 0)
-                return log_error_errno(errno, "failed to call unshare(): %m");
+                return log_error_errno(errno, "Failed to call unshare(): %m");
 
-        if (mount(NULL, "/", NULL, MS_PRIVATE|MS_REC, NULL) < 0)
-                return log_error_errno(errno, "failed to mount / as private: %m");
+        if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0)
+                return log_error_errno(errno, "Failed to mount / as private: %m");
 
-        for (i = 0; i < ELEMENTSOF(fakefss); i++) {
+        for (i = 0; i < ELEMENTSOF(fakefss); i++)
                 if (mount(fakefss[i].src, fakefss[i].target, NULL, MS_BIND, NULL) < 0) {
                         log_full_errno(fakefss[i].ignore_mount_error ? LOG_DEBUG : LOG_ERR, errno, "%s: %m", fakefss[i].error);
                         if (!fakefss[i].ignore_mount_error)
                                 return -errno;
                 }
-        }
 
         return 0;
 }
 
-int main(int argc, char *argv[]) {
-        _cleanup_(udev_unrefp) struct udev *udev = NULL;
-        _cleanup_(udev_event_unrefp) struct udev_event *event = NULL;
-        _cleanup_(udev_device_unrefp) struct udev_device *dev = NULL;
-        _cleanup_(udev_rules_unrefp) struct udev_rules *rules = NULL;
-        char syspath[UTIL_PATH_SIZE];
-        const char *devpath;
-        const char *action;
-        int err;
+static int run(int argc, char *argv[]) {
+        _cleanup_(udev_rules_freep) UdevRules *rules = NULL;
+        _cleanup_(udev_event_freep) UdevEvent *event = NULL;
+        _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
+        const char *devpath, *devname, *action;
+        int r;
 
-        log_parse_environment();
-        log_open();
+        test_setup_logging(LOG_INFO);
 
-        err = fake_filesystems();
-        if (err < 0)
-                return EXIT_FAILURE;
+        if (!IN_SET(argc, 2, 3)) {
+                log_error("This program needs one or two arguments, %d given", argc - 1);
+                return -EINVAL;
+        }
 
-        udev = udev_new();
-        if (udev == NULL)
-                return EXIT_FAILURE;
+        r = fake_filesystems();
+        if (r < 0)
+                return r;
 
-        log_debug("version %s", PACKAGE_VERSION);
-        mac_selinux_init();
+        if (argc == 2) {
+                if (!streq(argv[1], "check")) {
+                        log_error("Unknown argument: %s", argv[1]);
+                        return -EINVAL;
+                }
 
-        action = argv[1];
-        if (action == NULL) {
-                log_error("action missing");
-                goto out;
+                return 0;
         }
 
+        log_debug("version %s", GIT_VERSION);
+        mac_selinux_init();
+
+        action = argv[1];
         devpath = argv[2];
-        if (devpath == NULL) {
-                log_error("devpath missing");
-                goto out;
-        }
 
-        rules = udev_rules_new(udev, 1);
+        assert_se(udev_rules_new(&rules, RESOLVE_NAME_EARLY) == 0);
 
-        strscpyl(syspath, sizeof(syspath), "/sys", devpath, NULL);
-        dev = udev_device_new_from_synthetic_event(udev, syspath, action);
-        if (dev == NULL) {
-                log_debug("unknown device '%s'", devpath);
-                goto out;
-        }
+        const char *syspath = strjoina("/sys", devpath);
+        r = device_new_from_synthetic_event(&dev, syspath, action);
+        if (r < 0)
+                return log_debug_errno(r, "Failed to open device '%s'", devpath);
 
-        event = udev_event_new(dev);
+        assert_se(event = udev_event_new(dev, 0, NULL));
 
         assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGHUP, SIGCHLD, -1) >= 0);
 
         /* do what devtmpfs usually provides us */
-        if (udev_device_get_devnode(dev) != NULL) {
+        if (sd_device_get_devname(dev, &devname) >= 0) {
+                const char *subsystem;
                 mode_t mode = 0600;
 
-                if (streq(udev_device_get_subsystem(dev), "block"))
+                if (sd_device_get_subsystem(dev, &subsystem) >= 0 && streq(subsystem, "block"))
                         mode |= S_IFBLK;
                 else
                         mode |= S_IFCHR;
 
                 if (!streq(action, "remove")) {
-                        mkdir_parents_label(udev_device_get_devnode(dev), 0755);
-                        mknod(udev_device_get_devnode(dev), mode, udev_device_get_devnum(dev));
+                        dev_t devnum = makedev(0, 0);
+
+                        (void) mkdir_parents_label(devname, 0755);
+                        (void) sd_device_get_devnum(dev, &devnum);
+                        if (mknod(devname, mode, devnum) < 0)
+                                return log_error_errno(errno, "mknod() failed for '%s': %m", devname);
                 } else {
-                        unlink(udev_device_get_devnode(dev));
-                        rmdir_parents(udev_device_get_devnode(dev), "/");
+                        if (unlink(devname) < 0)
+                                return log_error_errno(errno, "unlink('%s') failed: %m", devname);
+                        (void) rmdir_parents(devname, "/");
                 }
         }
 
-        udev_event_execute_rules(event,
-                                 3 * USEC_PER_SEC, USEC_PER_SEC,
-                                 NULL,
-                                 rules);
-        udev_event_execute_run(event,
-                               3 * USEC_PER_SEC, USEC_PER_SEC);
-out:
-        mac_selinux_finish();
+        udev_event_execute_rules(event, 3 * USEC_PER_SEC, NULL, rules);
+        udev_event_execute_run(event, 3 * USEC_PER_SEC);
 
-        return err ? EXIT_FAILURE : EXIT_SUCCESS;
+        return 0;
 }
+
+DEFINE_MAIN_FUNCTION(run);