summaryrefslogtreecommitdiff
path: root/src/device.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2010-07-21 05:00:29 +0200
committerLennart Poettering <lennart@poettering.net>2010-07-21 05:00:29 +0200
commita7f241db3f1ae96ab2708092e1b31d2feb989947 (patch)
treed48588845b8d22658eb7a46bee49d58ec528716d /src/device.c
parent672c48cc065251ddbdc3926221e8a7718241cccd (diff)
unit: deduce following unit value dynamically instead of statically, to avoid dangling pointers
Diffstat (limited to 'src/device.c')
-rw-r--r--src/device.c60
1 files changed, 41 insertions, 19 deletions
diff --git a/src/device.c b/src/device.c
index 526e714378..46b3ed3dff 100644
--- a/src/device.c
+++ b/src/device.c
@@ -40,22 +40,21 @@ static void device_unset_sysfs(Device *d) {
assert(d);
- if (d->sysfs) {
- /* Remove this unit from the chain of devices which share the
- * same sysfs path. */
- first = hashmap_get(d->meta.manager->devices_by_sysfs, d->sysfs);
- LIST_REMOVE(Device, same_sysfs, first, d);
-
- if (first)
- hashmap_remove_and_replace(d->meta.manager->devices_by_sysfs, d->sysfs, first->sysfs, first);
- else
- hashmap_remove(d->meta.manager->devices_by_sysfs, d->sysfs);
-
- free(d->sysfs);
- d->sysfs = NULL;
- }
+ if (!d->sysfs)
+ return;
+
+ /* Remove this unit from the chain of devices which share the
+ * same sysfs path. */
+ first = hashmap_get(d->meta.manager->devices_by_sysfs, d->sysfs);
+ LIST_REMOVE(Device, same_sysfs, first, d);
- d->meta.following = NULL;
+ if (first)
+ hashmap_remove_and_replace(d->meta.manager->devices_by_sysfs, d->sysfs, first->sysfs, first);
+ else
+ hashmap_remove(d->meta.manager->devices_by_sysfs, d->sysfs);
+
+ free(d->sysfs);
+ d->sysfs = NULL;
}
static void device_init(Unit *u) {
@@ -268,10 +267,7 @@ static int device_update_unit(Manager *m, struct udev_device *dev, const char *p
goto fail;
}
}
-
- u->meta.following = NULL;
- } else
- device_find_escape_name(m, sysfs, &u->meta.following);
+ }
unit_add_to_dbus_queue(u);
return 0;
@@ -365,6 +361,30 @@ static int device_process_removed_device(Manager *m, struct udev_device *dev) {
return 0;
}
+static Unit *device_following(Unit *u) {
+ Device *d = DEVICE(u);
+ Device *other, *first = NULL;
+
+ assert(d);
+
+ if (startswith(u->meta.id, "sys-"))
+ return NULL;
+
+ /* Make everybody follow the unit that's named after the sysfs path */
+ for (other = d->same_sysfs_next; other; other = other->same_sysfs_next)
+ if (startswith(other->meta.id, "sys-"))
+ return UNIT(other);
+
+ for (other = d->same_sysfs_prev; other; other = other->same_sysfs_prev) {
+ if (startswith(other->meta.id, "sys-"))
+ return UNIT(other);
+
+ first = other;
+ }
+
+ return UNIT(first);
+}
+
static void device_shutdown(Manager *m) {
assert(m);
@@ -512,6 +532,8 @@ const UnitVTable device_vtable = {
.bus_message_handler = bus_device_message_handler,
+ .following = device_following,
+
.enumerate = device_enumerate,
.shutdown = device_shutdown
};