[PATCH] Testbeds for libudev/gudev clients

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello friends of udev,

I would like to make it vastly easier, and for some aspects possible
at all, to write automatic tests for libudev/gudev client software.
For example, upower's test suite builds a temporary mock sysfs tree:

  http://cgit.freedesktop.org/upower/tree/src/linux/integration-test

(line 106 ff.) so that we can test its logic with having various
combinations of empty or full batteries, UPSes, ACs, power supplies
that power the whole platform vs. only particular devices, and so on.
Often developers do not have that hardware, or it's not easy to set up
a situation to reproduce a bug (waiting a couple of hours for your
battery to drain, etc.), so it is much more convenient to reproduce
the sysfs attributes in a small test bed.

Another example is the test suite for Ubuntu's driver package
detection which implements the corresponding PackageKit API; it also
uses a "fake sys" module largely derived from upower's:

  https://github.com/tseliot/ubuntu-drivers-common/blob/master/tests/fakesysfs.py

There are several problems with these approaches:

 * Copy&paste code is obviously bad. It would be much better if the
   convenience API to set up a libudev/gudev test bed would be
   provided by libudev/gudev itself. Also, it should be in C and
   available through introspection, so that you can use it from a
   variety of languages; this means it should be in gudev.

   I am currently working on a first patch for this, and will post it
   for discussion here when I have something working.

 * upower's test suite is not working any more with current
   systemd/udev versions because the support for $SYSFS_PATH was
   removed.

   I have a patch attached to generalize this to use
   $UDEV_TEST_PREFIX, replacing the current compile-time TEST_PREFIX
   macro. This will also allow us in the future to create mock dev and
   run/rules.d files without having to change the environment variable
   and temporary directory structure again. Once that (or a variant of
   it) is in, I'll adapt upower's test suite to also set
   UDEV_TEST_PREFIX so that it works with both old and new libudev
   versions.

   With that patch you can now e. g. call

     UDEV_TEST_PREFIX=test ./udevadm info --export-db
     UDEV_TEST_PREFIX=test ./udevadm info --query=all --path=/devices/virtual/block/md0

   in the built systemd tree and it will DTRT. I tested with
   ./test-libudev, which also works fine.

 * You can currently only control the coldplug part. That's why
   upower's test suite starts the daemon again in each test case. But
   you cannot test the dynamic parts with that, such as updating the
   properties correctly when changing power sources. What's missing is
   to emulate corresponding uevents for the $UDEV_TEST_PREFIX tree.

   My initial idea about this was to make udev_monitor_send_device()
   public API and relax the uid/pid checks to allow non-root messages
   when the corresponding sysfs dir is writable for the calling user
   (or something like that). But as non-root users are not allowed to
   send NETLINK_KOBJECT_UEVENT messages, this is moot anyway as we do
   not want to require root privileges for tests, at least not in all
   cases.

   So my current idea about this to have gudev read events from a
   simple GIO socket in $UDEV_TEST_PREFIX/uevent instead from
   libudev_monitor_* if $UDEV_TEST_PREFIX is given, as in that case
   the real uevents won't coincide with the sysfs anyway. The "uevent"
   signal would then be raised on messages from that socket. Do you
   think that's too crazy?

Thanks,

Martin
-- 
Martin Pitt                        | http://www.piware.de
Ubuntu Developer (www.ubuntu.com)  | Debian Developer  (www.debian.org)
From eebd02e708cc73e08f6ff13b49ac4f99716c6777 Mon Sep 17 00:00:00 2001
From: Martin Pitt <martinpitt@xxxxxxxxx>
Date: Thu, 5 Jul 2012 13:34:23 +0200
Subject: [PATCH] udev: Replace compile-time TEST_PREFIX with runtime $UDEV_TEST_PREFIX

The removal of $SYSFS_PATH and configurable paths made it impossible for test
suites to set up a local sysfs tree and point libudev to that. Restore and
generalize the functionality with checking the $UDEV_TEST_PREFIX environment
variable which replaces the compile-time TEST_PREFIX macro.

