LCOV - code coverage report
Current view: top level - core - dbus-job.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 16 86 18.6 %
Date: 2015-07-29 18:47:03 Functions: 2 9 22.2 %

          Line data    Source code
       1             : /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
       2             : 
       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
       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
      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
      16             :   Lesser General Public License for more details.
      17             : 
      18             :   You should have received a copy of the GNU Lesser General Public License
      19             :   along with systemd; If not, see <http://www.gnu.org/licenses/>.
      20             : ***/
      21             : 
      22             : #include "log.h"
      23             : #include "sd-bus.h"
      24             : #include "selinux-access.h"
      25             : #include "job.h"
      26             : #include "dbus-job.h"
      27             : #include "dbus.h"
      28             : 
      29           0 : static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, job_type, JobType);
      30           0 : static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_state, job_state, JobState);
      31             : 
      32           0 : static 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             :                 void *userdata,
      39             :                 sd_bus_error *error) {
      40             : 
      41           0 :         _cleanup_free_ char *p = NULL;
      42           0 :         Job *j = userdata;
      43             : 
      44           0 :         assert(bus);
      45           0 :         assert(reply);
      46           0 :         assert(j);
      47             : 
      48           0 :         p = unit_dbus_path(j->unit);
      49           0 :         if (!p)
      50           0 :                 return -ENOMEM;
      51             : 
      52           0 :         return sd_bus_message_append(reply, "(so)", j->unit->id, p);
      53             : }
      54             : 
      55           0 : int bus_job_method_cancel(sd_bus_message *message, void *userdata, sd_bus_error *error) {
      56           0 :         Job *j = userdata;
      57             :         int r;
      58             : 
      59           0 :         assert(message);
      60           0 :         assert(j);
      61             : 
      62           0 :         r = mac_selinux_unit_access_check(j->unit, message, "stop", error);
      63           0 :         if (r < 0)
      64           0 :                 return r;
      65             : 
      66             :         /* Access is granted to the job owner */
      67           0 :         if (!sd_bus_track_contains(j->clients, sd_bus_message_get_sender(message))) {
      68             : 
      69             :                 /* And for everybody else consult PolicyKit */
      70           0 :                 r = bus_verify_manage_units_async(j->unit->manager, message, error);
      71           0 :                 if (r < 0)
      72           0 :                         return r;
      73           0 :                 if (r == 0)
      74           0 :                         return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
      75             :         }
      76             : 
      77           0 :         job_finish_and_invalidate(j, JOB_CANCELED, true);
      78             : 
      79           0 :         return sd_bus_reply_method_return(message, NULL);
      80             : }
      81             : 
      82             : const sd_bus_vtable bus_job_vtable[] = {
      83             :         SD_BUS_VTABLE_START(0),
      84             :         SD_BUS_METHOD("Cancel", NULL, NULL, bus_job_method_cancel, SD_BUS_VTABLE_UNPRIVILEGED),
      85             :         SD_BUS_PROPERTY("Id", "u", NULL, offsetof(Job, id), SD_BUS_VTABLE_PROPERTY_CONST),
      86             :         SD_BUS_PROPERTY("Unit", "(so)", property_get_unit, 0, SD_BUS_VTABLE_PROPERTY_CONST),
      87             :         SD_BUS_PROPERTY("JobType", "s", property_get_type, offsetof(Job, type), SD_BUS_VTABLE_PROPERTY_CONST),
      88             :         SD_BUS_PROPERTY("State", "s", property_get_state, offsetof(Job, state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
      89             :         SD_BUS_VTABLE_END
      90             : };
      91             : 
      92           0 : static int send_new_signal(sd_bus *bus, void *userdata) {
      93           0 :         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
      94           0 :         _cleanup_free_ char *p = NULL;
      95           0 :         Job *j = userdata;
      96             :         int r;
      97             : 
      98           0 :         assert(bus);
      99           0 :         assert(j);
     100             : 
     101           0 :         p = job_dbus_path(j);
     102           0 :         if (!p)
     103           0 :                 return -ENOMEM;
     104             : 
     105           0 :         r = sd_bus_message_new_signal(
     106             :                         bus,
     107             :                         &m,
     108             :                         "/org/freedesktop/systemd1",
     109             :                         "org.freedesktop.systemd1.Manager",
     110             :                         "JobNew");
     111           0 :         if (r < 0)
     112           0 :                 return r;
     113             : 
     114           0 :         r = sd_bus_message_append(m, "uos", j->id, p, j->unit->id);
     115           0 :         if (r < 0)
     116           0 :                 return r;
     117             : 
     118           0 :         return sd_bus_send(bus, m, NULL);
     119             : }
     120             : 
     121           0 : static int send_changed_signal(sd_bus *bus, void *userdata) {
     122           0 :         _cleanup_free_ char *p = NULL;
     123           0 :         Job *j = userdata;
     124             : 
     125           0 :         assert(bus);
     126           0 :         assert(j);
     127             : 
     128           0 :         p = job_dbus_path(j);
     129           0 :         if (!p)
     130           0 :                 return -ENOMEM;
     131             : 
     132           0 :         return sd_bus_emit_properties_changed(bus, p, "org.freedesktop.systemd1.Job", "State", NULL);
     133             : }
     134             : 
     135          63 : void bus_job_send_change_signal(Job *j) {
     136             :         int r;
     137             : 
     138          63 :         assert(j);
     139             : 
     140          63 :         if (j->in_dbus_queue) {
     141          63 :                 LIST_REMOVE(dbus_queue, j->manager->dbus_job_queue, j);
     142          63 :                 j->in_dbus_queue = false;
     143             :         }
     144             : 
     145          63 :         r = bus_foreach_bus(j->manager, j->clients, j->sent_dbus_new_signal ? send_changed_signal : send_new_signal, j);
     146          63 :         if (r < 0)
     147           0 :                 log_debug_errno(r, "Failed to send job change signal for %u: %m", j->id);
     148             : 
     149          63 :         j->sent_dbus_new_signal = true;
     150          63 : }
     151             : 
     152           0 : static int send_removed_signal(sd_bus *bus, void *userdata) {
     153           0 :         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
     154           0 :         _cleanup_free_ char *p = NULL;
     155           0 :         Job *j = userdata;
     156             :         int r;
     157             : 
     158           0 :         assert(bus);
     159           0 :         assert(j);
     160             : 
     161           0 :         p = job_dbus_path(j);
     162           0 :         if (!p)
     163           0 :                 return -ENOMEM;
     164             : 
     165           0 :         r = sd_bus_message_new_signal(
     166             :                         bus,
     167             :                         &m,
     168             :                         "/org/freedesktop/systemd1",
     169             :                         "org.freedesktop.systemd1.Manager",
     170             :                         "JobRemoved");
     171           0 :         if (r < 0)
     172           0 :                 return r;
     173             : 
     174           0 :         r = sd_bus_message_append(m, "uoss", j->id, p, j->unit->id, job_result_to_string(j->result));
     175           0 :         if (r < 0)
     176           0 :                 return r;
     177             : 
     178           0 :         return sd_bus_send(bus, m, NULL);
     179             : }
     180             : 
     181          63 : void bus_job_send_removed_signal(Job *j) {
     182             :         int r;
     183             : 
     184          63 :         assert(j);
     185             : 
     186          63 :         if (!j->sent_dbus_new_signal)
     187          63 :                 bus_job_send_change_signal(j);
     188             : 
     189          63 :         r = bus_foreach_bus(j->manager, j->clients, send_removed_signal, j);
     190          63 :         if (r < 0)
     191           0 :                 log_debug_errno(r, "Failed to send job remove signal for %u: %m", j->id);
     192          63 : }

Generated by: LCOV version 1.11