diff options
author | Tom Gundersen <teg@jklm.no> | 2014-11-07 16:48:55 +0100 |
---|---|---|
committer | Tom Gundersen <teg@jklm.no> | 2014-12-11 13:54:18 +0100 |
commit | b5284aed71f86f845127fffad65bc7cab5a68247 (patch) | |
tree | 6c29c2c534eaefaad6d9489a601e3eac5eaba3cf | |
parent | b1addd68f4e7ca81dba82de31827bbe113d82d79 (diff) |
sd-device: add sd_device_get_parent
-rw-r--r-- | src/libsystemd/sd-device/sd-device.c | 59 | ||||
-rw-r--r-- | src/systemd/sd-device.h | 1 |
2 files changed, 60 insertions, 0 deletions
diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c index e944e34a3..acb699479 100644 --- a/src/libsystemd/sd-device/sd-device.c +++ b/src/libsystemd/sd-device/sd-device.c @@ -36,6 +36,8 @@ struct sd_device { RefCount n_ref; + sd_device *parent; + char *syspath; const char *devpath; char *sysname; @@ -47,6 +49,7 @@ struct sd_device { dev_t devnum; bool uevent_loaded; + bool parent_set; }; static int device_new(sd_device **ret) { @@ -75,6 +78,7 @@ _public_ sd_device *sd_device_ref(sd_device *device) { _public_ sd_device *sd_device_unref(sd_device *device) { if (device && REFCNT_DEC(device->n_ref) <= 0) { + sd_device_unref(device->parent); free(device->syspath); free(device->sysname); free(device->devtype); @@ -564,3 +568,58 @@ _public_ int sd_device_new_from_device_id(sd_device **ret, const char *id) { return -EINVAL; } } + +static int device_new_from_child(sd_device **ret, sd_device *child) { + _cleanup_free_ char *path = NULL; + const char *subdir, *syspath; + int r; + + assert(ret); + assert(child); + + r = sd_device_get_syspath(child, &syspath); + if (r < 0) + return r; + + path = strdup(syspath); + if (!path) + return -ENOMEM; + subdir = path + strlen("/sys"); + + for (;;) { + char *pos; + + pos = strrchr(subdir, '/'); + if (!pos || pos < subdir + 2) + break; + + *pos = '\0'; + + r = sd_device_new_from_syspath(ret, path); + if (r < 0) + continue; + + return 0; + } + + return -ENOENT; +} + +_public_ int sd_device_get_parent(sd_device *child, sd_device **ret) { + + assert_return(ret, -EINVAL); + assert_return(child, -EINVAL); + + if (child->parent_set) { + child->parent_set = true; + + (void)device_new_from_child(&child->parent, child); + } + + if (!child->parent) + return -ENOENT; + + *ret = child->parent; + + return 0; +} diff --git a/src/systemd/sd-device.h b/src/systemd/sd-device.h index 903e4e416..820660145 100644 --- a/src/systemd/sd-device.h +++ b/src/systemd/sd-device.h @@ -41,6 +41,7 @@ int sd_device_new_from_subsystem_sysname(sd_device **ret, const char *subsystem, int sd_device_new_from_device_id(sd_device **ret, const char *id); int sd_device_get_syspath(sd_device *device, const char **ret); +int sd_device_get_parent(sd_device *child, sd_device **ret); _SD_END_DECLARATIONS; |