Also adjust udevadm to respect the test prefix.
---
 Makefile.am                          |    7 +++--
 src/libudev/libudev-device-private.c |   11 +++++---
 src/libudev/libudev-device.c         |   50 ++++++++++++++++++++--------------
 src/libudev/libudev-enumerate.c      |   19 +++++++++----
 src/libudev/libudev-private.h        |    4 ---
 src/libudev/libudev.c                |   23 ++++++++++++++++
 src/libudev/libudev.h                |    1 +
 src/test/test-udev.c                 |    2 +-
 src/udev/udev-event.c                |   14 ++++++----
 src/udev/udev-node.c                 |   11 +++++---
 src/udev/udev-rules.c                |   26 ++++++++++++------
 src/udev/udevadm-info.c              |   17 +++++++++---
 12 files changed, 125 insertions(+), 60 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 3b7ec0b..6d941a0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1630,6 +1630,10 @@ TESTS += \
 	test/udev-test.pl \
 	test/rules-test.sh
 
+# The test-udev program should run with relative path names for /sys, /dev,
+# /run prefixed, pointing to our test/ directory.
+TESTS_ENVIRONMENT = UDEV_TEST_PREFIX=test
+
 noinst_PROGRAMS += \
 	test-libudev \
 	test-udev
@@ -1647,10 +1651,7 @@ test_udev_SOURCES = \
 	$(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)
 
diff --git a/src/libudev/libudev-device-private.c b/src/libudev/libudev-device-private.c
index 2347736..f6cbb46 100644
--- a/src/libudev/libudev-device-private.c
+++ b/src/libudev/libudev-device-private.c
@@ -30,7 +30,8 @@ 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), udev_get_test_prefix(udev_device_get_udev(dev)),
+                      "/run/udev/tags/", tag, "/", id, NULL);
 
         if (add) {
                 int fd;
@@ -107,7 +108,8 @@ 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), udev_get_test_prefix(udev_device_get_udev(udev_device)),
+                      "/run/udev/data/", id, NULL);
 
         /* do not store anything for otherwise empty devices */
         if (!has_info &&
@@ -138,7 +140,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(udev_get_test_prefix(udev)) + 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 +177,8 @@ 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), udev_get_test_prefix(udev_device_get_udev(udev_device)),
+                      "/run/udev/data/", id, NULL);
         unlink(filename);
         return 0;
 }
diff --git a/src/libudev/libudev-device.c b/src/libudev/libudev-device.c
index a8277d1..665619a 100644
--- a/src/libudev/libudev-device.c
+++ b/src/libudev/libudev-device.c
@@ -360,7 +360,8 @@ 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), udev_get_test_prefix(udev_device_get_udev(udev_device)),
+                              "/sys", &property[8], NULL);
                 udev_device_set_syspath(udev_device, path);
         } else if (startswith(property, "SUBSYSTEM=")) {
                 udev_device_set_subsystem(udev_device, &property[10]);
@@ -467,6 +468,9 @@ int udev_device_read_db(struct udev_device *udev_device, const char *dbfile)
         char filename[UTIL_PATH_SIZE];
         char line[UTIL_LINE_SIZE];
         FILE *f;
+        const char *prefix;
+
+        prefix = udev_get_test_prefix(udev_device_get_udev(udev_device));
 
         /* providing a database file will always force-load it */
         if (dbfile == NULL) {
@@ -479,7 +483,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), prefix, "/run/udev/data/", id, NULL);
                 dbfile = filename;
         }
 
@@ -502,7 +506,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), prefix, "/dev/", val, NULL);
                         udev_device_add_devlink(udev_device, filename, 0);
                         break;
                 case 'L':
