]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-job.c
bus: rework message handlers to always take an error argument
[thirdparty/systemd.git] / src / core / dbus-job.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
ea430986 2
a7334b09
LP
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
5430f7f2
LP
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
a7334b09
LP
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
5430f7f2 16 Lesser General Public License for more details.
a7334b09 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
a7334b09
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
ea430986 22#include "log.h"
718db961 23#include "sd-bus.h"
cad45ba1 24#include "selinux-access.h"
718db961
LP
25#include "job.h"
26#include "dbus-job.h"
27#include "dbus-client-track.h"
28
29static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, job_type, JobType);
30static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_state, job_state, JobState);
31
32static int property_get_unit(
33 sd_bus *bus,
34 const char *path,
35 const char *interface,
36 const char *property,
37 sd_bus_message *reply,
ebcf1f97
LP
38 void *userdata,
39 sd_bus_error *error) {
ea430986 40
68eda4bd 41 _cleanup_free_ char *p = NULL;
718db961 42 Job *j = userdata;
86fbf370 43
718db961
LP
44 assert(bus);
45 assert(reply);
86fbf370
LP
46 assert(j);
47
cad45ba1
LP
48 p = unit_dbus_path(j->unit);
49 if (!p)
86fbf370
LP
50 return -ENOMEM;
51
718db961 52 return sd_bus_message_append(reply, "(so)", j->unit->id, p);
86fbf370
LP
53}
54
ebcf1f97 55static int method_cancel(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961 56 Job *j = userdata;
ebcf1f97 57 int r;
ea430986 58
718db961 59 assert(bus);
ea430986 60 assert(message);
718db961 61 assert(j);
86fbf370 62
ebcf1f97
LP
63 r = selinux_unit_access_check(j->unit, bus, message, "stop", error);
64 if (r < 0)
65 return r;
66
718db961 67 job_finish_and_invalidate(j, JOB_CANCELED, true);
2cccbca4 68
df2d202e 69 return sd_bus_reply_method_return(message, NULL);
ea430986
LP
70}
71
718db961
LP
72const sd_bus_vtable bus_job_vtable[] = {
73 SD_BUS_VTABLE_START(0),
74 SD_BUS_METHOD("Cancel", NULL, NULL, method_cancel, 0),
75 SD_BUS_PROPERTY("Id", "u", NULL, offsetof(Job, id), 0),
76 SD_BUS_PROPERTY("Unit", "(so)", property_get_unit, 0, 0),
77 SD_BUS_PROPERTY("JobType", "s", property_get_type, offsetof(Job, type), 0),
78 SD_BUS_PROPERTY("State", "s", property_get_state, offsetof(Job, state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
79 SD_BUS_VTABLE_END
ea430986 80};
c1e1601e 81
718db961
LP
82static int foreach_client(Job *j, int (*send_message)(sd_bus *bus, const char *name, Job *j)) {
83 BusTrackedClient *one_destination = NULL;
84 Iterator i;
85 sd_bus *b;
86 unsigned n, m;
a567261a
LP
87 int r;
88
89 assert(j);
718db961 90 assert(send_message);
a567261a 91
718db961
LP
92 n = set_size(j->manager->subscribed);
93 m = set_size(j->subscribed);
84286536 94
718db961
LP
95 if (n <= 0 && m <= 0)
96 return 0;
97e6a119 97
718db961
LP
98 if (n == 1 && m == 0)
99 one_destination = set_first(j->manager->subscribed);
100 else if (n == 0 && m == 1)
101 one_destination = set_first(j->subscribed);
102 else
103 one_destination = NULL;
a567261a 104
718db961
LP
105 if (one_destination)
106 return send_message(one_destination->bus, isempty(one_destination->name) ? NULL : one_destination->name, j);
a567261a 107
718db961
LP
108 /* Send to everybody */
109 SET_FOREACH(b, j->manager->private_buses, i) {
110 r = send_message(b, NULL, j);
111 if (r < 0)
112 return r;
a567261a
LP
113 }
114
718db961
LP
115 if (j->manager->api_bus)
116 return send_message(j->manager->api_bus, NULL, j);
117
a567261a
LP
118 return 0;
119}
120
718db961
LP
121static int send_new_signal(sd_bus *bus, const char *destination, Job *j) {
122 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1508e858 123 _cleanup_free_ char *p = NULL;
718db961
LP
124 int r;
125
126 assert(bus);
127 assert(j);
c1e1601e 128
97e6a119
MS
129 p = job_dbus_path(j);
130 if (!p)
718db961 131 return -ENOMEM;
c1e1601e 132
718db961
LP
133 r = sd_bus_message_new_signal(
134 bus,
135 "/org/freedesktop/systemd1",
136 "org.freedesktop.systemd1.Manager",
137 "JobNew",
138 &m);
139 if (r < 0)
140 return r;
141
142 r = sd_bus_message_append(m, "uos", j->id, p, j->unit->id);
143 if (r < 0)
144 return r;
145
146 return sd_bus_send_to(bus, m, destination, NULL);
c1e1601e
LP
147}
148
718db961 149static int send_changed_signal(sd_bus *bus, const char *destination, Job *j) {
1508e858 150 _cleanup_free_ char *p = NULL;
718db961
LP
151
152 assert(bus);
153 assert(j);
c1e1601e 154
97e6a119
MS
155 p = job_dbus_path(j);
156 if (!p)
718db961 157 return -ENOMEM;
c1e1601e 158
718db961 159 return sd_bus_emit_properties_changed(bus, p, "org.freedesktop.systemd1.Job", "State", NULL);
97e6a119
MS
160}
161
162void bus_job_send_change_signal(Job *j) {
718db961
LP
163 int r;
164
97e6a119
MS
165 assert(j);
166
167 if (j->in_dbus_queue) {
71fda00f 168 LIST_REMOVE(dbus_queue, j->manager->dbus_job_queue, j);
97e6a119
MS
169 j->in_dbus_queue = false;
170 }
171
718db961
LP
172 r = foreach_client(j, j->sent_dbus_new_signal ? send_changed_signal : send_new_signal);
173 if (r < 0)
174 log_warning("Failed to send job change signal for %u/%s: %s", j->id, j->unit->id, strerror(-r));
97e6a119
MS
175
176 j->sent_dbus_new_signal = true;
718db961
LP
177}
178
179static int send_removed_signal(sd_bus *bus, const char *destination, Job *j) {
180 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
181 _cleanup_free_ char *p = NULL;
182 int r;
183
184 assert(bus);
185 assert(j);
186
187 p = job_dbus_path(j);
188 if (!p)
189 return -ENOMEM;
c1e1601e 190
c1e1601e 191
718db961
LP
192 r = sd_bus_message_new_signal(
193 bus,
194 "/org/freedesktop/systemd1",
195 "org.freedesktop.systemd1.Manager",
196 "JobRemoved",
197 &m);
198 if (r < 0)
199 return r;
200
201 r = sd_bus_message_append(m, "uoss", j->id, p, j->unit->id, job_result_to_string(j->result));
202 if (r < 0)
203 return r;
204
205 return sd_bus_send_to(bus, m, destination, NULL);
97e6a119 206}
c1e1601e 207
97e6a119 208void bus_job_send_removed_signal(Job *j) {
718db961 209 int r;
c1e1601e 210
718db961 211 assert(j);
97e6a119
MS
212
213 if (!j->sent_dbus_new_signal)
214 bus_job_send_change_signal(j);
215
718db961
LP
216 r = foreach_client(j, send_removed_signal);
217 if (r < 0)
218 log_warning("Failed to send job removal signal for %u/%s: %s", j->id, j->unit->id, strerror(-r));
219 return;
c1e1601e 220}