]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-job.c
missing.h: add BTRFS_IOC_QUOTA_RESCAN_WAIT (#3266)
[thirdparty/systemd.git] / src / core / dbus-job.c
CommitLineData
a7334b09
LP
1/***
2 This file is part of systemd.
3
4 Copyright 2010 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
a7334b09
LP
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 14 Lesser General Public License for more details.
a7334b09 15
5430f7f2 16 You should have received a copy of the GNU Lesser General Public License
a7334b09
LP
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18***/
19
718db961 20#include "sd-bus.h"
07630cea 21
b5efdb8a
LP
22#include "alloc-util.h"
23#include "dbus-job.h"
07630cea 24#include "dbus.h"
718db961 25#include "job.h"
07630cea
LP
26#include "log.h"
27#include "selinux-access.h"
28#include "string-util.h"
718db961
LP
29
30static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, job_type, JobType);
31static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_state, job_state, JobState);
32
33static int property_get_unit(
34 sd_bus *bus,
35 const char *path,
36 const char *interface,
37 const char *property,
38 sd_bus_message *reply,
ebcf1f97
LP
39 void *userdata,
40 sd_bus_error *error) {
ea430986 41
68eda4bd 42 _cleanup_free_ char *p = NULL;
718db961 43 Job *j = userdata;
86fbf370 44
718db961
LP
45 assert(bus);
46 assert(reply);
86fbf370
LP
47 assert(j);
48
cad45ba1
LP
49 p = unit_dbus_path(j->unit);
50 if (!p)
86fbf370
LP
51 return -ENOMEM;
52
718db961 53 return sd_bus_message_append(reply, "(so)", j->unit->id, p);
86fbf370
LP
54}
55
19070062 56int bus_job_method_cancel(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961 57 Job *j = userdata;
ebcf1f97 58 int r;
ea430986 59
ea430986 60 assert(message);
718db961 61 assert(j);
86fbf370 62
8a188de9 63 r = mac_selinux_unit_access_check(j->unit, message, "stop", error);
ebcf1f97
LP
64 if (r < 0)
65 return r;
66
1d22e906
LP
67 /* Access is granted to the job owner */
68 if (!sd_bus_track_contains(j->clients, sd_bus_message_get_sender(message))) {
69
70 /* And for everybody else consult PolicyKit */
71 r = bus_verify_manage_units_async(j->unit->manager, message, error);
72 if (r < 0)
73 return r;
74 if (r == 0)
75 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
76 }
77
718db961 78 job_finish_and_invalidate(j, JOB_CANCELED, true);
2cccbca4 79
df2d202e 80 return sd_bus_reply_method_return(message, NULL);
ea430986
LP
81}
82
718db961
LP
83const sd_bus_vtable bus_job_vtable[] = {
84 SD_BUS_VTABLE_START(0),
283868e1 85 SD_BUS_METHOD("Cancel", NULL, NULL, bus_job_method_cancel, SD_BUS_VTABLE_UNPRIVILEGED),
556089dc
LP
86 SD_BUS_PROPERTY("Id", "u", NULL, offsetof(Job, id), SD_BUS_VTABLE_PROPERTY_CONST),
87 SD_BUS_PROPERTY("Unit", "(so)", property_get_unit, 0, SD_BUS_VTABLE_PROPERTY_CONST),
88 SD_BUS_PROPERTY("JobType", "s", property_get_type, offsetof(Job, type), SD_BUS_VTABLE_PROPERTY_CONST),
718db961
LP
89 SD_BUS_PROPERTY("State", "s", property_get_state, offsetof(Job, state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
90 SD_BUS_VTABLE_END
ea430986 91};
c1e1601e 92
8f8f05a9 93static int send_new_signal(sd_bus *bus, void *userdata) {
4afd3348 94 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
1508e858 95 _cleanup_free_ char *p = NULL;
8f8f05a9 96 Job *j = userdata;
718db961
LP
97 int r;
98
99 assert(bus);
100 assert(j);
c1e1601e 101
97e6a119
MS
102 p = job_dbus_path(j);
103 if (!p)
718db961 104 return -ENOMEM;
c1e1601e 105
718db961
LP
106 r = sd_bus_message_new_signal(
107 bus,
151b9b96 108 &m,
718db961
LP
109 "/org/freedesktop/systemd1",
110 "org.freedesktop.systemd1.Manager",
151b9b96 111 "JobNew");
718db961
LP
112 if (r < 0)
113 return r;
114
115 r = sd_bus_message_append(m, "uos", j->id, p, j->unit->id);
116 if (r < 0)
117 return r;
118
8f8f05a9 119 return sd_bus_send(bus, m, NULL);
c1e1601e
LP
120}
121
8f8f05a9 122static int send_changed_signal(sd_bus *bus, void *userdata) {
1508e858 123 _cleanup_free_ char *p = NULL;
8f8f05a9 124 Job *j = userdata;
718db961
LP
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 133 return sd_bus_emit_properties_changed(bus, p, "org.freedesktop.systemd1.Job", "State", NULL);
97e6a119
MS
134}
135
136void bus_job_send_change_signal(Job *j) {
718db961
LP
137 int r;
138
97e6a119
MS
139 assert(j);
140
141 if (j->in_dbus_queue) {
71fda00f 142 LIST_REMOVE(dbus_queue, j->manager->dbus_job_queue, j);
97e6a119
MS
143 j->in_dbus_queue = false;
144 }
145
b39a2770 146 r = bus_foreach_bus(j->manager, j->clients, j->sent_dbus_new_signal ? send_changed_signal : send_new_signal, j);
718db961 147 if (r < 0)
da927ba9 148 log_debug_errno(r, "Failed to send job change signal for %u: %m", j->id);
97e6a119
MS
149
150 j->sent_dbus_new_signal = true;
718db961
LP
151}
152
8f8f05a9 153static int send_removed_signal(sd_bus *bus, void *userdata) {
4afd3348 154 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
718db961 155 _cleanup_free_ char *p = NULL;
8f8f05a9 156 Job *j = userdata;
718db961
LP
157 int r;
158
159 assert(bus);
160 assert(j);
161
162 p = job_dbus_path(j);
163 if (!p)
164 return -ENOMEM;
c1e1601e 165
718db961
LP
166 r = sd_bus_message_new_signal(
167 bus,
151b9b96 168 &m,
718db961
LP
169 "/org/freedesktop/systemd1",
170 "org.freedesktop.systemd1.Manager",
151b9b96 171 "JobRemoved");
718db961
LP
172 if (r < 0)
173 return r;
174
175 r = sd_bus_message_append(m, "uoss", j->id, p, j->unit->id, job_result_to_string(j->result));
176 if (r < 0)
177 return r;
178
8f8f05a9 179 return sd_bus_send(bus, m, NULL);
97e6a119 180}
c1e1601e 181
97e6a119 182void bus_job_send_removed_signal(Job *j) {
718db961 183 int r;
c1e1601e 184
718db961 185 assert(j);
97e6a119
MS
186
187 if (!j->sent_dbus_new_signal)
188 bus_job_send_change_signal(j);
189
b39a2770 190 r = bus_foreach_bus(j->manager, j->clients, send_removed_signal, j);
718db961 191 if (r < 0)
da927ba9 192 log_debug_errno(r, "Failed to send job remove signal for %u: %m", j->id);
c1e1601e 193}