@@ -635,6 +639,11 @@ _public_ struct udev_device *udev_device_new_from_syspath(struct udev *udev, con
         char *pos;
         struct stat statbuf;
         struct udev_device *udev_device;
+        const char *prefix;
+        int prefix_sys_len;
+
+        prefix = udev_get_test_prefix(udev);
+        prefix_sys_len = strlen(prefix) + strlen("/sys");
 
         if (udev == NULL)
                 return NULL;
@@ -642,13 +651,14 @@ _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, udev_get_test_prefix(udev)) ||
+            !startswith(syspath + strlen(udev_get_test_prefix(udev)), "/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 + prefix_sys_len;
         pos = strrchr(subdir, '/');
         if (pos == NULL || pos[1] == '\0' || pos < &subdir[2])
                 return NULL;
@@ -657,7 +667,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 + prefix_sys_len, "/devices/")) {
                 char file[UTIL_PATH_SIZE];
 
                 /* all "devices" require a "uevent" file */
@@ -709,8 +719,8 @@ _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",
-                 type_str, major(devnum), minor(devnum));
+        snprintf(path, sizeof(path), "%s/sys/dev/%s/%u:%u",
+                 udev_get_test_prefix(udev), type_str, major(devnum), minor(devnum));
         return udev_device_new_from_syspath(udev, path);
 }
 
@@ -790,22 +800,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), udev_get_test_prefix(udev), "/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), udev_get_test_prefix(udev), "/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), udev_get_test_prefix(udev), "/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), udev_get_test_prefix(udev), "/sys/module/", sysname, NULL);
                 if (stat(path, &statbuf) == 0)
                         goto found;
                 goto out;
@@ -821,26 +831,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), udev_get_test_prefix(udev), "/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), udev_get_test_prefix(udev), "/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), udev_get_test_prefix(udev), "/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), udev_get_test_prefix(udev), "/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), udev_get_test_prefix(udev), "/sys/class/", subsystem, "/", sysname, NULL);
         if (stat(path, &statbuf) == 0)
                 goto found;
 out:
