]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-job.c
sd-bus: the bus returned should be the first arg
[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),
556089dc
LP
75 SD_BUS_PROPERTY("Id", "u", NULL, offsetof(Job, id), SD_BUS_VTABLE_PROPERTY_CONST),
76 SD_BUS_PROPERTY("Unit", "(so)", property_get_unit, 0, SD_BUS_VTABLE_PROPERTY_CONST),
77 SD_BUS_PROPERTY("JobType", "s", property_get_type, offsetof(Job, type), SD_BUS_VTABLE_PROPERTY_CONST),
718db961
LP
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;
39abcaee 87 int r, ret;
a567261a
LP
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
39abcaee
LP
108 ret = 0;
109
718db961
LP
110 /* Send to everybody */
111 SET_FOREACH(b, j->manager->private_buses, i) {
112 r = send_message(b, NULL, j);
113 if (r < 0)
39abcaee 114 ret = r;
a567261a
LP
115 }
116
39abcaee
LP
117 if (j->manager->api_bus) {
118 r = send_message(j->manager->api_bus, NULL, j);
119 if (r < 0)
120 ret = r;
121 }
718db961 122
39abcaee 123 return ret;
a567261a
LP
124}
125
718db961
LP
126static int send_new_signal(sd_bus *bus, const char *destination, Job *j) {
127 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1508e858 128 _cleanup_free_ char *p = NULL;
718db961
LP
129 int r;
130
131 assert(bus);
132 assert(j);
c1e1601e 133
97e6a119
MS
134 p = job_dbus_path(j);
135 if (!p)
718db961 136 return -ENOMEM;
c1e1601e 137
718db961
LP
138 r = sd_bus_message_new_signal(
139 bus,
140 "/org/freedesktop/systemd1",
141 "org.freedesktop.systemd1.Manager",
142 "JobNew",
143 &m);
144 if (r < 0)
145 return r;
146
147 r = sd_bus_message_append(m, "uos", j->id, p, j->unit->id);
148 if (r < 0)
149 return r;
150
151 return sd_bus_send_to(bus, m, destination, NULL);
c1e1601e
LP
152}
153
718db961 154static int send_changed_signal(sd_bus *bus, const char *destination, Job *j) {
1508e858 155 _cleanup_free_ char *p = NULL;
718db961
LP
156
157 assert(bus);
158 assert(j);
c1e1601e 159
97e6a119
MS
160 p = job_dbus_path(j);
161 if (!p)
718db961 162 return -ENOMEM;
c1e1601e 163
718db961 164 return sd_bus_emit_properties_changed(bus, p, "org.freedesktop.systemd1.Job", "State", NULL);
97e6a119
MS
165}
166
167void bus_job_send_change_signal(Job *j) {
718db961
LP
168 int r;
169
97e6a119
MS
170 assert(j);
171
172 if (j->in_dbus_queue) {
71fda00f 173 LIST_REMOVE(dbus_queue, j->manager->dbus_job_queue, j);
97e6a119
MS
174 j->in_dbus_queue = false;
175 }
176
718db961
LP
177 r = foreach_client(j, j->sent_dbus_new_signal ? send_changed_signal : send_new_signal);
178 if (r < 0)
39abcaee 179 log_debug("Failed to send job change signal for %u: %s", j->id, strerror(-r));
97e6a119
MS
180
181 j->sent_dbus_new_signal = true;
718db961
LP
182}
183
184static int send_removed_signal(sd_bus *bus, const char *destination, Job *j) {
185 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
186 _cleanup_free_ char *p = NULL;
187 int r;
188
189 assert(bus);
190 assert(j);
191
192 p = job_dbus_path(j);
193 if (!p)
194 return -ENOMEM;
c1e1601e 195
c1e1601e 196
718db961
LP
197 r = sd_bus_message_new_signal(
198 bus,
199 "/org/freedesktop/systemd1",
200 "org.freedesktop.systemd1.Manager",
201 "JobRemoved",
202 &m);
203 if (r < 0)
204 return r;
205
206 r = sd_bus_message_append(m, "uoss", j->id, p, j->unit->id, job_result_to_string(j->result));
207 if (r < 0)
208 return r;
209
210 return sd_bus_send_to(bus, m, destination, NULL);
97e6a119 211}
c1e1601e 212
97e6a119 213void bus_job_send_removed_signal(Job *j) {
718db961 214 int r;
c1e1601e 215
718db961 216 assert(j);
97e6a119
MS
217
218 if (!j->sent_dbus_new_signal)
219 bus_job_send_change_signal(j);
220
718db961
LP
221 r = foreach_client(j, send_removed_signal);
222 if (r < 0)
39abcaee 223 log_debug("Failed to send job remove signal for %u: %s", j->id, strerror(-r));
c1e1601e 224}