chiark / gitweb /
dbus: add FlushDevices() bus call to reset all seat assignments
authorLennart Poettering <lennart@poettering.net>
Wed, 29 Jun 2011 01:12:23 +0000 (03:12 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 29 Jun 2011 01:12:23 +0000 (03:12 +0200)
src/logind-dbus.c
src/logind-device.c
src/logind.h
src/org.freedesktop.login1.policy

index 93525980b79dc3167efb76bf9660dd2a6adf23ca..96216e43a358eaf81374d72664e3d7f624939ca8 100644 (file)
@@ -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;
index 31afa4ff2a776cb420bda0ca119142b877654b9f..bbd370fbff75dc9721e6dc5bdae57795bbcb1a41 100644 (file)
@@ -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;
 }
 
index 59ea799d521e82185c44d648fbefb80d871ddaf4..ebf859eb2ef14068bc940d766a4c9ac2a3151807 100644 (file)
@@ -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:
index 8f802c1e56f76e92cdc6cb70883e4d15e0a65130..7ad8f6f316b851d3860338a15c5ff4485b6c15a1 100644 (file)
                 </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>