]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-job.c
update TODO
[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"
8f8f05a9 27#include "dbus.h"
718db961
LP
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
283868e1 32static int verify_sys_admin_or_owner_sync(sd_bus_message *message, Job *j, sd_bus_error *error) {
283868e1
SW
33 int r;
34
35 if (sd_bus_track_contains(j->clients, sd_bus_message_get_sender(message)))
36 return 0; /* One of the job owners is calling us */
37
38 r = sd_bus_query_sender_privilege(message, CAP_SYS_ADMIN);
39 if (r < 0)
40 return r;
41 if (r == 0)
42 return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Access denied to perform action");
43
44 /* Root has called us */
45 return 0;
46}
47
718db961
LP
48static int property_get_unit(
49 sd_bus *bus,
50 const char *path,
51 const char *interface,
52 const char *property,
53 sd_bus_message *reply,
ebcf1f97
LP
54 void *userdata,
55 sd_bus_error *error) {
ea430986 56
68eda4bd 57 _cleanup_free_ char *p = NULL;
718db961 58 Job *j = userdata;
86fbf370 59
718db961
LP
60 assert(bus);
61 assert(reply);
86fbf370
LP
62 assert(j);
63
cad45ba1
LP
64 p = unit_dbus_path(j->unit);
65 if (!p)
86fbf370
LP
66 return -ENOMEM;
67
718db961 68 return sd_bus_message_append(reply, "(so)", j->unit->id, p);
86fbf370
LP
69}
70
2ea31e5b 71int bus_job_method_cancel(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961 72 Job *j = userdata;
ebcf1f97 73 int r;
ea430986 74
718db961 75 assert(bus);
ea430986 76 assert(message);
718db961 77 assert(j);
86fbf370 78
283868e1
SW
79 r = verify_sys_admin_or_owner_sync(message, j, error);
80 if (r < 0)
81 return r;
82
4f4f7036 83 r = selinux_unit_access_check(j->unit, message, "stop", error);
ebcf1f97
LP
84 if (r < 0)
85 return r;
86
718db961 87 job_finish_and_invalidate(j, JOB_CANCELED, true);
2cccbca4 88
df2d202e 89 return sd_bus_reply_method_return(message, NULL);
ea430986
LP
90}
91
718db961
LP
92const sd_bus_vtable bus_job_vtable[] = {
93 SD_BUS_VTABLE_START(0),
283868e1 94 SD_BUS_METHOD("Cancel", NULL, NULL, bus_job_method_cancel, SD_BUS_VTABLE_UNPRIVILEGED),
556089dc
LP
95 SD_BUS_PROPERTY("Id", "u", NULL, offsetof(Job, id), SD_BUS_VTABLE_PROPERTY_CONST),
96 SD_BUS_PROPERTY("Unit", "(so)", property_get_unit, 0, SD_BUS_VTABLE_PROPERTY_CONST),
97 SD_BUS_PROPERTY("JobType", "s", property_get_type, offsetof(Job, type), SD_BUS_VTABLE_PROPERTY_CONST),
718db961
LP
98 SD_BUS_PROPERTY("State", "s", property_get_state, offsetof(Job, state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
99 SD_BUS_VTABLE_END
ea430986 100};
c1e1601e 101
8f8f05a9 102static int send_new_signal(sd_bus *bus, void *userdata) {
718db961 103 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1508e858 104 _cleanup_free_ char *p = NULL;
8f8f05a9 105 Job *j = userdata;
718db961
LP
106 int r;
107
108 assert(bus);
109 assert(j);
c1e1601e 110
97e6a119
MS
111 p = job_dbus_path(j);
112 if (!p)
718db961 113 return -ENOMEM;
c1e1601e 114
718db961
LP
115 r = sd_bus_message_new_signal(
116 bus,
151b9b96 117 &m,
718db961
LP
118 "/org/freedesktop/systemd1",
119 "org.freedesktop.systemd1.Manager",
151b9b96 120 "JobNew");
718db961
LP
121 if (r < 0)
122 return r;
123
124 r = sd_bus_message_append(m, "uos", j->id, p, j->unit->id);
125 if (r < 0)
126 return r;
127
8f8f05a9 128 return sd_bus_send(bus, m, NULL);
c1e1601e
LP
129}
130
8f8f05a9 131static int send_changed_signal(sd_bus *bus, void *userdata) {
1508e858 132 _cleanup_free_ char *p = NULL;
8f8f05a9 133 Job *j = userdata;
718db961
LP
134
135 assert(bus);
136 assert(j);
c1e1601e 137
97e6a119
MS
138 p = job_dbus_path(j);
139 if (!p)
718db961 140 return -ENOMEM;
c1e1601e 141
718db961 142 return sd_bus_emit_properties_changed(bus, p, "org.freedesktop.systemd1.Job", "State", NULL);
97e6a119
MS
143}
144
145void bus_job_send_change_signal(Job *j) {
718db961
LP
146 int r;
147
97e6a119
MS
148 assert(j);
149
150 if (j->in_dbus_queue) {
71fda00f 151 LIST_REMOVE(dbus_queue, j->manager->dbus_job_queue, j);
97e6a119
MS
152 j->in_dbus_queue = false;
153 }
154
b39a2770 155 r = bus_foreach_bus(j->manager, j->clients, j->sent_dbus_new_signal ? send_changed_signal : send_new_signal, j);
718db961 156 if (r < 0)
39abcaee 157 log_debug("Failed to send job change signal for %u: %s", j->id, strerror(-r));
97e6a119
MS
158
159 j->sent_dbus_new_signal = true;
718db961
LP
160}
161
8f8f05a9 162static int send_removed_signal(sd_bus *bus, void *userdata) {
718db961
LP
163 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
164 _cleanup_free_ char *p = NULL;
8f8f05a9 165 Job *j = userdata;
718db961
LP
166 int r;
167
168 assert(bus);
169 assert(j);
170
171 p = job_dbus_path(j);
172 if (!p)
173 return -ENOMEM;
c1e1601e 174
718db961
LP
175 r = sd_bus_message_new_signal(
176 bus,
151b9b96 177 &m,
718db961
LP
178 "/org/freedesktop/systemd1",
179 "org.freedesktop.systemd1.Manager",
151b9b96 180 "JobRemoved");
718db961
LP
181 if (r < 0)
182 return r;
183
184 r = sd_bus_message_append(m, "uoss", j->id, p, j->unit->id, job_result_to_string(j->result));
185 if (r < 0)
186 return r;
187
8f8f05a9 188 return sd_bus_send(bus, m, NULL);
97e6a119 189}
c1e1601e 190
97e6a119 191void bus_job_send_removed_signal(Job *j) {
718db961 192 int r;
c1e1601e 193
718db961 194 assert(j);
97e6a119
MS
195
196 if (!j->sent_dbus_new_signal)
197 bus_job_send_change_signal(j);
198
b39a2770 199 r = bus_foreach_bus(j->manager, j->clients, send_removed_signal, j);
718db961 200 if (r < 0)
39abcaee 201 log_debug("Failed to send job remove signal for %u: %s", j->id, strerror(-r));
c1e1601e 202}