]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-job.c
hostnamed: modernizations
[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,
38 sd_bus_error *error,
39 void *userdata) {
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
718db961
LP
55static int method_cancel(sd_bus *bus, sd_bus_message *message, void *userdata) {
56 Job *j = userdata;
ea430986 57
718db961 58 assert(bus);
ea430986 59 assert(message);
718db961 60 assert(j);
86fbf370 61
718db961
LP
62 SELINUX_UNIT_ACCESS_CHECK(j->unit, bus, message, "stop");
63 job_finish_and_invalidate(j, JOB_CANCELED, true);
2cccbca4 64
df2d202e 65 return sd_bus_reply_method_return(message, NULL);
ea430986
LP
66}
67
718db961
LP
68const sd_bus_vtable bus_job_vtable[] = {
69 SD_BUS_VTABLE_START(0),
70 SD_BUS_METHOD("Cancel", NULL, NULL, method_cancel, 0),
71 SD_BUS_PROPERTY("Id", "u", NULL, offsetof(Job, id), 0),
72 SD_BUS_PROPERTY("Unit", "(so)", property_get_unit, 0, 0),
73 SD_BUS_PROPERTY("JobType", "s", property_get_type, offsetof(Job, type), 0),
74 SD_BUS_PROPERTY("State", "s", property_get_state, offsetof(Job, state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
75 SD_BUS_VTABLE_END
ea430986 76};
c1e1601e 77
718db961
LP
78static int foreach_client(Job *j, int (*send_message)(sd_bus *bus, const char *name, Job *j)) {
79 BusTrackedClient *one_destination = NULL;
80 Iterator i;
81 sd_bus *b;
82 unsigned n, m;
a567261a
LP
83 int r;
84
85 assert(j);
718db961 86 assert(send_message);
a567261a 87
718db961
LP
88 n = set_size(j->manager->subscribed);
89 m = set_size(j->subscribed);
84286536 90
718db961
LP
91 if (n <= 0 && m <= 0)
92 return 0;
97e6a119 93
718db961
LP
94 if (n == 1 && m == 0)
95 one_destination = set_first(j->manager->subscribed);
96 else if (n == 0 && m == 1)
97 one_destination = set_first(j->subscribed);
98 else
99 one_destination = NULL;
a567261a 100
718db961
LP
101 if (one_destination)
102 return send_message(one_destination->bus, isempty(one_destination->name) ? NULL : one_destination->name, j);
a567261a 103
718db961
LP
104 /* Send to everybody */
105 SET_FOREACH(b, j->manager->private_buses, i) {
106 r = send_message(b, NULL, j);
107 if (r < 0)
108 return r;
a567261a
LP
109 }
110
718db961
LP
111 if (j->manager->api_bus)
112 return send_message(j->manager->api_bus, NULL, j);
113
a567261a
LP
114 return 0;
115}
116
718db961
LP
117static int send_new_signal(sd_bus *bus, const char *destination, Job *j) {
118 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1508e858 119 _cleanup_free_ char *p = NULL;
718db961
LP
120 int r;
121
122 assert(bus);
123 assert(j);
c1e1601e 124
97e6a119
MS
125 p = job_dbus_path(j);
126 if (!p)
718db961 127 return -ENOMEM;
c1e1601e 128
718db961
LP
129 r = sd_bus_message_new_signal(
130 bus,
131 "/org/freedesktop/systemd1",
132 "org.freedesktop.systemd1.Manager",
133 "JobNew",
134 &m);
135 if (r < 0)
136 return r;
137
138 r = sd_bus_message_append(m, "uos", j->id, p, j->unit->id);
139 if (r < 0)
140 return r;
141
142 return sd_bus_send_to(bus, m, destination, NULL);
c1e1601e
LP
143}
144
718db961 145static int send_changed_signal(sd_bus *bus, const char *destination, Job *j) {
1508e858 146 _cleanup_free_ char *p = NULL;
718db961
LP
147
148 assert(bus);
149 assert(j);
c1e1601e 150
97e6a119
MS
151 p = job_dbus_path(j);
152 if (!p)
718db961 153 return -ENOMEM;
c1e1601e 154
718db961 155 return sd_bus_emit_properties_changed(bus, p, "org.freedesktop.systemd1.Job", "State", NULL);
97e6a119
MS
156}
157
158void bus_job_send_change_signal(Job *j) {
718db961
LP
159 int r;
160
97e6a119
MS
161 assert(j);
162
163 if (j->in_dbus_queue) {
71fda00f 164 LIST_REMOVE(dbus_queue, j->manager->dbus_job_queue, j);
97e6a119
MS
165 j->in_dbus_queue = false;
166 }
167
718db961
LP
168 r = foreach_client(j, j->sent_dbus_new_signal ? send_changed_signal : send_new_signal);
169 if (r < 0)
170 log_warning("Failed to send job change signal for %u/%s: %s", j->id, j->unit->id, strerror(-r));
97e6a119
MS
171
172 j->sent_dbus_new_signal = true;
718db961
LP
173}
174
175static int send_removed_signal(sd_bus *bus, const char *destination, Job *j) {
176 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
177 _cleanup_free_ char *p = NULL;
178 int r;
179
180 assert(bus);
181 assert(j);
182
183 p = job_dbus_path(j);
184 if (!p)
185 return -ENOMEM;
c1e1601e 186
c1e1601e 187
718db961
LP
188 r = sd_bus_message_new_signal(
189 bus,
190 "/org/freedesktop/systemd1",
191 "org.freedesktop.systemd1.Manager",
192 "JobRemoved",
193 &m);
194 if (r < 0)
195 return r;
196
197 r = sd_bus_message_append(m, "uoss", j->id, p, j->unit->id, job_result_to_string(j->result));
198 if (r < 0)
199 return r;
200
201 return sd_bus_send_to(bus, m, destination, NULL);
97e6a119 202}
c1e1601e 203
97e6a119 204void bus_job_send_removed_signal(Job *j) {
718db961 205 int r;
c1e1601e 206
718db961 207 assert(j);
97e6a119
MS
208
209 if (!j->sent_dbus_new_signal)
210 bus_job_send_change_signal(j);
211
718db961
LP
212 r = foreach_client(j, send_removed_signal);
213 if (r < 0)
214 log_warning("Failed to send job removal signal for %u/%s: %s", j->id, j->unit->id, strerror(-r));
215 return;
c1e1601e 216}