summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/logind-dbus.c141
-rw-r--r--src/logind-device.c1
-rw-r--r--src/logind.h1
-rw-r--r--src/org.freedesktop.login1.policy10
4 files changed, 118 insertions, 35 deletions
diff --git a/src/logind-dbus.c b/src/logind-dbus.c
index 93525980b7..96216e43a3 100644
--- a/src/logind-dbus.c
+++ b/src/logind-dbus.c
@@ -94,6 +94,9 @@
" <arg name=\"sysfs\" type=\"s\" direction=\"in\"/>\n" \
" <arg name=\"interactive\" type=\"b\" direction=\"in\"/>\n" \
" </method>\n" \
+ " <method name=\"FlushDevices\">\n" \
+ " <arg name=\"interactive\" type=\"b\" direction=\"in\"/>\n" \
+ " </method>\n" \
" <signal name=\"SessionNew\">\n" \
" <arg name=\"id\" type=\"s\"/>\n" \
" <arg name=\"path\" type=\"o\"/>\n" \
@@ -548,13 +551,58 @@ static bool device_has_tag(struct udev_device *d, const char *tag) {
return false;
}
+static int trigger_device(Manager *m, const char *prefix) {
+ struct udev_enumerate *e;
+ struct udev_list_entry *first, *item;
+ int r;
+
+ assert(m);
+
+ e = udev_enumerate_new(m->udev);
+ if (!e) {
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ if (udev_enumerate_scan_devices(e) < 0) {
+ r = -EIO;
+ goto finish;
+ }
+
+ first = udev_enumerate_get_list_entry(e);
+ udev_list_entry_foreach(item, first) {
+ char *t;
+ const char *p;
+
+ p = udev_list_entry_get_name(item);
+
+ if (prefix && !path_startswith(p, prefix))
+ continue;
+
+ t = strappend(p, "/uevent");
+ if (!t) {
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ write_one_line_file(t, "change");
+ free(t);
+ }
+
+ r = 0;
+
+finish:
+ if (e)
+ udev_enumerate_unref(e);
+
+ return r;
+}
+
static int attach_device(Manager *m, const char *seat, const char *sysfs) {
struct udev_device *d;
char *rule = NULL, *file = NULL;
const char *id_for_seat;
int r;
- struct udev_enumerate *e;
- struct udev_list_entry *first, *item;
assert(m);
assert(seat);
@@ -590,35 +638,7 @@ static int attach_device(Manager *m, const char *seat, const char *sysfs) {
if (r < 0)
goto finish;
- e = udev_enumerate_new(m->udev);
- if (!e) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (udev_enumerate_scan_devices(e) < 0) {
- r = -EIO;
- goto finish;
- }
-
- first = udev_enumerate_get_list_entry(e);
- udev_list_entry_foreach(item, first) {
- char *t;
- const char *p;
-
- p = udev_list_entry_get_name(item);
- if (!path_startswith(p, sysfs))
- continue;
-
- t = strappend(p, "/uevent");
- if (!t) {
- r = -ENOMEM;
- goto finish;
- }
-
- write_one_line_file(t, "change");
- free(t);
- }
+ r = trigger_device(m, sysfs);
finish:
free(rule);
@@ -627,12 +647,42 @@ finish:
if (d)
udev_device_unref(d);
- if (e)
- udev_enumerate_unref(e);
-
return r;
}
+static int flush_devices(Manager *m) {
+ DIR *d;
+
+ assert(m);
+
+ d = opendir("/etc/udev/rules.d");
+ if (!d) {
+ if (errno != ENOENT)
+ log_warning("Failed to open /etc/udev/rules.d: %m");
+ } else {
+ struct dirent *de;
+
+ while ((de = readdir(d))) {
+
+ if (!dirent_is_file(de))
+ continue;
+
+ if (!startswith(de->d_name, "72-seat-"))
+ continue;
+
+ if (!endswith(de->d_name, ".rules"))
+ continue;
+
+ if (unlinkat(dirfd(d), de->d_name, 0) < 0)
+ log_warning("Failed to unlink %s: %m", de->d_name);
+ }
+
+ closedir(d);
+ }
+
+ return trigger_device(m, NULL);
+}
+
static DBusHandlerResult manager_message_handler(
DBusConnection *connection,
DBusMessage *message,
@@ -1088,6 +1138,29 @@ static DBusHandlerResult manager_message_handler(
if (!reply)
goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "FlushDevices")) {
+ dbus_bool_t interactive;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_BOOLEAN, &interactive,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ r = verify_polkit(connection, message, "org.freedesktop.login1.flush-devices", interactive, &error);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, &error, r);
+
+ r = flush_devices(m);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, NULL, -EINVAL);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
} else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
char *introspection = NULL;
FILE *f;
diff --git a/src/logind-device.c b/src/logind-device.c
index 31afa4ff2a..bbd370fbff 100644
--- a/src/logind-device.c
+++ b/src/logind-device.c
@@ -70,6 +70,7 @@ void device_detach(Device *d) {
if (d->seat)
LIST_REMOVE(Device, devices, d->seat->devices, d);
+ seat_add_to_gc_queue(d->seat);
d->seat = NULL;
}
diff --git a/src/logind.h b/src/logind.h
index 59ea799d52..ebf859eb2e 100644
--- a/src/logind.h
+++ b/src/logind.h
@@ -37,7 +37,6 @@
* spawn user systemd
* direct client API
* verify access to SetIdleHint
- * add FlushDevices bus call
* hook up ACL tool for udev
*
* udev:
diff --git a/src/org.freedesktop.login1.policy b/src/org.freedesktop.login1.policy
index 8f802c1e56..7ad8f6f316 100644
--- a/src/org.freedesktop.login1.policy
+++ b/src/org.freedesktop.login1.policy
@@ -36,4 +36,14 @@
</defaults>
</action>
+ <action id="org.freedesktop.login1.flush-devices">
+ <description>Flush device to seat attachments</description>
+ <message>Authentication is required to allow reseting how devices are attached to seats</message>
+ <defaults>
+ <allow_any>auth_admin_keep</allow_any>
+ <allow_inactive>auth_admin_keep</allow_inactive>
+ <allow_active>auth_admin_keep</allow_active>
+ </defaults>
+ </action>
+
</policyconfig>