chiark / gitweb /
udev: get rid of TEST_PREFIX and use unshare() to fake /sys, /dev, /run
authorKay Sievers <kay@vrfy.org>
Sun, 15 Jul 2012 20:10:46 +0000 (22:10 +0200)
committerKay Sievers <kay@vrfy.org>
Sun, 15 Jul 2012 20:10:46 +0000 (22:10 +0200)
Makefile.am
TODO
src/libudev/libudev-device-private.c
src/libudev/libudev-device.c
src/libudev/libudev-private.h
src/test/test-udev.c
src/udev/udev-event.c
src/udev/udev-node.c
src/udev/udev-rules.c
test/udev-test.pl

index d9fb72f8e5416e574f10699d6c9a87af9b79528c..c9ea8047ad6673e4aab92b5ff404ae418ed1a713 100644 (file)
@@ -1756,22 +1756,10 @@ test_libudev_LDADD = \
        libudev.la
 
 test_udev_SOURCES = \
-       src/test/test-udev.c \
-       $(libudev_core_la_SOURCES) \
-       $(libudev_private_la_SOURCES)
-
-# The test-udev program needs everything compiled with relative path
-# names for /sys, /dev, /run prefixed, pointing to our test/ directory.
-test_udev_CFLAGS = \
-       -DTEST_PREFIX=\"test\" \
-       $(libudev_core_la_CFLAGS) \
-       $(libudev_private_la_CFLAGS)
-
-test_udev_CPPFLAGS =\
-       $(libudev_core_la_CPPFLAGS)
+       src/test/test-udev.c
 
 test_udev_LDADD = \
-       libsystemd-label.la \
+       libudev-core.la \
        libsystemd-shared.la \
        $(BLKID_LIBS) \
        $(KMOD_LIBS) \
diff --git a/TODO b/TODO
index e3debb45d1b3ef9fd6e42325bd95ee30dcda26ef..1ec59b2f53043c5bb979be987ef8fd6a961ff3c6 100644 (file)
--- a/TODO
+++ b/TODO
@@ -33,8 +33,6 @@ Bugfixes:
   Jul 09 18:22:37 mop [21866]: Process 21865 (systemd) dumped core.
 
 Features:
-* udev: use 'unshare' to test udev with fake sysfs tree, and kill TEST_PREFIX entirely
-
 * change mount access mode of 0700 or so for debugfs?
 
 * logind: wakelock/opportunistic suspend support
index 234773662bb2b8e0cc0fe07b67b1b7ce270ccc58..00fa3b88908467b0a4448a446bb31b9f937c9d9e 100644 (file)
@@ -30,7 +30,7 @@ static void udev_device_tag(struct udev_device *dev, const char *tag, bool add)
         id = udev_device_get_id_filename(dev);
         if (id == NULL)
                 return;
