summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Gundersen <teg@jklm.no>2014-11-07 16:48:55 +0100
committerTom Gundersen <teg@jklm.no>2014-12-11 13:54:18 +0100
commitb5284aed71f86f845127fffad65bc7cab5a68247 (patch)
tree6c29c2c534eaefaad6d9489a601e3eac5eaba3cf
parentb1addd68f4e7ca81dba82de31827bbe113d82d79 (diff)
sd-device: add sd_device_get_parent
-rw-r--r--src/libsystemd/sd-device/sd-device.c59
-rw-r--r--src/systemd/sd-device.h1
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;