sd-device: replace '!' with '/' before calling sd_device_new_from_subsystem_sysname()
Device ID uses device directory name as is, hence may contain '!', but
sd_device_new_from_subsystem_sysname() expects that the input is sysname.
So, we need to replace '!' with '/'.
Follow-up for 1393c5a2a4.
Fixes #37711.
This commit is contained in:
@@ -922,15 +922,24 @@ _public_ int sd_device_new_from_device_id(sd_device **ret, const char *id) {
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
return sd_device_new_from_subsystem_sysname(ret, subsys, sep + 1);
|
||||
_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, subsystem, sysname);
|
||||
}
|
||||
|
||||
default:
|
||||
|
||||
@@ -10,10 +10,14 @@
|
||||
#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 "set.h"
|
||||
#include "stat-util.h"
|
||||
@@ -22,6 +26,62 @@
|
||||
#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;
|
||||
|
||||
Reference in New Issue
Block a user