-        util_strscpyl(filename, sizeof(filename), TEST_PREFIX "/run/udev/tags/", tag, "/", id, NULL);
+        util_strscpyl(filename, sizeof(filename), "/run/udev/tags/", tag, "/", id, NULL);
 
         if (add) {
                 int fd;
@@ -107,7 +107,7 @@ int udev_device_update_db(struct udev_device *udev_device)
                 return -1;
 
         has_info = device_has_info(udev_device);
-        util_strscpyl(filename, sizeof(filename), TEST_PREFIX "/run/udev/data/", id, NULL);
+        util_strscpyl(filename, sizeof(filename), "/run/udev/data/", id, NULL);
 
         /* do not store anything for otherwise empty devices */
         if (!has_info &&
@@ -138,7 +138,7 @@ int udev_device_update_db(struct udev_device *udev_device)
 
                 if (major(udev_device_get_devnum(udev_device)) > 0) {
                         udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(udev_device))
-                                fprintf(f, "S:%s\n", udev_list_entry_get_name(list_entry) + strlen(TEST_PREFIX "/dev/"));
+                                fprintf(f, "S:%s\n", udev_list_entry_get_name(list_entry) + strlen("/dev/"));
                         if (udev_device_get_devlink_priority(udev_device) != 0)
                                 fprintf(f, "L:%i\n", udev_device_get_devlink_priority(udev_device));
                         if (udev_device_get_watch_handle(udev_device) >= 0)
@@ -175,7 +175,7 @@ int udev_device_delete_db(struct udev_device *udev_device)
         id = udev_device_get_id_filename(udev_device);
         if (id == NULL)
                 return -1;
-        util_strscpyl(filename, sizeof(filename), TEST_PREFIX "/run/udev/data/", id, NULL);
+        util_strscpyl(filename, sizeof(filename), "/run/udev/data/", id, NULL);
         unlink(filename);
         return 0;
 }
index a8277d1363dc4b039d20dd6a01bd4c1edee5f337..98077e777de7c4787d4c5d1a47c45c30af17eaed 100644 (file)
@@ -360,7 +360,7 @@ void udev_device_add_property_from_string_parse(struct udev_device *udev_device,
         if (startswith(property, "DEVPATH=")) {
                 char path[UTIL_PATH_SIZE];
 
-                util_strscpyl(path, sizeof(path), TEST_PREFIX "/sys", &property[8], NULL);
+                util_strscpyl(path, sizeof(path), "/sys", &property[8], NULL);
                 udev_device_set_syspath(udev_device, path);
         } else if (startswith(property, "SUBSYSTEM=")) {
                 udev_device_set_subsystem(udev_device, &property[10]);
@@ -479,7 +479,7 @@ int udev_device_read_db(struct udev_device *udev_device, const char *dbfile)
                 id = udev_device_get_id_filename(udev_device);
                 if (id == NULL)
                         return -1;
-                util_strscpyl(filename, sizeof(filename), TEST_PREFIX "/run/udev/data/", id, NULL);
+                util_strscpyl(filename, sizeof(filename), "/run/udev/data/", id, NULL);
                 dbfile = filename;
         }
 
@@ -502,7 +502,7 @@ int udev_device_read_db(struct udev_device *udev_device, const char *dbfile)
                 val = &line[2];
                 switch(line[0]) {
                 case 'S':
-                        util_strscpyl(filename, sizeof(filename), TEST_PREFIX "/dev/", val, NULL);
+                        util_strscpyl(filename, sizeof(filename), "/dev/", val, NULL);
                         udev_device_add_devlink(udev_device, filename, 0);
                         break;
                 case 'L':
@@ -642,13 +642,13 @@ _public_ struct udev_device *udev_device_new_from_syspath(struct udev *udev, con
                 return NULL;
 
         /* path starts in sys */
-        if (!startswith(syspath, TEST_PREFIX "/sys")) {
+        if (!startswith(syspath, "/sys")) {
                 udev_dbg(udev, "not in sys :%s\n", syspath);
                 return NULL;
         }
 
         /* path is not a root directory */
-        subdir = syspath + strlen(TEST_PREFIX "/sys");
+        subdir = syspath + strlen("/sys");
         pos = strrchr(subdir, '/');
         if (pos == NULL || pos[1] == '\0' || pos < &subdir[2])
                 return NULL;
@@ -657,7 +657,7 @@ _public_ struct udev_device *udev_device_new_from_syspath(struct udev *udev, con
         util_strscpy(path, sizeof(path), syspath);
         util_resolve_sys_link(udev, path, sizeof(path));
 
-        if (startswith(path + strlen(TEST_PREFIX "/sys"), "/devices/")) {
+        if (startswith(path + strlen("/sys"), "/devices/")) {
                 char file[UTIL_PATH_SIZE];
 
                 /* all "devices" require a "uevent" file */
@@ -709,7 +709,7 @@ _public_ struct udev_device *udev_device_new_from_devnum(struct udev *udev, char
                 return NULL;
 
         /* use /sys/dev/{block,char}/<maj>:<min> link */
-        snprintf(path, sizeof(path), TEST_PREFIX "/sys/dev/%s/%u:%u",
+        snprintf(path, sizeof(path), "/sys/dev/%s/%u:%u",
                  type_str, major(devnum), minor(devnum));
         return udev_device_new_from_syspath(udev, path);
 }
@@ -790,22 +790,22 @@ _public_ struct udev_device *udev_device_new_from_subsystem_sysname(struct udev
         struct stat statbuf;
 
         if (streq(subsystem, "subsystem")) {
-                util_strscpyl(path, sizeof(path), TEST_PREFIX "/sys/subsystem/", sysname, NULL);
+                util_strscpyl(path, sizeof(path), "/sys/subsystem/", sysname, NULL);
                 if (stat(path, &statbuf) == 0)
                         goto found;
 
-                util_strscpyl(path, sizeof(path), TEST_PREFIX "/sys/bus/", sysname, NULL);
+                util_strscpyl(path, sizeof(path), "/sys/bus/", sysname, NULL);
                 if (stat(path, &statbuf) == 0)
                         goto found;
 
-                util_strscpyl(path, sizeof(path), TEST_PREFIX "/sys/class/", sysname, NULL);
+                util_strscpyl(path, sizeof(path), "/sys/class/", sysname, NULL);
                 if (stat(path, &statbuf) == 0)
                         goto found;
                 goto out;
         }
 
         if (streq(subsystem, "module")) {
-                util_strscpyl(path, sizeof(path), TEST_PREFIX "/sys/module/", sysname, NULL);
+                util_strscpyl(path, sizeof(path), "/sys/module/", sysname, NULL);
                 if (stat(path, &statbuf) == 0)
                         goto found;
                 goto out;
@@ -821,26 +821,26 @@ _public_ struct udev_device *udev_device_new_from_subsystem_sysname(struct udev
                         driver[0] = '\0';
                         driver = &driver[1];
 
-                        util_strscpyl(path, sizeof(path), TEST_PREFIX "/sys/subsystem/", subsys, "/drivers/", driver, NULL);
+                        util_strscpyl(path, sizeof(path), "/sys/subsystem/", subsys, "/drivers/", driver, NULL);
                         if (stat(path, &statbuf) == 0)
                                 goto found;
 
-                        util_strscpyl(path, sizeof(path), TEST_PREFIX "/sys/bus/", subsys, "/drivers/", driver, NULL);
+                        util_strscpyl(path, sizeof(path), "/sys/bus/", subsys, "/drivers/", driver, NULL);
                         if (stat(path, &statbuf) == 0)
                                 goto found;
                 }
                 goto out;
         }
 
-        util_strscpyl(path, sizeof(path), TEST_PREFIX "/sys/subsystem/", subsystem, "/devices/", sysname, NULL);
+        util_strscpyl(path, sizeof(path), "/sys/subsystem/", subsystem, "/devices/", sysname, NULL);
         if (stat(path, &statbuf) == 0)
                 goto found;
 
-        util_strscpyl(path, sizeof(path), TEST_PREFIX "/sys/bus/", subsystem, "/devices/", sysname, NULL);
+        util_strscpyl(path, sizeof(path), "/sys/bus/", subsystem, "/devices/", sysname, NULL);
         if (stat(path, &statbuf) == 0)
                 goto found;
 
-        util_strscpyl(path, sizeof(path), TEST_PREFIX "/sys/class/", subsystem, "/", sysname, NULL);
+        util_strscpyl(path, sizeof(path), "/sys/class/", subsystem, "/", sysname, NULL);
         if (stat(path, &statbuf) == 0)
                 goto found;
 out:
@@ -892,7 +892,7 @@ static struct udev_device *device_new_from_parent(struct udev_device *udev_devic
         const char *subdir;
 
         util_strscpy(path, sizeof(path), udev_device->syspath);
-        subdir = path + strlen(TEST_PREFIX "/sys/");
+        subdir = path + strlen("/sys/");
         for (;;) {
                 char *pos;
 
@@ -1443,7 +1443,7 @@ int udev_device_set_syspath(struct udev_device *udev_device, const char *syspath
         udev_device->syspath = strdup(syspath);
         if (udev_device->syspath ==  NULL)
                 return -ENOMEM;
-        udev_device->devpath = udev_device->syspath + strlen(TEST_PREFIX "/sys");
+        udev_device->devpath = udev_device->syspath + strlen("/sys");
         udev_device_add_property(udev_device, "DEVPATH", udev_device->devpath);
 
         pos = strrchr(udev_device->syspath, '/');
@@ -1476,7 +1476,7 @@ int udev_device_set_devnode(struct udev_device *udev_device, const char *devnode
 {
         free(udev_device->devnode);
         if (devnode[0] != '/') {
-                if (asprintf(&udev_device->devnode, TEST_PREFIX "/dev/%s", devnode) < 0)
+                if (asprintf(&udev_device->devnode, "/dev/%s", devnode) < 0)
                         udev_device->devnode = NULL;
         } else {
                 udev_device->devnode = strdup(devnode);
index bc5842463687c2023ef83a180499661ca1a42f53..5990605445639b51891ca45e4877f0bbb4a894a7 100644 (file)
 #define READ_END  0
 #define WRITE_END 1
 
-#ifndef TEST_PREFIX
-#define TEST_PREFIX ""
-#endif
-
 /* avoid (sometimes expensive) calculations of parameters for debug output */
 #define udev_log_cond(udev, prio, arg...) \
   do { \
index 414eabc7b862e52996324277021b2eb732ef7135..89827c02cb359356e4edfc219bab107591850799 100644 (file)
@@ -26,6 +26,8 @@
 #include <unistd.h>
 #include <syslog.h>
 #include <grp.h>
+#include <sched.h>
+#include <sys/mount.h>
 #include <sys/signalfd.h>
 
 #include "udev.h"
@@ -34,6 +36,40 @@ void udev_main_log(struct udev *udev, int priority,
                    const char *file, int line, const char *fn,
                    const char *format, va_list args) {}
 
+static int fake_filesystems(void) {
+        static const struct fakefs {
+                const char *src;
+                const char *target;
+                const char *error;
+        } fakefss[] = {
+                { "test/sys", "/sys",                   "failed to mount test /sys" },
+                { "test/dev", "/dev",                   "failed to mount test /dev" },
+                { "test/run", "/run",                   "failed to mount test /run" },
+                { "test/run", "/etc/udev/rules.d",      "failed to mount empty /etc/udev/rules.d" },
+                { "test/run", "/usr/lib/udev/rules.d",  "failed to mount empty /usr/lib/udev/rules.d" },
+        };
+        unsigned int i;
+        int err;
+
+        err = unshare(CLONE_NEWNS);
+        if (err < 0) {
+                err = -errno;
+                fprintf(stderr, "failed to call unshare() %m\n");
+                return err;
+        }
+
+        for (i = 0; i < ELEMENTSOF(fakefss); i++) {
+                err = mount(fakefss[i].src, fakefss[i].target, NULL, MS_BIND, NULL);
+                if (err < 0) {
+                        err = -errno;
+                        fprintf(stderr, "%s %m", fakefss[i].error);
+                        return err;
+                }
+        }
+        return err;
+}
+
+
 int main(int argc, char *argv[])
 {
         struct udev *udev;
@@ -44,7 +80,11 @@ int main(int argc, char *argv[])
         const char *devpath;
         const char *action;
         sigset_t mask, sigmask_orig;
-        int err = -EINVAL;
+        int err;
+
+        err = fake_filesystems();
+        if (err < 0)
+                return EXIT_FAILURE;
 
         udev = udev_new();
         if (udev == NULL)
@@ -68,7 +108,7 @@ int main(int argc, char *argv[])
 
         rules = udev_rules_new(udev, 1);
 
-        util_strscpyl(syspath, sizeof(syspath), TEST_PREFIX "/sys", devpath, NULL);
+        util_strscpyl(syspath, sizeof(syspath), "/sys", devpath, NULL);
         dev = udev_device_new_from_syspath(udev, syspath);
         if (dev == NULL) {
                 log_debug("unknown device '%s'\n", devpath);
index d5dd1f3ba4cbc0a7d58676f6235a1796fffc12a7..2ade0ab81aa7a96e76da04bf85158004b4b86eff 100644 (file)
@@ -319,7 +319,7 @@ subst:
                                 break;
                         devnode = udev_device_get_devnode(dev_parent);
                         if (devnode != NULL)
-                                l = util_strpcpy(&s, l, devnode + strlen(TEST_PREFIX "/dev/"));
+                                l = util_strpcpy(&s, l, devnode + strlen("/dev/"));
                         break;
                 }
                 case SUBST_DEVNODE:
@@ -330,7 +330,7 @@ subst:
                         if (event->name != NULL)
                                 l = util_strpcpy(&s, l, event->name);
                         else if (udev_device_get_devnode(dev) != NULL)
-                                l = util_strpcpy(&s, l, udev_device_get_devnode(dev) + strlen(TEST_PREFIX "/dev/"));
+                                l = util_strpcpy(&s, l, udev_device_get_devnode(dev) + strlen("/dev/"));
                         else
                                 l = util_strpcpy(&s, l, udev_device_get_sysname(dev));
                         break;
@@ -340,16 +340,16 @@ subst:
                         list_entry = udev_device_get_devlinks_list_entry(dev);
                         if (list_entry == NULL)
                                 break;
-                        l = util_strpcpy(&s, l, udev_list_entry_get_name(list_entry) + strlen(TEST_PREFIX "/dev/"));
+                        l = util_strpcpy(&s, l, udev_list_entry_get_name(list_entry) + strlen("/dev/"));
                         udev_list_entry_foreach(list_entry, udev_list_entry_get_next(list_entry))
-                                l = util_strpcpyl(&s, l, " ", udev_list_entry_get_name(list_entry) + strlen(TEST_PREFIX "/dev/"), NULL);
+                                l = util_strpcpyl(&s, l, " ", udev_list_entry_get_name(list_entry) + strlen("/dev/"), NULL);
                         break;
                 }
                 case SUBST_ROOT:
-                        l = util_strpcpy(&s, l, TEST_PREFIX "/dev");
+                        l = util_strpcpy(&s, l, "/dev");
                         break;
                 case SUBST_SYS:
-                        l = util_strpcpy(&s, l, TEST_PREFIX "/sys");
+                        l = util_strpcpy(&s, l, "/sys");
                         break;
                 case SUBST_ENV:
                         if (attr == NULL) {
index 9add76547f1437dae86674c57c341375074217cd..738d02fa2525d50b040d3b8e6e5178e81b44f893 100644 (file)
@@ -190,8 +190,8 @@ static void link_update(struct udev_device *dev, const char *slink, bool add)
         const char *target;
         char buf[UTIL_PATH_SIZE];
 
-        util_path_encode(slink + strlen(TEST_PREFIX "/dev"), name_enc, sizeof(name_enc));
-        util_strscpyl(dirname, sizeof(dirname), TEST_PREFIX "/run/udev/links/", name_enc, NULL);
+        util_path_encode(slink + strlen("/dev"), name_enc, sizeof(name_enc));
+        util_strscpyl(dirname, sizeof(dirname), "/run/udev/links/", name_enc, NULL);
         util_strscpyl(filename, sizeof(filename), dirname, "/", udev_device_get_id_filename(dev), NULL);
 
         if (!add && unlink(filename) == 0)
@@ -315,7 +315,7 @@ void udev_node_add(struct udev_device *dev, mode_t mode, uid_t uid, gid_t gid)
                 return;
 
         /* always add /dev/{block,char}/$major:$minor */
-        snprintf(filename, sizeof(filename), TEST_PREFIX "/dev/%s/%u:%u",
+        snprintf(filename, sizeof(filename), "/dev/%s/%u:%u",
                  strcmp(udev_device_get_subsystem(dev), "block") == 0 ? "block" : "char",
                  major(udev_device_get_devnum(dev)), minor(udev_device_get_devnum(dev)));
         node_symlink(udev, udev_device_get_devnode(dev), filename);
@@ -340,7 +340,7 @@ void udev_node_remove(struct udev_device *dev)
                 link_update(dev, udev_list_entry_get_name(list_entry), 0);
 
         /* remove /dev/{block,char}/$major:$minor */
-        snprintf(filename, sizeof(filename), TEST_PREFIX "/dev/%s/%u:%u",
+        snprintf(filename, sizeof(filename), "/dev/%s/%u:%u",
                  strcmp(udev_device_get_subsystem(dev), "block") == 0 ? "block" : "char",
                  major(udev_device_get_devnum(dev)), minor(udev_device_get_devnum(dev)));
         unlink(filename);
index c571c828773f66a75a17c58ec991a46c2112e6c6..d3b33e4bbf960d597687cfa3a051a426d49fe410 100644 (file)
@@ -1757,9 +1757,9 @@ struct udev_rules *udev_rules_new(struct udev *udev, int resolve_names)
         memset(rules->trie_nodes, 0x00, sizeof(struct trie_node));
         rules->trie_nodes_cur = 1;
 
-        rules->dirs = strv_new(TEST_PREFIX SYSCONFDIR "/udev/rules.d",
-                               TEST_PREFIX "/run/udev/rules.d",
-                               TEST_PREFIX UDEVLIBEXECDIR "/rules.d",
+        rules->dirs = strv_new(SYSCONFDIR "/udev/rules.d",
+                               "/run/udev/rules.d",
+                               UDEVLIBEXECDIR "/rules.d",
                                NULL);
         if (!rules->dirs) {
                 log_error("failed to build config directory array");
@@ -2059,7 +2059,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event
                         udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(event->dev)) {
                                 const char *devlink;
 
-                                devlink =  udev_list_entry_get_name(list_entry) + strlen(TEST_PREFIX "/dev/");
+                                devlink =  udev_list_entry_get_name(list_entry) + strlen("/dev/");
                                 if (match_key(rules, cur, devlink) == 0) {
                                         match = true;
                                         break;
@@ -2533,7 +2533,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event
                                         log_debug("%i character(s) replaced\n", count);
                         }
                         if (major(udev_device_get_devnum(event->dev)) &&
-                            (!streq(name_str, udev_device_get_devnode(event->dev) + strlen(TEST_PREFIX "/dev/")))) {
+                            (!streq(name_str, udev_device_get_devnode(event->dev) + strlen("/dev/")))) {
                                 log_error("NAME=\"%s\" ignored, kernel device nodes "
                                     "can not be renamed; please fix it in %s:%u\n", name,
                                     &rules->buf[rule->rule.filename_off], rule->rule.filename_line);
@@ -2578,7 +2578,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event
                                 next[0] = '\0';
                                 log_debug("LINK '%s' %s:%u\n", pos,
                                           &rules->buf[rule->rule.filename_off], rule->rule.filename_line);
-                                util_strscpyl(filename, sizeof(filename), TEST_PREFIX "/dev/", pos, NULL);
+                                util_strscpyl(filename, sizeof(filename), "/dev/", pos, NULL);
                                 udev_device_add_devlink(event->dev, filename, cur->key.devlink_unique);
                                 while (isspace(next[1]))
                                         next++;
@@ -2588,7 +2588,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event
                         if (pos[0] != '\0') {
                                 log_debug("LINK '%s' %s:%u\n", pos,
                                           &rules->buf[rule->rule.filename_off], rule->rule.filename_line);
-                                util_strscpyl(filename, sizeof(filename), TEST_PREFIX "/dev/", pos, NULL);
+                                util_strscpyl(filename, sizeof(filename), "/dev/", pos, NULL);
                                 udev_device_add_devlink(event->dev, filename, cur->key.devlink_unique);
                         }
                         break;
@@ -2698,7 +2698,7 @@ void udev_rules_apply_static_dev_perms(struct udev_rules *rules)
                         /* we assure, that the permissions tokens are sorted before the static token */
                         if (mode == 0 && uid == 0 && gid == 0)
                                 goto next;
-                        util_strscpyl(filename, sizeof(filename), TEST_PREFIX "/dev/",
+                        util_strscpyl(filename, sizeof(filename), "/dev/",
                                       &rules->buf[cur->key.value_off], NULL);
                         if (stat(filename, &stats) != 0)
                                 goto next;
index d80b00c3748de69280588c1d59af5b2420d26496..e91dda11cff9a237f7b5e29da03a7b7b4d134d38 100755 (executable)
@@ -891,7 +891,7 @@ EOF
         {
                 desc            => "udev_root substitution",
                 devpath         => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
-                exp_name        => "start-test/dev-end",
+                exp_name        => "start-/dev-end",
                 rules           => <<EOF
 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="start-%r-end"
 EOF