mirror of
https://github.com/systemd/systemd
synced 2024-10-15 04:24:19 +00:00
Merge pull request #24285 from yuwata/sd-device-new-from-path
sd-device: make sd_device_new_from_path() support symlink outside of /sys
This commit is contained in:
commit
9d9bc6fc57
|
@ -145,15 +145,12 @@ int device_set_syspath(sd_device *device, const char *_syspath, bool verify) {
|
|||
assert(device);
|
||||
assert(_syspath);
|
||||
|
||||
/* must be a subdirectory of /sys */
|
||||
if (!path_startswith(_syspath, "/sys/"))
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"sd-device: Syspath '%s' is not a subdirectory of /sys",
|
||||
_syspath);
|
||||
|
||||
if (verify) {
|
||||
_cleanup_close_ int fd = -1;
|
||||
|
||||
/* The input path maybe a symlink located outside of /sys. Let's try to chase the symlink at first.
|
||||
* The primary usecase is that e.g. /proc/device-tree is a symlink to /sys/firmware/devicetree/base.
|
||||
* By chasing symlinks in the path at first, we can call sd_device_new_from_path() with such path. */
|
||||
r = chase_symlinks(_syspath, NULL, 0, &syspath, &fd);
|
||||
if (r == -ENOENT)
|
||||
/* the device does not exist (any more?) */
|
||||
|
@ -230,6 +227,12 @@ int device_set_syspath(sd_device *device, const char *_syspath, bool verify) {
|
|||
"sd-device: the syspath \"%s\" is outside of sysfs, refusing.", syspath);
|
||||
}
|
||||
} else {
|
||||
/* must be a subdirectory of /sys */
|
||||
if (!path_startswith(_syspath, "/sys/"))
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"sd-device: Syspath '%s' is not a subdirectory of /sys",
|
||||
_syspath);
|
||||
|
||||
syspath = strdup(_syspath);
|
||||
if (!syspath)
|
||||
return log_oom_debug();
|
||||
|
@ -250,13 +253,16 @@ int device_set_syspath(sd_device *device, const char *_syspath, bool verify) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
_public_ int sd_device_new_from_syspath(sd_device **ret, const char *syspath) {
|
||||
static int device_new_from_syspath(sd_device **ret, const char *syspath, bool strict) {
|
||||
_cleanup_(sd_device_unrefp) sd_device *device = NULL;
|
||||
int r;
|
||||
|
||||
assert_return(ret, -EINVAL);
|
||||
assert_return(syspath, -EINVAL);
|
||||
|
||||
if (strict && !path_startswith(syspath, "/sys/"))
|
||||
return -EINVAL;
|
||||
|
||||
r = device_new_aux(&device);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -269,6 +275,10 @@ _public_ int sd_device_new_from_syspath(sd_device **ret, const char *syspath) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
_public_ int sd_device_new_from_syspath(sd_device **ret, const char *syspath) {
|
||||
return device_new_from_syspath(ret, syspath, /* strict = */ true);
|
||||
}
|
||||
|
||||
static int device_new_from_mode_and_devnum(sd_device **ret, mode_t mode, dev_t devnum) {
|
||||
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
|
||||
_cleanup_free_ char *syspath = NULL;
|
||||
|
@ -516,7 +526,7 @@ _public_ int sd_device_new_from_path(sd_device **ret, const char *path) {
|
|||
if (path_startswith(path, "/dev"))
|
||||
return sd_device_new_from_devname(ret, path);
|
||||
|
||||
return sd_device_new_from_syspath(ret, path);
|
||||
return device_new_from_syspath(ret, path, /* strict = */ false);
|
||||
}
|
||||
|
||||
int device_set_devtype(sd_device *device, const char *devtype) {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "device-enumerator-private.h"
|
||||
#include "device-internal.h"
|
||||
|
@ -12,9 +13,11 @@
|
|||
#include "hashmap.h"
|
||||
#include "nulstr-util.h"
|
||||
#include "path-util.h"
|
||||
#include "rm-rf.h"
|
||||
#include "string-util.h"
|
||||
#include "tests.h"
|
||||
#include "time-util.h"
|
||||
#include "tmpfile-util.h"
|
||||
|
||||
static void test_sd_device_one(sd_device *d) {
|
||||
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
|
||||
|
@ -406,4 +409,50 @@ TEST(sd_device_new_from_nulstr) {
|
|||
}
|
||||
}
|
||||
|
||||
TEST(sd_device_new_from_path) {
|
||||
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
|
||||
_cleanup_(rm_rf_physical_and_freep) char *tmpdir = NULL;
|
||||
sd_device *dev;
|
||||
int r;
|
||||
|
||||
assert_se(mkdtemp_malloc("/tmp/test-sd-device.XXXXXXX", &tmpdir) >= 0);
|
||||
|
||||
assert_se(sd_device_enumerator_new(&e) >= 0);
|
||||
assert_se(sd_device_enumerator_allow_uninitialized(e) >= 0);
|
||||
assert_se(sd_device_enumerator_add_match_subsystem(e, "block", true) >= 0);
|
||||
assert_se(sd_device_enumerator_add_nomatch_sysname(e, "loop*") >= 0);
|
||||
assert_se(sd_device_enumerator_add_match_property(e, "DEVNAME", "*") >= 0);
|
||||
|
||||
FOREACH_DEVICE(e, dev) {
|
||||
_cleanup_(sd_device_unrefp) sd_device *d = NULL;
|
||||
const char *syspath, *devpath, *sysname, *s;
|
||||
_cleanup_free_ char *path = NULL;
|
||||
|
||||
assert_se(sd_device_get_sysname(dev, &sysname) >= 0);
|
||||
|
||||
log_debug("%s(%s)", __func__, sysname);
|
||||
|
||||
assert_se(sd_device_get_syspath(dev, &syspath) >= 0);
|
||||
assert_se(sd_device_new_from_path(&d, syspath) >= 0);
|
||||
assert_se(sd_device_get_syspath(d, &s) >= 0);
|
||||
assert_se(streq(s, syspath));
|
||||
d = sd_device_unref(d);
|
||||
|
||||
assert_se(sd_device_get_devname(dev, &devpath) >= 0);
|
||||
r = sd_device_new_from_path(&d, devpath);
|
||||
if (r >= 0) {
|
||||
assert_se(sd_device_get_syspath(d, &s) >= 0);
|
||||
assert_se(streq(s, syspath));
|
||||
d = sd_device_unref(d);
|
||||
} else
|
||||
assert_se(r == -ENODEV || ERRNO_IS_PRIVILEGE(r));
|
||||
|
||||
assert_se(path = path_join(tmpdir, sysname));
|
||||
assert_se(symlink(syspath, path) >= 0);
|
||||
assert_se(sd_device_new_from_path(&d, path) >= 0);
|
||||
assert_se(sd_device_get_syspath(d, &s) >= 0);
|
||||
assert_se(streq(s, syspath));
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN(LOG_INFO);
|
||||
|
|
|
@ -604,9 +604,8 @@ static int names_platform(sd_device *dev, NetNames *names, bool test) {
|
|||
}
|
||||
|
||||
static int dev_devicetree_onboard(sd_device *dev, NetNames *names) {
|
||||
const char *alias, *ofnode_path, *ofnode_syspath;
|
||||
_cleanup_free_ char *devicetree_syspath = NULL;
|
||||
_cleanup_(sd_device_unrefp) sd_device *aliases_dev = NULL, *ofnode_dev = NULL;
|
||||
_cleanup_(sd_device_unrefp) sd_device *aliases_dev = NULL, *ofnode_dev = NULL, *devicetree_dev = NULL;
|
||||
const char *alias, *ofnode_path, *ofnode_syspath, *devicetree_syspath;
|
||||
sd_device *parent;
|
||||
int r;
|
||||
|
||||
|
@ -626,7 +625,12 @@ static int dev_devicetree_onboard(sd_device *dev, NetNames *names) {
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = chase_symlinks("/proc/device-tree", NULL, 0, &devicetree_syspath, NULL);
|
||||
/* /proc/device-tree should be a symlink to /sys/firmware/devicetree/base. */
|
||||
r = sd_device_new_from_path(&devicetree_dev, "/proc/device-tree");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_device_get_syspath(devicetree_dev, &devicetree_syspath);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -644,7 +648,7 @@ static int dev_devicetree_onboard(sd_device *dev, NetNames *names) {
|
|||
ofnode_path--;
|
||||
assert(path_is_absolute(ofnode_path));
|
||||
|
||||
r = sd_device_new_from_syspath(&aliases_dev, strjoina(devicetree_syspath, "/aliases"));
|
||||
r = sd_device_new_child(&aliases_dev, devicetree_dev, "aliases");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
|
Loading…
Reference in a new issue