chiark / gitweb /
dbus: expose cgroup properties in introspection everywhere
[elogind.git] / src / core / dbus-timer.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <errno.h>
23
24 #include "dbus-unit.h"
25 #include "dbus-timer.h"
26 #include "dbus-execute.h"
27 #include "dbus-common.h"
28 #include "selinux-access.h"
29
30 #define BUS_TIMER_INTERFACE                                             \
31         " <interface name=\"org.freedesktop.systemd1.Timer\">\n"        \
32         "  <property name=\"Unit\" type=\"s\" access=\"read\"/>\n"      \
33         "  <property name=\"TimersMonotonic\" type=\"a(stt)\" access=\"read\"/>\n" \
34         "  <property name=\"TimersCalendar\" type=\"a(sst)\" access=\"read\"/>\n" \
35         "  <property name=\"NextElapseUSecRealtime\" type=\"t\" access=\"read\"/>\n" \
36         "  <property name=\"NextElapseUSecMonotonic\" type=\"t\" access=\"read\"/>\n" \
37         "  <property name=\"Result\" type=\"s\" access=\"read\"/>\n"    \
38         " </interface>\n"
39
40 #define INTROSPECTION                                                   \
41         DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                       \
42         "<node>\n"                                                      \
43         BUS_UNIT_INTERFACE                                              \
44         BUS_TIMER_INTERFACE                                             \
45         BUS_PROPERTIES_INTERFACE                                        \
46         BUS_PEER_INTERFACE                                              \
47         BUS_INTROSPECTABLE_INTERFACE                                    \
48         "</node>\n"
49
50 #define INTERFACES_LIST                              \
51         BUS_UNIT_INTERFACES_LIST                     \
52         "org.freedesktop.systemd1.Timer\0"
53
54 const char bus_timer_interface[] _introspect_("Timer") = BUS_TIMER_INTERFACE;
55
56 const char bus_timer_invalidating_properties[] =
57         "TimersMonotonic\0"
58         "TimersRealtime\0"
59         "NextElapseUSecRealtime\0"
60         "NextElapseUSecMonotonic\0"
61         "Result\0";
62
63 static int bus_timer_append_monotonic_timers(DBusMessageIter *i, const char *property, void *data) {
64         Timer *p = data;
65         DBusMessageIter sub, sub2;
66         TimerValue *k;
67
68         assert(i);
69         assert(property);
70         assert(p);
71
72         if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(stt)", &sub))
73                 return -ENOMEM;
74
75         LIST_FOREACH(value, k, p->values) {
76                 _cleanup_free_ char *buf = NULL;
77                 const char *t;
78                 size_t l;
79                 bool b;
80
81                 if (k->base == TIMER_CALENDAR)
82                         continue;
83
84                 t = timer_base_to_string(k->base);
85                 assert(endswith(t, "Sec"));
86
87                 /* s/Sec/USec/ */
88                 l = strlen(t);
89                 buf = new(char, l+2);
90                 if (!buf)
91                         return -ENOMEM;
92
93                 memcpy(buf, t, l-3);
94                 memcpy(buf+l-3, "USec", 5);
95
96                 b = dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) &&
97                         dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &buf) &&
98                         dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &k->value) &&
99                         dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &k->next_elapse) &&
100                         dbus_message_iter_close_container(&sub, &sub2);
101
102                 if (!b)
103                         return -ENOMEM;
104         }
105
106         if (!dbus_message_iter_close_container(i, &sub))
107                 return -ENOMEM;
108
109         return 0;
110 }
111
112 static int bus_timer_append_calendar_timers(DBusMessageIter *i, const char *property, void *data) {
113         Timer *p = data;
114         DBusMessageIter sub, sub2;
115         TimerValue *k;
116
117         assert(i);
118         assert(property);
119         assert(p);
120
121         if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sst)", &sub))
122                 return -ENOMEM;
123
124         LIST_FOREACH(value, k, p->values) {
125                 _cleanup_free_ char *buf = NULL;
126                 const char *t;
127                 bool b;
128                 int j;
129
130                 if (k->base != TIMER_CALENDAR)
131                         continue;
132
133                 t = timer_base_to_string(k->base);
134                 j = calendar_spec_to_string(k->calendar_spec, &buf);
135                 if (j < 0)
136                         return j;
137
138                 b = dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) &&
139                         dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &t) &&
140                         dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &buf) &&
141                         dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &k->next_elapse) &&
142                         dbus_message_iter_close_container(&sub, &sub2);
143
144                 if (!b)
145                         return -ENOMEM;
146         }
147
148         if (!dbus_message_iter_close_container(i, &sub))
149                 return -ENOMEM;
150
151         return 0;
152 }
153
154 static int bus_timer_append_unit(DBusMessageIter *i, const char *property, void *data) {
155         Unit *u = data, *trigger;
156         const char *t;
157
158         assert(i);
159         assert(property);
160         assert(u);
161
162         trigger = UNIT_TRIGGER(u);
163         t = trigger ? trigger->id : "";
164
165         return dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t) ? 0 : -ENOMEM;
166 }
167
168 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_timer_append_timer_result, timer_result, TimerResult);
169
170 static const BusProperty bus_timer_properties[] = {
171         { "Unit",                    bus_timer_append_unit,             "s",      0 },
172         { "TimersMonotonic",         bus_timer_append_monotonic_timers, "a(stt)", 0 },
173         { "TimersCalendar",          bus_timer_append_calendar_timers,  "a(sst)", 0 },
174         { "NextElapseUSecMonotonic", bus_property_append_usec,          "t",      offsetof(Timer, next_elapse_monotonic) },
175         { "NextElapseUSecRealtime",  bus_property_append_usec,          "t",      offsetof(Timer, next_elapse_realtime) },
176         { "Result",                  bus_timer_append_timer_result,     "s",      offsetof(Timer, result) },
177         { NULL, }
178 };
179
180 DBusHandlerResult bus_timer_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
181         Timer *t = TIMER(u);
182         const BusBoundProperties bps[] = {
183                 { "org.freedesktop.systemd1.Unit",  bus_unit_properties,  u },
184                 { "org.freedesktop.systemd1.Timer", bus_timer_properties, t },
185                 { NULL, }
186         };
187
188         SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
189
190         return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
191 }