}
case '+': {
- const char *subsys, *sep;
-
- sep = strchr(id + 1, ':');
- if (!sep || sep - id - 1 > NAME_MAX)
+ const char *sep = strchr(id + 1, ':');
+ if (!sep || sep[1] == '\0')
return -EINVAL;
- subsys = memdupa_suffix0(id + 1, sep - id - 1);
+ _cleanup_free_ char *subsystem = strndup(id + 1, sep - id - 1);
+ if (!subsystem)
+ return -ENOMEM;
+
+ _cleanup_free_ char *sysname = strdup(sep + 1);
+ if (!sysname)
+ return -ENOMEM;
+
+ /* Device ID uses device directory name as is, hence may contain '!', but
+ * sd_device_new_from_subsystem_sysname() expects that the input is sysname,
+ * that is, '!' must be replaced with '/'. */
+ string_replace_char(sysname, '!', '/');
- return sd_device_new_from_subsystem_sysname(ret, subsys, sep + 1);
+ return sd_device_new_from_subsystem_sysname(ret, subsystem, sysname);
}
default:
#include "device-util.h"
#include "errno-util.h"
#include "fd-util.h"
+#include "fs-util.h"
#include "hashmap.h"
+#include "mkdir.h"
+#include "mount-util.h"
#include "mountpoint-util.h"
#include "nulstr-util.h"
#include "path-util.h"
+#include "process-util.h"
#include "rm-rf.h"
#include "stat-util.h"
#include "string-util.h"
#include "tmpfile-util.h"
#include "udev-util.h"
+TEST(mdio_bus) {
+ int r;
+
+ /* For issue #37711 */
+
+ if (getuid() != 0)
+ return (void) log_tests_skipped("not running as root");
+
+ ASSERT_OK(r = safe_fork("(mdio_bus)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_WAIT|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, NULL));
+ if (r == 0) {
+ const char *syspath = "/sys/bus/mdio_bus/drivers/Qualcomm Atheros AR8031!AR8033";
+ const char *id = "+drivers:mdio_bus:Qualcomm Atheros AR8031!AR8033";
+
+ struct {
+ int (*getter)(sd_device*, const char**);
+ const char *val;
+ } table[] = {
+ { sd_device_get_syspath, syspath },
+ { sd_device_get_device_id, id },
+ { sd_device_get_subsystem, "drivers" },
+ { sd_device_get_driver_subsystem, "mdio_bus" },
+ { sd_device_get_sysname, "Qualcomm Atheros AR8031/AR8033" },
+ };
+
+ ASSERT_OK_ERRNO(setenv("SYSTEMD_DEVICE_VERIFY_SYSFS", "0", /* overwrite = */ false));
+ ASSERT_OK(mount_nofollow_verbose(LOG_ERR, "tmpfs", "/sys/bus/", "tmpfs", 0, NULL));
+ ASSERT_OK(mkdir_p(syspath, 0755));
+
+ _cleanup_free_ char *uevent = path_join(syspath, "uevent");
+ ASSERT_NOT_NULL(uevent);
+ ASSERT_OK(touch(uevent));
+
+ _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
+ ASSERT_OK(sd_device_new_from_syspath(&dev, syspath));
+
+ FOREACH_ELEMENT(t, table) {
+ const char *v;
+
+ ASSERT_OK(t->getter(dev, &v));
+ ASSERT_STREQ(v, t->val);
+ }
+
+ dev = sd_device_unref(dev);
+ ASSERT_OK(sd_device_new_from_device_id(&dev, id));
+
+ FOREACH_ELEMENT(t, table) {
+ const char *v;
+
+ ASSERT_OK(t->getter(dev, &v));
+ ASSERT_STREQ(v, t->val);
+ }
+
+ _exit(EXIT_SUCCESS);
+ }
+}
+
static void test_sd_device_one(sd_device *d) {
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
const char *syspath, *sysname, *subsystem = NULL, *devname, *val;