@@ -892,7 +902,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(udev_get_test_prefix(udev_device_get_udev(udev_device))) + strlen("/sys/");
         for (;;) {
                 char *pos;
 
@@ -1443,7 +1453,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(udev_get_test_prefix(udev_device_get_udev(udev_device))) + strlen("/sys");
         udev_device_add_property(udev_device, "DEVPATH", udev_device->devpath);
 
         pos = strrchr(udev_device->syspath, '/');
@@ -1476,7 +1486,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, "%s/dev/%s", udev_get_test_prefix(udev_device_get_udev(udev_device)), devnode) < 0)
                         udev_device->devnode = NULL;
         } else {
                 udev_device->devnode = strdup(devnode);
diff --git a/src/libudev/libudev-enumerate.c b/src/libudev/libudev-enumerate.c
index a945758..1fb9208 100644
--- a/src/libudev/libudev-enumerate.c
+++ b/src/libudev/libudev-enumerate.c
@@ -214,7 +214,7 @@ static bool devices_delay_end(struct udev *udev, const char *syspath)
         int i;
 
         for (i = 0; delay_device_list[i] != NULL; i++) {
-                if (strstr(syspath + strlen("/sys"), delay_device_list[i]) != NULL)
+                if (strstr(syspath + strlen(udev_get_test_prefix(udev)) + strlen("/sys"), delay_device_list[i]) != NULL)
                         return true;
         }
         return false;
@@ -649,7 +649,8 @@ static int scan_dir_and_add_devices(struct udev_enumerate *udev_enumerate,
         struct dirent *dent;
 
         s = path;
-        l = util_strpcpyl(&s, sizeof(path), "/sys/", basedir, NULL);
+        l = util_strpcpyl(&s, sizeof(path), udev_get_test_prefix(udev_enumerate_get_udev(udev_enumerate)),
+                          "/sys/", basedir, NULL);
         if (subdir1 != NULL)
                 l = util_strpcpyl(&s, l, "/", subdir1, NULL);
         if (subdir2 != NULL)
@@ -728,7 +729,8 @@ static int scan_dir(struct udev_enumerate *udev_enumerate, const char *basedir,
         DIR *dir;
         struct dirent *dent;
 
-        util_strscpyl(path, sizeof(path), "/sys/", basedir, NULL);
+        util_strscpyl(path, sizeof(path), udev_get_test_prefix(udev_enumerate_get_udev(udev_enumerate)),
+                      "/sys/", basedir, NULL);
         dir = opendir(path);
         if (dir == NULL)
                 return -1;
@@ -875,8 +877,12 @@ static int scan_devices_children(struct udev_enumerate *enumerate)
 static int scan_devices_all(struct udev_enumerate *udev_enumerate)
 {
         struct stat statbuf;
+        char path[UTIL_PATH_SIZE];
+
+        util_strscpyl(path, sizeof(path), udev_get_test_prefix(udev_enumerate_get_udev(udev_enumerate)),
+                      "/sys/subsystem", NULL);
 
-        if (stat("/sys/subsystem", &statbuf) == 0) {
+        if (stat(path, &statbuf) == 0) {
                 /* we have /subsystem/, forget all the old stuff */
                 scan_dir(udev_enumerate, "subsystem", "devices", NULL);
         } else {
@@ -924,6 +930,7 @@ _public_ int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerat
 {
         struct stat statbuf;
         const char *subsysdir;
+        char path[UTIL_PATH_SIZE];
 
         if (udev_enumerate == NULL)
                 return -EINVAL;
@@ -932,7 +939,9 @@ _public_ int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerat
         if (match_subsystem(udev_enumerate, "module"))
                 scan_dir_and_add_devices(udev_enumerate, "module", NULL, NULL);
 
-        if (stat("/sys/subsystem", &statbuf) == 0)
+        util_strscpyl(path, sizeof(path), udev_get_test_prefix(udev_enumerate_get_udev(udev_enumerate)),
+                      "/sys/subsystem", NULL);
+        if (stat(path, &statbuf) == 0)
                 subsysdir = "subsystem";
         else
                 subsysdir = "bus";
diff --git a/src/libudev/libudev-private.h b/src/libudev/libudev-private.h
index 4eb4a59..af3338f 100644
--- a/src/libudev/libudev-private.h
+++ b/src/libudev/libudev-private.h
@@ -25,10 +25,6 @@
 #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 { \
diff --git a/src/libudev/libudev.c b/src/libudev/libudev.c
index 07a24d5..7be9c89 100644
--- a/src/libudev/libudev.c
+++ b/src/libudev/libudev.c
@@ -43,6 +43,7 @@ struct udev {
         void *userdata;
         struct udev_list properties_list;
         int log_priority;
+        char *test_prefix;
 };
 
 void udev_log(struct udev *udev,
@@ -95,6 +96,23 @@ _public_ void udev_set_userdata(struct udev *udev, void *userdata)
 }
 
 /**
+ * udev_get_test_prefix:
+ * @udev: udev library context
+ *
+ * Retrieve the file system root prefix for accessing /sys, /dev, etc. The
+ * default is empty, meaning the normal file system root. For testing purposes,
+ * it can be overridden with the environment variable $UDEV_TEST_PREFIX.
+ *
+ * Returns: the test prefix
+ **/
+_public_ const char *udev_get_test_prefix(struct udev *udev)
+{
+        if (udev == NULL)
+                return NULL;
+        return udev->test_prefix;
+}
+
+/**
  * udev_new:
  *
  * Create udev library context. This reads the udev configuration
@@ -190,6 +208,10 @@ _public_ struct udev *udev_new(void)
                 fclose(f);
         }
 
+        /* test prefix in environment? */
+        env = getenv("UDEV_TEST_PREFIX");
+        udev->test_prefix = strdup(env ? env : "");
+
         /* environment overrides config */
         env = getenv("UDEV_LOG");
         if (env != NULL)
@@ -231,6 +253,7 @@ _public_ struct udev *udev_unref(struct udev *udev)
         if (udev->refcount > 0)
                 return udev;
         udev_list_cleanup(&udev->properties_list);
+        free(udev->test_prefix);
         free(udev);
         return NULL;
 }
diff --git a/src/libudev/libudev.h b/src/libudev/libudev.h
index 8643984..5dd3f98 100644
--- a/src/libudev/libudev.h
+++ b/src/libudev/libudev.h
@@ -38,6 +38,7 @@ int udev_get_log_priority(struct udev *udev);
 void udev_set_log_priority(struct udev *udev, int priority);
 void *udev_get_userdata(struct udev *udev);
 void udev_set_userdata(struct udev *udev, void *userdata);
+const char *udev_get_test_prefix(struct udev *udev);
 
 /*
  * udev_list
diff --git a/src/test/test-udev.c b/src/test/test-udev.c
index 414eabc..46e8ce6 100644
--- a/src/test/test-udev.c
+++ b/src/test/test-udev.c
@@ -68,7 +68,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), udev_get_test_prefix(udev) , "/sys", devpath, NULL);
         dev = udev_device_new_from_syspath(udev, syspath);
         if (dev == NULL) {
                 log_debug("unknown device '%s'\n", devpath);
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index e6f405b..228b16c 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -112,6 +112,8 @@ size_t udev_event_apply_format(struct udev_event *event, const char *src, char *
         const char *from;
         char *s;
         size_t l;
+        const char *prefix = udev_get_test_prefix(udev_device_get_udev(dev));
+        const int devpath_len = strlen(prefix) + strlen("/dev/");
 
         from = src;
         s = dest;
@@ -319,7 +321,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 + devpath_len);
                         break;
                 }
                 case SUBST_DEVNODE:
@@ -330,7 +332,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) + devpath_len);
                         else
                                 l = util_strpcpy(&s, l, udev_device_get_sysname(dev));
                         break;
@@ -340,16 +342,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) + devpath_len);
                         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) + devpath_len, NULL);
                         break;
                 }
                 case SUBST_ROOT:
-                        l = util_strpcpy(&s, l, TEST_PREFIX "/dev");
+                        l = util_strpcpyl(&s, l, prefix, "/dev", NULL);
                         break;
                 case SUBST_SYS:
-                        l = util_strpcpy(&s, l, TEST_PREFIX "/sys");
+                        l = util_strpcpyl(&s, l, prefix, "/sys", NULL);
                         break;
                 case SUBST_ENV:
                         if (attr == NULL) {
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
index 1bef521..18a75c3 100644
--- a/src/udev/udev-node.c
+++ b/src/udev/udev-node.c
@@ -202,9 +202,10 @@ static void link_update(struct udev_device *dev, const char *slink, bool add)
         char dirname[UTIL_PATH_SIZE];
         const char *target;
         char buf[UTIL_PATH_SIZE];
+        const char *prefix = udev_get_test_prefix(udev_device_get_udev(dev));
 
-        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(prefix) + strlen("/dev"), name_enc, sizeof(name_enc));
+        util_strscpyl(dirname, sizeof(dirname), prefix, "/run/udev/links/", name_enc, NULL);
         util_strscpyl(filename, sizeof(filename), dirname, "/", udev_device_get_id_filename(dev), NULL);
 
         if (!add && unlink(filename) == 0)
@@ -328,7 +329,8 @@ 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), "%s/dev/%s/%u:%u",
+                 udev_get_test_prefix(udev),
                  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);
@@ -353,7 +355,8 @@ 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), "%s/dev/%s/%u:%u",
+                 udev_get_test_prefix(udev_device_get_udev(dev)),
                  strcmp(udev_device_get_subsystem(dev), "block") == 0 ? "block" : "char",
                  major(udev_device_get_devnum(dev)), minor(udev_device_get_devnum(dev)));
         unlink(filename);
diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c
index b5b54dd..d098ced 100644
--- a/src/udev/udev-rules.c
+++ b/src/udev/udev-rules.c
@@ -1718,6 +1718,9 @@ struct udev_rules *udev_rules_new(struct udev *udev, int resolve_names)
         struct token end_token;
         char **files, **f;
         int r;
+        char sysconf_path[UTIL_PATH_SIZE];
+        char run_path[UTIL_PATH_SIZE];
+        char libexec_path[UTIL_PATH_SIZE];
 
         rules = calloc(1, sizeof(struct udev_rules));
         if (rules == NULL)
@@ -1757,10 +1760,14 @@ 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",
-                               NULL);
+        util_strscpyl(sysconf_path, sizeof(sysconf_path), udev_get_test_prefix(udev),
+                      SYSCONFDIR "/udev/rules.d", NULL);
+        util_strscpyl(run_path, sizeof(run_path), udev_get_test_prefix(udev),
+                      "/run/udev/rules.d", NULL);
+        util_strscpyl(libexec_path, sizeof(libexec_path), udev_get_test_prefix(udev),
+                      UDEVLIBEXECDIR "/rules.d", NULL);
+        rules->dirs = strv_new(sysconf_path, run_path, libexec_path, NULL);
+
         if (!rules->dirs) {
                 log_error("failed to build config directory array");
                 return NULL;
@@ -2018,6 +2025,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event
         struct token *rule;
         enum escape_type esc = ESCAPE_UNSET;
         bool can_set_name;
+        const char *prefix = udev_get_test_prefix (event->udev);
 
         if (rules->tokens == NULL)
                 return -1;
@@ -2059,7 +2067,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(prefix) + strlen("/dev/");
                                 if (match_key(rules, cur, devlink) == 0) {
                                         match = true;
                                         break;
@@ -2533,7 +2541,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(prefix) + 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 +2586,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), prefix, "/dev/", pos, NULL);
                                 udev_device_add_devlink(event->dev, filename, cur->key.devlink_unique);
                                 while (isspace(next[1]))
                                         next++;
@@ -2588,7 +2596,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), prefix, "/dev/", pos, NULL);
                                 udev_device_add_devlink(event->dev, filename, cur->key.devlink_unique);
                         }
                         break;
@@ -2698,7 +2706,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), udev_get_test_prefix(rules->udev), "/dev/",
                                       &rules->buf[cur->key.value_off], NULL);
                         if (stat(filename, &stats) != 0)
                                 goto next;
diff --git a/src/udev/udevadm-info.c b/src/udev/udevadm-info.c
index 907e961..81a9ce7 100644
--- a/src/udev/udevadm-info.c
+++ b/src/udev/udevadm-info.c
@@ -267,13 +267,22 @@ static void cleanup_db(struct udev *udev)
 static struct udev_device *find_device(struct udev *udev, const char *id, const char *prefix)
 {
         char name[UTIL_PATH_SIZE];
+        char fullprefix[UTIL_PATH_SIZE];
+        char devdir[UTIL_PATH_SIZE];
+        char sysdir[UTIL_PATH_SIZE];
 
-        if (prefix && !startswith(id, prefix)) {
-                util_strscpyl(name, sizeof(name), prefix, id, NULL);
+        if (prefix)
+                util_strscpyl(fullprefix, sizeof(fullprefix), udev_get_test_prefix(udev), prefix, NULL);
+
+        if (prefix && !startswith(id, fullprefix)) {
+                util_strscpyl(name, sizeof(name), fullprefix, id, NULL);
                 id = name;
         }
 
-        if (startswith(id, "/dev/")) {
+        util_strscpyl(devdir, sizeof(devdir), udev_get_test_prefix(udev), "/dev/", NULL);
+        util_strscpyl(sysdir, sizeof(sysdir), udev_get_test_prefix(udev), "/sys/", NULL);
+
+        if (startswith(id, devdir)) {
                 struct stat statbuf;
                 char type;
 
@@ -288,7 +297,7 @@ static struct udev_device *find_device(struct udev *udev, const char *id, const
                         return NULL;
 
                 return udev_device_new_from_devnum(udev, type, statbuf.st_rdev);
-        } else if (startswith(id, "/sys/"))
+        } else if (startswith(id, sysdir))
                 return udev_device_new_from_syspath(udev, id);
         else
                 return NULL;
-- 
1.7.10.4

Attachment: signature.asc
Description: Digital signature


[Index of Archives]     [Linux Kernel]     [Linux DVB]     [Asterisk Internet PBX]     [DCCP]     [Netdev]     [X.org]     [Util Linux NG]     [Fedora Women]     [ALSA Devel]     [Linux USB]

  Powered by Linux