chiark / gitweb /
add org.freedesktop.DBus.Properies.Set method
authorAndrey Borzenkov <arvidjaar@gmail.com>
Sun, 6 Mar 2011 16:17:02 +0000 (19:17 +0300)
committerLennart Poettering <lennart@poettering.net>
Mon, 7 Mar 2011 01:17:31 +0000 (02:17 +0100)
The patch adds framework for processing Set requests on properties
and as first consumers allows setting of LogTarget and LogLevel on
interface org.freedesktop.systemd1.Manager of org.freedesktop.systemd1.

The code should be generic enough to allow processing of any
property on other objects and interfaces as well.

No systemctl visible interface is added so far. The LogTarget and
LogLevel are meant for debugging in the first place; user interface
can be added if other usage emerge.

Set on systemwide systemd is restricted to root; I am not sure
how session level access is controlled.

src/dbus-manager.c
src/dbus.c
src/dbus.h

index 1a58719..7d4703b 100644 (file)
         "  <property name=\"InitRDTimestamp\" type=\"t\" access=\"read\"/>\n" \
         "  <property name=\"StartupTimestamp\" type=\"t\" access=\"read\"/>\n" \
         "  <property name=\"FinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
         "  <property name=\"InitRDTimestamp\" type=\"t\" access=\"read\"/>\n" \
         "  <property name=\"StartupTimestamp\" type=\"t\" access=\"read\"/>\n" \
         "  <property name=\"FinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"LogLevel\" type=\"s\" access=\"read\"/>\n"  \
-        "  <property name=\"LogTarget\" type=\"s\" access=\"read\"/>\n" \
+        "  <property name=\"LogLevel\" type=\"s\" access=\"readwrite\"/>\n"  \
+        "  <property name=\"LogTarget\" type=\"s\" access=\"readwrite\"/>\n" \
         "  <property name=\"NNames\" type=\"u\" access=\"read\"/>\n"    \
         "  <property name=\"NJobs\" type=\"u\" access=\"read\"/>\n"     \
         "  <property name=\"NInstalledJobs\" type=\"u\" access=\"read\"/>\n" \
         "  <property name=\"NNames\" type=\"u\" access=\"read\"/>\n"    \
         "  <property name=\"NJobs\" type=\"u\" access=\"read\"/>\n"     \
         "  <property name=\"NInstalledJobs\" type=\"u\" access=\"read\"/>\n" \
@@ -252,6 +252,18 @@ static int bus_manager_append_log_target(Manager *m, DBusMessageIter *i, const c
         return 0;
 }
 
         return 0;
 }
 
