2 This file is part of systemd.
4 Copyright 2010 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
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
9 (at your option) any later version.
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
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include "alloc-util.h"
27 #include "selinux-access.h"
28 #include "string-util.h"
30 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type
, job_type
, JobType
);
31 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_state
, job_state
, JobState
);
33 static int property_get_unit(
36 const char *interface
,
38 sd_bus_message
*reply
,
40 sd_bus_error
*error
) {
42 _cleanup_free_
char *p
= NULL
;
49 p
= unit_dbus_path(j
->unit
);
53 return sd_bus_message_append(reply
, "(so)", j
->unit
->id
, p
);
56 int bus_job_method_cancel(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
63 r
= mac_selinux_unit_access_check(j
->unit
, message
, "stop", error
);
67 /* Access is granted to the job owner */
68 if (!sd_bus_track_contains(j
->clients
, sd_bus_message_get_sender(message
))) {
70 /* And for everybody else consult PolicyKit */
71 r
= bus_verify_manage_units_async(j
->unit
->manager
, message
, error
);
75 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
78 job_finish_and_invalidate(j
, JOB_CANCELED
, true);
80 return sd_bus_reply_method_return(message
, NULL
);
83 const sd_bus_vtable bus_job_vtable
[] = {
84 SD_BUS_VTABLE_START(0),
85 SD_BUS_METHOD("Cancel", NULL
, NULL
, bus_job_method_cancel
, SD_BUS_VTABLE_UNPRIVILEGED
),
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
),
89 SD_BUS_PROPERTY("State", "s", property_get_state
, offsetof(Job
, state
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
93 static int send_new_signal(sd_bus
*bus
, void *userdata
) {
94 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
95 _cleanup_free_
char *p
= NULL
;
102 p
= job_dbus_path(j
);
106 r
= sd_bus_message_new_signal(
109 "/org/freedesktop/systemd1",
110 "org.freedesktop.systemd1.Manager",
115 r
= sd_bus_message_append(m
, "uos", j
->id
, p
, j
->unit
->id
);
119 return sd_bus_send(bus
, m
, NULL
);
122 static int send_changed_signal(sd_bus
*bus
, void *userdata
) {
123 _cleanup_free_
char *p
= NULL
;
129 p
= job_dbus_path(j
);
133 return sd_bus_emit_properties_changed(bus
, p
, "org.freedesktop.systemd1.Job", "State", NULL
);
136 void bus_job_send_change_signal(Job
*j
) {
141 if (j
->in_dbus_queue
) {
142 LIST_REMOVE(dbus_queue
, j
->manager
->dbus_job_queue
, j
);
143 j
->in_dbus_queue
= false;
146 r
= bus_foreach_bus(j
->manager
, j
->clients
, j
->sent_dbus_new_signal
? send_changed_signal
: send_new_signal
, j
);
148 log_debug_errno(r
, "Failed to send job change signal for %u: %m", j
->id
);
150 j
->sent_dbus_new_signal
= true;
153 static int send_removed_signal(sd_bus
*bus
, void *userdata
) {
154 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
155 _cleanup_free_
char *p
= NULL
;
162 p
= job_dbus_path(j
);
166 r
= sd_bus_message_new_signal(
169 "/org/freedesktop/systemd1",
170 "org.freedesktop.systemd1.Manager",
175 r
= sd_bus_message_append(m
, "uoss", j
->id
, p
, j
->unit
->id
, job_result_to_string(j
->result
));
179 return sd_bus_send(bus
, m
, NULL
);
182 void bus_job_send_removed_signal(Job
*j
) {
187 if (!j
->sent_dbus_new_signal
)
188 bus_job_send_change_signal(j
);
190 r
= bus_foreach_bus(j
->manager
, j
->clients
, send_removed_signal
, j
);
192 log_debug_errno(r
, "Failed to send job remove signal for %u: %m", j
->id
);