dbus: add FlushDevices() bus call to reset all seat assignments
This commit is contained in:
+107
-34
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user