]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-job.c
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
[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
718db961 22#include "sd-bus.h"
07630cea 23
b5efdb8a
LP
24#include "alloc-util.h"
25#include "dbus-job.h"
07630cea 26#include "dbus.h"
718db961 27#include "job.h"
07630cea
LP
28#include "log.h"
29#include "selinux-access.h"
30#include "string-util.h"
718db961
LP
31
32static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, job_type, JobType);
33static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_state, job_state, JobState);
34
35static int property_get_unit(
36 sd_bus *bus,
37 const char *path,
38 const char *interface,
39 const char *property,
40 sd_bus_message *reply,
ebcf1f97
LP
41 void *userdata,
42 sd_bus_error *error) {
ea430986 43
68eda4bd 44 _cleanup_free_ char *p = NULL;
718db961 45 Job *j = userdata;
86fbf370 46
718db961
LP
47 assert(bus);
48 assert(reply);
86fbf370
LP
49 assert(j);
50
cad45ba1
LP
51 p = unit_dbus_path(j->unit);
52 if (!p)
86fbf370
LP
53 return -ENOMEM;
54
718db961 55 return sd_bus_message_append(reply, "(so)", j->unit->id, p);
86fbf370
LP
56}
57
19070062 58int bus_job_method_cancel(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961 59 Job *j = userdata;
ebcf1f97 60 int r;
ea430986 61
ea430986 62 assert(message);
718db961 63 assert(j);
86fbf370 64
8a188de9 65 r = mac_selinux_unit_access_check(j->unit, message, "stop", error);
ebcf1f97
LP
66 if (r < 0)
67 return r;
68
1d22e906
LP
69 /* Access is granted to the job owner */
70 if (!sd_bus_track_contains(j->clients, sd_bus_message_get_sender(message))) {
71
72 /* And for everybody else consult PolicyKit */
73 r = bus_verify_manage_units_async(j->unit->manager, message, error);
74 if (r < 0)
75 return r;
76 if (r == 0)
77 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
78 }
79
718db961 80 job_finish_and_invalidate(j, JOB_CANCELED, true);
2cccbca4 81
df2d202e 82 return sd_bus_reply_method_return(message, NULL);
ea430986
LP
83}
84
718db961
LP
85const sd_bus_vtable bus_job_vtable[] = {
86 SD_BUS_VTABLE_START(0),
283868e1 87 SD_BUS_METHOD("Cancel", NULL, NULL, bus_job_method_cancel, SD_BUS_VTABLE_UNPRIVILEGED),
556089dc
LP
88 SD_BUS_PROPERTY("Id", "u", NULL, offsetof(Job, id), SD_BUS_VTABLE_PROPERTY_CONST),
89 SD_BUS_PROPERTY("Unit", "(so)", property_get_unit, 0, SD_BUS_VTABLE_PROPERTY_CONST),
90 SD_BUS_PROPERTY("JobType", "s", property_get_type, offsetof(Job, type), SD_BUS_VTABLE_PROPERTY_CONST),
718db961
LP
91 SD_BUS_PROPERTY("State", "s", property_get_state, offsetof(Job, state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
92 SD_BUS_VTABLE_END
ea430986 93};
c1e1601e 94
8f8f05a9 95static int send_new_signal(sd_bus *bus, void *userdata) {
4afd3348 96 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
1508e858 97 _cleanup_free_ char *p = NULL;
8f8f05a9 98 Job *j = userdata;
718db961
LP
99 int r;
100
101 assert(bus);
102 assert(j);
c1e1601e 103
97e6a119
MS
104 p = job_dbus_path(j);
105 if (!p)
718db961 106 return -ENOMEM;
c1e1601e 107
718db961
LP
108 r = sd_bus_message_new_signal(
109 bus,
151b9b96 110 &m,
718db961
LP
111 "/org/freedesktop/systemd1",
112 "org.freedesktop.systemd1.Manager",
151b9b96 113 "JobNew");
718db961
LP
114 if (r < 0)
115 return r;
116
117 r = sd_bus_message_append(m, "uos", j->id, p, j->unit->id);
118 if (r < 0)
119 return r;
120
8f8f05a9 121 return sd_bus_send(bus, m, NULL);
c1e1601e
LP
122}
123
8f8f05a9 124static int send_changed_signal(sd_bus *bus, void *userdata) {
1508e858 125 _cleanup_free_ char *p = NULL;
8f8f05a9 126 Job *j = userdata;
718db961
LP
127
128 assert(bus);
129 assert(j);
c1e1601e 130
97e6a119
MS
131 p = job_dbus_path(j);
132 if (!p)
718db961 133 return -ENOMEM;
c1e1601e 134
718db961 135 return sd_bus_emit_properties_changed(bus, p, "org.freedesktop.systemd1.Job", "State", NULL);
97e6a119
MS
136}
137
138void bus_job_send_change_signal(Job *j) {
718db961
LP
139 int r;
140
97e6a119
MS
141 assert(j);
142
143 if (j->in_dbus_queue) {
71fda00f 144 LIST_REMOVE(dbus_queue, j->manager->dbus_job_queue, j);
97e6a119
MS
145 j->in_dbus_queue = false;
146 }
147
b39a2770 148 r = bus_foreach_bus(j->manager, j->clients, j->sent_dbus_new_signal ? send_changed_signal : send_new_signal, j);
718db961 149 if (r < 0)
da927ba9 150 log_debug_errno(r, "Failed to send job change signal for %u: %m", j->id);
97e6a119
MS
151
152 j->sent_dbus_new_signal = true;
718db961
LP
153}
154
8f8f05a9 155static int send_removed_signal(sd_bus *bus, void *userdata) {
4afd3348 156 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
718db961 157 _cleanup_free_ char *p = NULL;
8f8f05a9 158 Job *j = userdata;
718db961
LP
159 int r;
160
161 assert(bus);
162 assert(j);
163
164 p = job_dbus_path(j);
165 if (!p)
166 return -ENOMEM;
c1e1601e 167
718db961
LP
168 r = sd_bus_message_new_signal(
169 bus,
151b9b96 170 &m,
718db961
LP
171 "/org/freedesktop/systemd1",
172 "org.freedesktop.systemd1.Manager",
151b9b96 173 "JobRemoved");
718db961
LP
174 if (r < 0)
175 return r;
176
177 r = sd_bus_message_append(m, "uoss", j->id, p, j->unit->id, job_result_to_string(j->result));
178 if (r < 0)
179 return r;
180
8f8f05a9 181 return sd_bus_send(bus, m, NULL);
97e6a119 182}
c1e1601e 183
97e6a119 184void bus_job_send_removed_signal(Job *j) {
718db961 185 int r;
c1e1601e 186
718db961 187 assert(j);
97e6a119
MS
188
189 if (!j->sent_dbus_new_signal)
190 bus_job_send_change_signal(j);
191
b39a2770 192 r = bus_foreach_bus(j->manager, j->clients, send_removed_signal, j);
718db961 193 if (r < 0)
da927ba9 194 log_debug_errno(r, "Failed to send job remove signal for %u: %m", j->id);
c1e1601e 195}