+static int bus_manager_set_log_target(Manager *m, DBusMessageIter *i, const char *property) {
+        const char *t;
+
+        assert(m);
+        assert(i);
+        assert(property);
+
+        dbus_message_iter_get_basic(i, &t);
+
+        return log_set_target_from_string(t);
+}
+
 static int bus_manager_append_log_level(Manager *m, DBusMessageIter *i, const char *property, void *data) {
         const char *t;
 
 static int bus_manager_append_log_level(Manager *m, DBusMessageIter *i, const char *property, void *data) {
         const char *t;
 
@@ -267,6 +279,18 @@ static int bus_manager_append_log_level(Manager *m, DBusMessageIter *i, const ch
         return 0;
 }
 
         return 0;
 }
 
+static int bus_manager_set_log_level(Manager *m, DBusMessageIter *i, const char *property) {
+        const char *t;
+
+        assert(m);
+        assert(i);
+        assert(property);
+
+        dbus_message_iter_get_basic(i, &t);
+
+        return log_set_max_level_from_string(t);
+}
+
 static int bus_manager_append_n_names(Manager *m, DBusMessageIter *i, const char *property, void *data) {
         uint32_t u;
 
 static int bus_manager_append_n_names(Manager *m, DBusMessageIter *i, const char *property, void *data) {
         uint32_t u;
 
@@ -341,8 +365,8 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
                 { "org.freedesktop.systemd1.Manager", "InitRDTimestamp", bus_property_append_uint64,  "t",  &m->initrd_timestamp.realtime },
                 { "org.freedesktop.systemd1.Manager", "StartupTimestamp", bus_property_append_uint64, "t",  &m->startup_timestamp.realtime },
                 { "org.freedesktop.systemd1.Manager", "FinishTimestamp", bus_property_append_uint64,  "t",  &m->finish_timestamp.realtime },
                 { "org.freedesktop.systemd1.Manager", "InitRDTimestamp", bus_property_append_uint64,  "t",  &m->initrd_timestamp.realtime },
                 { "org.freedesktop.systemd1.Manager", "StartupTimestamp", bus_property_append_uint64, "t",  &m->startup_timestamp.realtime },
                 { "org.freedesktop.systemd1.Manager", "FinishTimestamp", bus_property_append_uint64,  "t",  &m->finish_timestamp.realtime },
-                { "org.freedesktop.systemd1.Manager", "LogLevel",      bus_manager_append_log_level,  "s",  NULL               },
-                { "org.freedesktop.systemd1.Manager", "LogTarget",     bus_manager_append_log_target, "s",  NULL               },
+                { "org.freedesktop.systemd1.Manager", "LogLevel",      bus_manager_append_log_level,  "s",  NULL,               bus_manager_set_log_level},
+                { "org.freedesktop.systemd1.Manager", "LogTarget",     bus_manager_append_log_target, "s",  NULL,               bus_manager_set_log_target},
                 { "org.freedesktop.systemd1.Manager", "NNames",        bus_manager_append_n_names,    "u",  NULL               },
                 { "org.freedesktop.systemd1.Manager", "NJobs",         bus_manager_append_n_jobs,     "u",  NULL               },
                 { "org.freedesktop.systemd1.Manager", "NInstalledJobs",bus_property_append_uint32,    "u",  &m->n_installed_jobs },
                 { "org.freedesktop.systemd1.Manager", "NNames",        bus_manager_append_n_names,    "u",  NULL               },
                 { "org.freedesktop.systemd1.Manager", "NJobs",         bus_manager_append_n_jobs,     "u",  NULL               },
                 { "org.freedesktop.systemd1.Manager", "NInstalledJobs",bus_property_append_uint32,    "u",  &m->n_installed_jobs },
index 965a3e2..5a4750d 100644 (file)
@@ -1316,6 +1316,58 @@ DBusHandlerResult bus_default_message_handler(Manager *m, DBusConnection *c, DBu
 
                 if (!dbus_message_iter_close_container(&iter, &sub))
                         goto oom;
 
                 if (!dbus_message_iter_close_container(&iter, &sub))
                         goto oom;
+        } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Set") && properties) {
+                const char *interface, *property;
+                DBusMessageIter iter;
+                const BusProperty *p;
+
+                if (!dbus_message_iter_init(message, &iter) ||
+                    dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+                        return bus_send_error_reply(m, c, message, NULL, -EINVAL);
+
+                dbus_message_iter_get_basic(&iter, &interface);
+
+                if (!dbus_message_iter_next(&iter) ||
+                    dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+                        return bus_send_error_reply(m, c, message, NULL, -EINVAL);
+
+                dbus_message_iter_get_basic(&iter, &property);
+
+                if (!dbus_message_iter_next(&iter) ||
+                    dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT ||
+                    dbus_message_iter_has_next(&iter))
+                        return bus_send_error_reply(m, c, message, NULL, -EINVAL);
+
+                for (p = properties; p->property; p++)
+                        if (streq(p->interface, interface) && streq(p->property, property))
+                                break;
+
+                if (p->set) {
+                        DBusMessageIter sub;
+                        char *sig;
+
+                        dbus_message_iter_recurse(&iter, &sub);
+
+                        if (!(sig = dbus_message_iter_get_signature(&sub)))
+                                goto oom;
+
+                        if (!streq(sig, p->signature)) {
+                                dbus_free(sig);
+                                return bus_send_error_reply(m, c, message, NULL, -EINVAL);
+                        }
+
+                        dbus_free(sig);
+
+                        if ((r = p->set(m, &sub, property)) < 0) {
+                                if (r == -ENOMEM)
+                                        goto oom;
+                                return bus_send_error_reply(m, c, message, NULL, r);
+                        }
+
+                        if (!(reply = dbus_message_new_method_return(message)))
+                                goto oom;
+                } else
+                        return bus_send_error_reply(m, c, message, NULL, -EINVAL);
         }
 
         if (reply) {
         }
 
         if (reply) {
index d0a9e8e..255b653 100644 (file)
@@ -27,6 +27,7 @@
 #include "manager.h"
 
 typedef int (*BusPropertyCallback)(Manager *m, DBusMessageIter *iter, const char *property, void *data);
 #include "manager.h"
 
 typedef int (*BusPropertyCallback)(Manager *m, DBusMessageIter *iter, const char *property, void *data);
+typedef int (*BusPropertySetCallback)(Manager *m, DBusMessageIter *iter, const char *property);
 
 typedef struct BusProperty {
         const char *interface;           /* interface of the property */
 
 typedef struct BusProperty {
         const char *interface;           /* interface of the property */
@@ -34,6 +35,7 @@ typedef struct BusProperty {
         BusPropertyCallback append;      /* Function that is called to serialize this property */
         const char *signature;
         const void *data;                /* The data of this property */
         BusPropertyCallback append;      /* Function that is called to serialize this property */
         const char *signature;
         const void *data;                /* The data of this property */
+        BusPropertySetCallback set;      /* Function that is called to set this property */
 } BusProperty;
 
 #define BUS_PROPERTIES_INTERFACE                                        \
 } BusProperty;
 
 #define BUS_PROPERTIES_INTERFACE                                        \
@@ -47,6 +49,11 @@ typedef struct BusProperty {
         "   <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n"    \
         "   <arg name=\"properties\" direction=\"out\" type=\"a{sv}\"/>\n" \
         "  </method>\n"                                                 \
         "   <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n"    \
         "   <arg name=\"properties\" direction=\"out\" type=\"a{sv}\"/>\n" \
         "  </method>\n"                                                 \
+        "  <method name=\"Set\">\n"                                     \
+        "   <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n"    \
+        "   <arg name=\"property\" direction=\"in\" type=\"s\"/>\n"     \
+        "   <arg name=\"value\" direction=\"in\" type=\"v\"/>\n"       \
+        "  </method>\n"                                                 \
         "  <signal name=\"PropertiesChanged\">\n"                       \
         "   <arg type=\"s\" name=\"interface\"/>\n"                     \
         "   <arg type=\"a{sv}\" name=\"changed_properties\"/>\n"        \
         "  <signal name=\"PropertiesChanged\">\n"                       \
         "   <arg type=\"s\" name=\"interface\"/>\n"                     \
         "   <arg type=\"a{sv}\" name=\"changed_properties\"/>\n"        \