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