LCOV - code coverage report
Current view: top level - core - dbus-unit.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 26 1055 2.5 %
Date: 2019-08-23 13:36:53 Functions: 4 75 5.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 17 1034 1.6 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include "sd-bus.h"
       4                 :            : 
       5                 :            : #include "alloc-util.h"
       6                 :            : #include "bpf-firewall.h"
       7                 :            : #include "bus-common-errors.h"
       8                 :            : #include "cgroup-util.h"
       9                 :            : #include "condition.h"
      10                 :            : #include "dbus-job.h"
      11                 :            : #include "dbus-unit.h"
      12                 :            : #include "dbus-util.h"
      13                 :            : #include "dbus.h"
      14                 :            : #include "fd-util.h"
      15                 :            : #include "install.h"
      16                 :            : #include "locale-util.h"
      17                 :            : #include "log.h"
      18                 :            : #include "path-util.h"
      19                 :            : #include "process-util.h"
      20                 :            : #include "selinux-access.h"
      21                 :            : #include "signal-util.h"
      22                 :            : #include "special.h"
      23                 :            : #include "string-table.h"
      24                 :            : #include "string-util.h"
      25                 :            : #include "strv.h"
      26                 :            : #include "user-util.h"
      27                 :            : #include "web-util.h"
      28                 :            : 
      29                 :          0 : static bool unit_can_start_refuse_manual(Unit *u) {
      30   [ #  #  #  # ]:          0 :         return unit_can_start(u) && !u->refuse_manual_start;
      31                 :            : }
      32                 :            : 
      33                 :          0 : static bool unit_can_stop_refuse_manual(Unit *u) {
      34   [ #  #  #  # ]:          0 :         return unit_can_stop(u) && !u->refuse_manual_stop;
      35                 :            : }
      36                 :            : 
      37                 :          0 : static bool unit_can_isolate_refuse_manual(Unit *u) {
      38   [ #  #  #  # ]:          0 :         return unit_can_isolate(u) && !u->refuse_manual_start;
      39                 :            : }
      40                 :            : 
      41   [ #  #  #  #  :          0 : static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_collect_mode, collect_mode, CollectMode);
                   #  # ]
      42   [ #  #  #  #  :          0 : static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_load_state, unit_load_state, UnitLoadState);
                   #  # ]
      43   [ #  #  #  #  :          0 : static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_job_mode, job_mode, JobMode);
                   #  # ]
      44   [ #  #  #  #  :          0 : static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_emergency_action, emergency_action, EmergencyAction);
                   #  # ]
      45   [ #  #  #  #  :          0 : static BUS_DEFINE_PROPERTY_GET(property_get_description, "s", Unit, unit_description);
                   #  # ]
      46   [ #  #  #  #  :          0 : static BUS_DEFINE_PROPERTY_GET2(property_get_active_state, "s", Unit, unit_active_state, unit_active_state_to_string);
                   #  # ]
      47   [ #  #  #  #  :          0 : static BUS_DEFINE_PROPERTY_GET(property_get_sub_state, "s", Unit, unit_sub_state_to_string);
                   #  # ]
      48   [ #  #  #  #  :          0 : static BUS_DEFINE_PROPERTY_GET2(property_get_unit_file_state, "s", Unit, unit_get_unit_file_state, unit_file_state_to_string);
                   #  # ]
      49   [ #  #  #  #  :          0 : static BUS_DEFINE_PROPERTY_GET(property_get_can_reload, "b", Unit, unit_can_reload);
                   #  # ]
      50   [ #  #  #  #  :          0 : static BUS_DEFINE_PROPERTY_GET(property_get_can_start, "b", Unit, unit_can_start_refuse_manual);
                   #  # ]
      51   [ #  #  #  #  :          0 : static BUS_DEFINE_PROPERTY_GET(property_get_can_stop, "b", Unit, unit_can_stop_refuse_manual);
                   #  # ]
      52   [ #  #  #  #  :          0 : static BUS_DEFINE_PROPERTY_GET(property_get_can_isolate, "b", Unit, unit_can_isolate_refuse_manual);
                   #  # ]
      53   [ #  #  #  #  :          0 : static BUS_DEFINE_PROPERTY_GET(property_get_need_daemon_reload, "b", Unit, unit_need_daemon_reload);
                   #  # ]
      54   [ #  #  #  # ]:          0 : static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_empty_strv, "as", 0);
      55                 :            : 
      56                 :          0 : static int property_get_can_clean(
      57                 :            :                 sd_bus *bus,
      58                 :            :                 const char *path,
      59                 :            :                 const char *interface,
      60                 :            :                 const char *property,
      61                 :            :                 sd_bus_message *reply,
      62                 :            :                 void *userdata,
      63                 :            :                 sd_bus_error *error) {
      64                 :            : 
      65                 :          0 :         Unit *u = userdata;
      66                 :            :         ExecCleanMask mask;
      67                 :            :         int r;
      68                 :            : 
      69         [ #  # ]:          0 :         assert(bus);
      70         [ #  # ]:          0 :         assert(reply);
      71                 :            : 
      72                 :          0 :         r = unit_can_clean(u, &mask);
      73         [ #  # ]:          0 :         if (r < 0)
      74                 :          0 :                 return r;
      75                 :            : 
      76                 :          0 :         r = sd_bus_message_open_container(reply, 'a', "s");
      77         [ #  # ]:          0 :         if (r < 0)
      78                 :          0 :                 return r;
      79                 :            : 
      80         [ #  # ]:          0 :         for (ExecDirectoryType t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) {
      81         [ #  # ]:          0 :                 if (!FLAGS_SET(mask, 1U << t))
      82                 :          0 :                         continue;
      83                 :            : 
      84                 :          0 :                 r = sd_bus_message_append(reply, "s", exec_resource_type_to_string(t));
      85         [ #  # ]:          0 :                 if (r < 0)
      86                 :          0 :                         return r;
      87                 :            :         }
      88                 :            : 
      89                 :          0 :         return sd_bus_message_close_container(reply);
      90                 :            : }
      91                 :            : 
      92                 :          0 : static int property_get_names(
      93                 :            :                 sd_bus *bus,
      94                 :            :                 const char *path,
      95                 :            :                 const char *interface,
      96                 :            :                 const char *property,
      97                 :            :                 sd_bus_message *reply,
      98                 :            :                 void *userdata,
      99                 :            :                 sd_bus_error *error) {
     100                 :            : 
     101                 :          0 :         Set **s = userdata;
     102                 :            :         Iterator i;
     103                 :            :         const char *t;
     104                 :            :         int r;
     105                 :            : 
     106         [ #  # ]:          0 :         assert(bus);
     107         [ #  # ]:          0 :         assert(reply);
     108         [ #  # ]:          0 :         assert(s);
     109                 :            : 
     110                 :          0 :         r = sd_bus_message_open_container(reply, 'a', "s");
     111         [ #  # ]:          0 :         if (r < 0)
     112                 :          0 :                 return r;
     113                 :            : 
     114         [ #  # ]:          0 :         SET_FOREACH(t, *s, i) {
     115                 :          0 :                 r = sd_bus_message_append(reply, "s", t);
     116         [ #  # ]:          0 :                 if (r < 0)
     117                 :          0 :                         return r;
     118                 :            :         }
     119                 :            : 
     120                 :          0 :         return sd_bus_message_close_container(reply);
     121                 :            : }
     122                 :            : 
     123                 :          0 : static int property_get_following(
     124                 :            :                 sd_bus *bus,
     125                 :            :                 const char *path,
     126                 :            :                 const char *interface,
     127                 :            :                 const char *property,
     128                 :            :                 sd_bus_message *reply,
     129                 :            :                 void *userdata,
     130                 :            :                 sd_bus_error *error) {
     131                 :            : 
     132                 :          0 :         Unit *u = userdata, *f;
     133                 :            : 
     134         [ #  # ]:          0 :         assert(bus);
     135         [ #  # ]:          0 :         assert(reply);
     136         [ #  # ]:          0 :         assert(u);
     137                 :            : 
     138                 :          0 :         f = unit_following(u);
     139         [ #  # ]:          0 :         return sd_bus_message_append(reply, "s", f ? f->id : NULL);
     140                 :            : }
     141                 :            : 
     142                 :          0 : static int property_get_dependencies(
     143                 :            :                 sd_bus *bus,
     144                 :            :                 const char *path,
     145                 :            :                 const char *interface,
     146                 :            :                 const char *property,
     147                 :            :                 sd_bus_message *reply,
     148                 :            :                 void *userdata,
     149                 :            :                 sd_bus_error *error) {
     150                 :            : 
     151                 :          0 :         Hashmap **h = userdata;
     152                 :            :         Iterator j;
     153                 :            :         Unit *u;
     154                 :            :         void *v;
     155                 :            :         int r;
     156                 :            : 
     157         [ #  # ]:          0 :         assert(bus);
     158         [ #  # ]:          0 :         assert(reply);
     159         [ #  # ]:          0 :         assert(h);
     160                 :            : 
     161                 :          0 :         r = sd_bus_message_open_container(reply, 'a', "s");
     162         [ #  # ]:          0 :         if (r < 0)
     163                 :          0 :                 return r;
     164                 :            : 
     165         [ #  # ]:          0 :         HASHMAP_FOREACH_KEY(v, u, *h, j) {
     166                 :          0 :                 r = sd_bus_message_append(reply, "s", u->id);
     167         [ #  # ]:          0 :                 if (r < 0)
     168                 :          0 :                         return r;
     169                 :            :         }
     170                 :            : 
     171                 :          0 :         return sd_bus_message_close_container(reply);
     172                 :            : }
     173                 :            : 
     174                 :          0 : static int property_get_requires_mounts_for(
     175                 :            :                 sd_bus *bus,
     176                 :            :                 const char *path,
     177                 :            :                 const char *interface,
     178                 :            :                 const char *property,
     179                 :            :                 sd_bus_message *reply,
     180                 :            :                 void *userdata,
     181                 :            :                 sd_bus_error *error) {
     182                 :            : 
     183                 :          0 :         Hashmap **h = userdata;
     184                 :            :         const char *p;
     185                 :            :         Iterator j;
     186                 :            :         void *v;
     187                 :            :         int r;
     188                 :            : 
     189         [ #  # ]:          0 :         assert(bus);
     190         [ #  # ]:          0 :         assert(reply);
     191         [ #  # ]:          0 :         assert(h);
     192                 :            : 
     193                 :          0 :         r = sd_bus_message_open_container(reply, 'a', "s");
     194         [ #  # ]:          0 :         if (r < 0)
     195                 :          0 :                 return r;
     196                 :            : 
     197         [ #  # ]:          0 :         HASHMAP_FOREACH_KEY(v, p, *h, j) {
     198                 :          0 :                 r = sd_bus_message_append(reply, "s", p);
     199         [ #  # ]:          0 :                 if (r < 0)
     200                 :          0 :                         return r;
     201                 :            :         }
     202                 :            : 
     203                 :          0 :         return sd_bus_message_close_container(reply);
     204                 :            : }
     205                 :            : 
     206                 :          0 : static int property_get_unit_file_preset(
     207                 :            :                 sd_bus *bus,
     208                 :            :                 const char *path,
     209                 :            :                 const char *interface,
     210                 :            :                 const char *property,
     211                 :            :                 sd_bus_message *reply,
     212                 :            :                 void *userdata,
     213                 :            :                 sd_bus_error *error) {
     214                 :            : 
     215                 :          0 :         Unit *u = userdata;
     216                 :            :         int r;
     217                 :            : 
     218         [ #  # ]:          0 :         assert(bus);
     219         [ #  # ]:          0 :         assert(reply);
     220         [ #  # ]:          0 :         assert(u);
     221                 :            : 
     222                 :          0 :         r = unit_get_unit_file_preset(u);
     223                 :            : 
     224         [ #  # ]:          0 :         return sd_bus_message_append(reply, "s",
     225                 :            :                                      r < 0 ? NULL:
     226         [ #  # ]:          0 :                                      r > 0 ? "enabled" : "disabled");
     227                 :            : }
     228                 :            : 
     229                 :          0 : static int property_get_job(
     230                 :            :                 sd_bus *bus,
     231                 :            :                 const char *path,
     232                 :            :                 const char *interface,
     233                 :            :                 const char *property,
     234                 :            :                 sd_bus_message *reply,
     235                 :            :                 void *userdata,
     236                 :            :                 sd_bus_error *error) {
     237                 :            : 
     238                 :          0 :         _cleanup_free_ char *p = NULL;
     239                 :          0 :         Job **j = userdata;
     240                 :            : 
     241         [ #  # ]:          0 :         assert(bus);
     242         [ #  # ]:          0 :         assert(reply);
     243         [ #  # ]:          0 :         assert(j);
     244                 :            : 
     245         [ #  # ]:          0 :         if (!*j)
     246                 :          0 :                 return sd_bus_message_append(reply, "(uo)", 0, "/");
     247                 :            : 
     248                 :          0 :         p = job_dbus_path(*j);
     249         [ #  # ]:          0 :         if (!p)
     250                 :          0 :                 return -ENOMEM;
     251                 :            : 
     252                 :          0 :         return sd_bus_message_append(reply, "(uo)", (*j)->id, p);
     253                 :            : }
     254                 :            : 
     255                 :          0 : static int property_get_conditions(
     256                 :            :                 sd_bus *bus,
     257                 :            :                 const char *path,
     258                 :            :                 const char *interface,
     259                 :            :                 const char *property,
     260                 :            :                 sd_bus_message *reply,
     261                 :            :                 void *userdata,
     262                 :            :                 sd_bus_error *error) {
     263                 :            : 
     264                 :          0 :         const char *(*to_string)(ConditionType type) = NULL;
     265                 :          0 :         Condition **list = userdata, *c;
     266                 :            :         int r;
     267                 :            : 
     268         [ #  # ]:          0 :         assert(bus);
     269         [ #  # ]:          0 :         assert(reply);
     270         [ #  # ]:          0 :         assert(list);
     271                 :            : 
     272         [ #  # ]:          0 :         to_string = streq(property, "Asserts") ? assert_type_to_string : condition_type_to_string;
     273                 :            : 
     274                 :          0 :         r = sd_bus_message_open_container(reply, 'a', "(sbbsi)");
     275         [ #  # ]:          0 :         if (r < 0)
     276                 :          0 :                 return r;
     277                 :            : 
     278         [ #  # ]:          0 :         LIST_FOREACH(conditions, c, *list) {
     279                 :            :                 int tristate;
     280                 :            : 
     281                 :          0 :                 tristate =
     282         [ #  # ]:          0 :                         c->result == CONDITION_UNTESTED ? 0 :
     283         [ #  # ]:          0 :                         c->result == CONDITION_SUCCEEDED ? 1 : -1;
     284                 :            : 
     285                 :          0 :                 r = sd_bus_message_append(reply, "(sbbsi)",
     286                 :          0 :                                           to_string(c->type),
     287                 :          0 :                                           c->trigger, c->negate,
     288                 :            :                                           c->parameter, tristate);
     289         [ #  # ]:          0 :                 if (r < 0)
     290                 :          0 :                         return r;
     291                 :            : 
     292                 :            :         }
     293                 :            : 
     294                 :          0 :         return sd_bus_message_close_container(reply);
     295                 :            : }
     296                 :            : 
     297                 :          0 : static int property_get_load_error(
     298                 :            :                 sd_bus *bus,
     299                 :            :                 const char *path,
     300                 :            :                 const char *interface,
     301                 :            :                 const char *property,
     302                 :            :                 sd_bus_message *reply,
     303                 :            :                 void *userdata,
     304                 :            :                 sd_bus_error *error) {
     305                 :            : 
     306                 :          0 :         _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
     307                 :          0 :         Unit *u = userdata;
     308                 :            :         int r;
     309                 :            : 
     310         [ #  # ]:          0 :         assert(bus);
     311         [ #  # ]:          0 :         assert(reply);
     312         [ #  # ]:          0 :         assert(u);
     313                 :            : 
     314                 :          0 :         r = bus_unit_validate_load_state(u, &e);
     315         [ #  # ]:          0 :         if (r < 0)
     316                 :          0 :                 return sd_bus_message_append(reply, "(ss)", e.name, e.message);
     317                 :            : 
     318                 :          0 :         return sd_bus_message_append(reply, "(ss)", NULL, NULL);
     319                 :            : }
     320                 :            : 
     321                 :          0 : static int bus_verify_manage_units_async_full(
     322                 :            :                 Unit *u,
     323                 :            :                 const char *verb,
     324                 :            :                 int capability,
     325                 :            :                 const char *polkit_message,
     326                 :            :                 bool interactive,
     327                 :            :                 sd_bus_message *call,
     328                 :            :                 sd_bus_error *error) {
     329                 :            : 
     330                 :          0 :         const char *details[9] = {
     331                 :          0 :                 "unit", u->id,
     332                 :            :                 "verb", verb,
     333                 :            :         };
     334                 :            : 
     335         [ #  # ]:          0 :         if (polkit_message) {
     336                 :          0 :                 details[4] = "polkit.message";
     337                 :          0 :                 details[5] = polkit_message;
     338                 :          0 :                 details[6] = "polkit.gettext_domain";
     339                 :          0 :                 details[7] = GETTEXT_PACKAGE;
     340                 :            :         }
     341                 :            : 
     342                 :          0 :         return bus_verify_polkit_async(
     343                 :            :                         call,
     344                 :            :                         capability,
     345                 :            :                         "org.freedesktop.systemd1.manage-units",
     346                 :            :                         details,
     347                 :            :                         interactive,
     348                 :            :                         UID_INVALID,
     349                 :          0 :                         &u->manager->polkit_registry,
     350                 :            :                         error);
     351                 :            : }
     352                 :            : 
     353                 :            : static const char *const polkit_message_for_job[_JOB_TYPE_MAX] = {
     354                 :            :         [JOB_START]       = N_("Authentication is required to start '$(unit)'."),
     355                 :            :         [JOB_STOP]        = N_("Authentication is required to stop '$(unit)'."),
     356                 :            :         [JOB_RELOAD]      = N_("Authentication is required to reload '$(unit)'."),
     357                 :            :         [JOB_RESTART]     = N_("Authentication is required to restart '$(unit)'."),
     358                 :            :         [JOB_TRY_RESTART] = N_("Authentication is required to restart '$(unit)'."),
     359                 :            : };
     360                 :            : 
     361                 :          0 : int bus_unit_method_start_generic(
     362                 :            :                 sd_bus_message *message,
     363                 :            :                 Unit *u,
     364                 :            :                 JobType job_type,
     365                 :            :                 bool reload_if_possible,
     366                 :            :                 sd_bus_error *error) {
     367                 :            : 
     368                 :            :         const char *smode, *verb;
     369                 :            :         JobMode mode;
     370                 :            :         int r;
     371                 :            : 
     372         [ #  # ]:          0 :         assert(message);
     373         [ #  # ]:          0 :         assert(u);
     374   [ #  #  #  # ]:          0 :         assert(job_type >= 0 && job_type < _JOB_TYPE_MAX);
     375                 :            : 
     376                 :          0 :         r = mac_selinux_unit_access_check(
     377                 :            :                         u, message,
     378                 :            :                         job_type_to_access_method(job_type),
     379                 :            :                         error);
     380         [ #  # ]:          0 :         if (r < 0)
     381                 :          0 :                 return r;
     382                 :            : 
     383                 :          0 :         r = sd_bus_message_read(message, "s", &smode);
     384         [ #  # ]:          0 :         if (r < 0)
     385                 :          0 :                 return r;
     386                 :            : 
     387                 :          0 :         mode = job_mode_from_string(smode);
     388         [ #  # ]:          0 :         if (mode < 0)
     389                 :          0 :                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s invalid", smode);
     390                 :            : 
     391         [ #  # ]:          0 :         if (reload_if_possible)
     392   [ #  #  #  #  :          0 :                 verb = strjoina("reload-or-", job_type_to_string(job_type));
          #  #  #  #  #  
                #  #  # ]
     393                 :            :         else
     394                 :          0 :                 verb = job_type_to_string(job_type);
     395                 :            : 
     396                 :          0 :         r = bus_verify_manage_units_async_full(
     397                 :            :                         u,
     398                 :            :                         verb,
     399                 :            :                         CAP_SYS_ADMIN,
     400                 :            :                         polkit_message_for_job[job_type],
     401                 :            :                         true,
     402                 :            :                         message,
     403                 :            :                         error);
     404         [ #  # ]:          0 :         if (r < 0)
     405                 :          0 :                 return r;
     406         [ #  # ]:          0 :         if (r == 0)
     407                 :          0 :                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
     408                 :            : 
     409                 :          0 :         return bus_unit_queue_job(message, u, job_type, mode,
     410                 :            :                                   reload_if_possible ? BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE : 0, error);
     411                 :            : }
     412                 :            : 
     413                 :          0 : static int method_start(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     414                 :          0 :         return bus_unit_method_start_generic(message, userdata, JOB_START, false, error);
     415                 :            : }
     416                 :            : 
     417                 :          0 : static int method_stop(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     418                 :          0 :         return bus_unit_method_start_generic(message, userdata, JOB_STOP, false, error);
     419                 :            : }
     420                 :            : 
     421                 :          0 : static int method_reload(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     422                 :          0 :         return bus_unit_method_start_generic(message, userdata, JOB_RELOAD, false, error);
     423                 :            : }
     424                 :            : 
     425                 :          0 : static int method_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     426                 :          0 :         return bus_unit_method_start_generic(message, userdata, JOB_RESTART, false, error);
     427                 :            : }
     428                 :            : 
     429                 :          0 : static int method_try_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     430                 :          0 :         return bus_unit_method_start_generic(message, userdata, JOB_TRY_RESTART, false, error);
     431                 :            : }
     432                 :            : 
     433                 :          0 : static int method_reload_or_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     434                 :          0 :         return bus_unit_method_start_generic(message, userdata, JOB_RESTART, true, error);
     435                 :            : }
     436                 :            : 
     437                 :          0 : static int method_reload_or_try_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     438                 :          0 :         return bus_unit_method_start_generic(message, userdata, JOB_TRY_RESTART, true, error);
     439                 :            : }
     440                 :            : 
     441                 :          0 : int bus_unit_method_enqueue_job(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     442                 :          0 :         BusUnitQueueFlags flags = BUS_UNIT_QUEUE_VERBOSE_REPLY;
     443                 :            :         const char *jtype, *smode;
     444                 :          0 :         Unit *u = userdata;
     445                 :            :         JobType type;
     446                 :            :         JobMode mode;
     447                 :            :         int r;
     448                 :            : 
     449         [ #  # ]:          0 :         assert(message);
     450         [ #  # ]:          0 :         assert(u);
     451                 :            : 
     452                 :          0 :         r = sd_bus_message_read(message, "ss", &jtype, &smode);
     453         [ #  # ]:          0 :         if (r < 0)
     454                 :          0 :                 return r;
     455                 :            : 
     456                 :            :         /* Parse the two magic reload types "reload-or-…" manually */
     457         [ #  # ]:          0 :         if (streq(jtype, "reload-or-restart")) {
     458                 :          0 :                 type = JOB_RESTART;
     459                 :          0 :                 flags |= BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE;
     460         [ #  # ]:          0 :         } else if (streq(jtype, "reload-or-try-restart")) {
     461                 :          0 :                 type = JOB_TRY_RESTART;
     462                 :          0 :                 flags |= BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE;
     463                 :            :         } else {
     464                 :            :                 /* And the rest generically */
     465                 :          0 :                 type = job_type_from_string(jtype);
     466         [ #  # ]:          0 :                 if (type < 0)
     467                 :          0 :                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job type %s invalid", jtype);
     468                 :            :         }
     469                 :            : 
     470                 :          0 :         mode = job_mode_from_string(smode);
     471         [ #  # ]:          0 :         if (mode < 0)
     472                 :          0 :                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s invalid", smode);
     473                 :            : 
     474                 :          0 :         r = mac_selinux_unit_access_check(
     475                 :            :                         u, message,
     476                 :            :                         job_type_to_access_method(type),
     477                 :            :                         error);
     478         [ #  # ]:          0 :         if (r < 0)
     479                 :          0 :                 return r;
     480                 :            : 
     481                 :          0 :         r = bus_verify_manage_units_async_full(
     482                 :            :                         u,
     483                 :            :                         jtype,
     484                 :            :                         CAP_SYS_ADMIN,
     485                 :            :                         polkit_message_for_job[type],
     486                 :            :                         true,
     487                 :            :                         message,
     488                 :            :                         error);
     489         [ #  # ]:          0 :         if (r < 0)
     490                 :          0 :                 return r;
     491         [ #  # ]:          0 :         if (r == 0)
     492                 :          0 :                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
     493                 :            : 
     494                 :          0 :         return bus_unit_queue_job(message, u, type, mode, flags, error);
     495                 :            : }
     496                 :            : 
     497                 :          0 : int bus_unit_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     498                 :          0 :         Unit *u = userdata;
     499                 :            :         const char *swho;
     500                 :            :         int32_t signo;
     501                 :            :         KillWho who;
     502                 :            :         int r;
     503                 :            : 
     504         [ #  # ]:          0 :         assert(message);
     505         [ #  # ]:          0 :         assert(u);
     506                 :            : 
     507                 :          0 :         r = mac_selinux_unit_access_check(u, message, "stop", error);
     508         [ #  # ]:          0 :         if (r < 0)
     509                 :          0 :                 return r;
     510                 :            : 
     511                 :          0 :         r = sd_bus_message_read(message, "si", &swho, &signo);
     512         [ #  # ]:          0 :         if (r < 0)
     513                 :          0 :                 return r;
     514                 :            : 
     515         [ #  # ]:          0 :         if (isempty(swho))
     516                 :          0 :                 who = KILL_ALL;
     517                 :            :         else {
     518                 :          0 :                 who = kill_who_from_string(swho);
     519         [ #  # ]:          0 :                 if (who < 0)
     520                 :          0 :                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid who argument %s", swho);
     521                 :            :         }
     522                 :            : 
     523         [ #  # ]:          0 :         if (!SIGNAL_VALID(signo))
     524                 :          0 :                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Signal number out of range.");
     525                 :            : 
     526                 :          0 :         r = bus_verify_manage_units_async_full(
     527                 :            :                         u,
     528                 :            :                         "kill",
     529                 :            :                         CAP_KILL,
     530                 :            :                         N_("Authentication is required to send a UNIX signal to the processes of '$(unit)'."),
     531                 :            :                         true,
     532                 :            :                         message,
     533                 :            :                         error);
     534         [ #  # ]:          0 :         if (r < 0)
     535                 :          0 :                 return r;
     536         [ #  # ]:          0 :         if (r == 0)
     537                 :          0 :                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
     538                 :            : 
     539                 :          0 :         r = unit_kill(u, who, signo, error);
     540         [ #  # ]:          0 :         if (r < 0)
     541                 :          0 :                 return r;
     542                 :            : 
     543                 :          0 :         return sd_bus_reply_method_return(message, NULL);
     544                 :            : }
     545                 :            : 
     546                 :          0 : int bus_unit_method_reset_failed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     547                 :          0 :         Unit *u = userdata;
     548                 :            :         int r;
     549                 :            : 
     550         [ #  # ]:          0 :         assert(message);
     551         [ #  # ]:          0 :         assert(u);
     552                 :            : 
     553                 :          0 :         r = mac_selinux_unit_access_check(u, message, "reload", error);
     554         [ #  # ]:          0 :         if (r < 0)
     555                 :          0 :                 return r;
     556                 :            : 
     557                 :          0 :         r = bus_verify_manage_units_async_full(
     558                 :            :                         u,
     559                 :            :                         "reset-failed",
     560                 :            :                         CAP_SYS_ADMIN,
     561                 :            :                         N_("Authentication is required to reset the \"failed\" state of '$(unit)'."),
     562                 :            :                         true,
     563                 :            :                         message,
     564                 :            :                         error);
     565         [ #  # ]:          0 :         if (r < 0)
     566                 :          0 :                 return r;
     567         [ #  # ]:          0 :         if (r == 0)
     568                 :          0 :                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
     569                 :            : 
     570                 :          0 :         unit_reset_failed(u);
     571                 :            : 
     572                 :          0 :         return sd_bus_reply_method_return(message, NULL);
     573                 :            : }
     574                 :            : 
     575                 :          0 : int bus_unit_method_set_properties(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     576                 :          0 :         Unit *u = userdata;
     577                 :            :         int runtime, r;
     578                 :            : 
     579         [ #  # ]:          0 :         assert(message);
     580         [ #  # ]:          0 :         assert(u);
     581                 :            : 
     582                 :          0 :         r = mac_selinux_unit_access_check(u, message, "start", error);
     583         [ #  # ]:          0 :         if (r < 0)
     584                 :          0 :                 return r;
     585                 :            : 
     586                 :          0 :         r = sd_bus_message_read(message, "b", &runtime);
     587         [ #  # ]:          0 :         if (r < 0)
     588                 :          0 :                 return r;
     589                 :            : 
     590                 :          0 :         r = bus_verify_manage_units_async_full(
     591                 :            :                         u,
     592                 :            :                         "set-property",
     593                 :            :                         CAP_SYS_ADMIN,
     594                 :            :                         N_("Authentication is required to set properties on '$(unit)'."),
     595                 :            :                         true,
     596                 :            :                         message,
     597                 :            :                         error);
     598         [ #  # ]:          0 :         if (r < 0)
     599                 :          0 :                 return r;
     600         [ #  # ]:          0 :         if (r == 0)
     601                 :          0 :                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
     602                 :            : 
     603         [ #  # ]:          0 :         r = bus_unit_set_properties(u, message, runtime ? UNIT_RUNTIME : UNIT_PERSISTENT, true, error);
     604         [ #  # ]:          0 :         if (r < 0)
     605                 :          0 :                 return r;
     606                 :            : 
     607                 :          0 :         return sd_bus_reply_method_return(message, NULL);
     608                 :            : }
     609                 :            : 
     610                 :          0 : int bus_unit_method_ref(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     611                 :          0 :         Unit *u = userdata;
     612                 :            :         int r;
     613                 :            : 
     614         [ #  # ]:          0 :         assert(message);
     615         [ #  # ]:          0 :         assert(u);
     616                 :            : 
     617                 :          0 :         r = mac_selinux_unit_access_check(u, message, "start", error);
     618         [ #  # ]:          0 :         if (r < 0)
     619                 :          0 :                 return r;
     620                 :            : 
     621                 :          0 :         r = bus_verify_manage_units_async_full(
     622                 :            :                         u,
     623                 :            :                         "ref",
     624                 :            :                         CAP_SYS_ADMIN,
     625                 :            :                         NULL,
     626                 :            :                         false,
     627                 :            :                         message,
     628                 :            :                         error);
     629         [ #  # ]:          0 :         if (r < 0)
     630                 :          0 :                 return r;
     631         [ #  # ]:          0 :         if (r == 0)
     632                 :          0 :                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
     633                 :            : 
     634                 :          0 :         r = bus_unit_track_add_sender(u, message);
     635         [ #  # ]:          0 :         if (r < 0)
     636                 :          0 :                 return r;
     637                 :            : 
     638                 :          0 :         return sd_bus_reply_method_return(message, NULL);
     639                 :            : }
     640                 :            : 
     641                 :          0 : int bus_unit_method_unref(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     642                 :          0 :         Unit *u = userdata;
     643                 :            :         int r;
     644                 :            : 
     645         [ #  # ]:          0 :         assert(message);
     646         [ #  # ]:          0 :         assert(u);
     647                 :            : 
     648                 :          0 :         r = bus_unit_track_remove_sender(u, message);
     649         [ #  # ]:          0 :         if (r == -EUNATCH)
     650                 :          0 :                 return sd_bus_error_setf(error, BUS_ERROR_NOT_REFERENCED, "Unit has not been referenced yet.");
     651         [ #  # ]:          0 :         if (r < 0)
     652                 :          0 :                 return r;
     653                 :            : 
     654                 :          0 :         return sd_bus_reply_method_return(message, NULL);
     655                 :            : }
     656                 :            : 
     657                 :          0 : int bus_unit_method_clean(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     658                 :          0 :         ExecCleanMask mask = 0;
     659                 :          0 :         Unit *u = userdata;
     660                 :            :         int r;
     661                 :            : 
     662         [ #  # ]:          0 :         assert(message);
     663         [ #  # ]:          0 :         assert(u);
     664                 :            : 
     665                 :          0 :         r = mac_selinux_unit_access_check(u, message, "stop", error);
     666         [ #  # ]:          0 :         if (r < 0)
     667                 :          0 :                 return r;
     668                 :            : 
     669                 :          0 :         r = sd_bus_message_enter_container(message, 'a', "s");
     670         [ #  # ]:          0 :         if (r < 0)
     671                 :          0 :                 return r;
     672                 :            : 
     673                 :          0 :         for (;;) {
     674                 :            :                 const char *i;
     675                 :            : 
     676                 :          0 :                 r = sd_bus_message_read(message, "s", &i);
     677         [ #  # ]:          0 :                 if (r < 0)
     678                 :          0 :                         return r;
     679         [ #  # ]:          0 :                 if (r == 0)
     680                 :          0 :                         break;
     681                 :            : 
     682         [ #  # ]:          0 :                 if (streq(i, "all"))
     683                 :          0 :                         mask |= EXEC_CLEAN_ALL;
     684                 :            :                 else {
     685                 :            :                         ExecDirectoryType t;
     686                 :            : 
     687                 :          0 :                         t = exec_resource_type_from_string(i);
     688         [ #  # ]:          0 :                         if (t < 0)
     689                 :          0 :                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid resource type: %s", i);
     690                 :            : 
     691                 :          0 :                         mask |= 1U << t;
     692                 :            :                 }
     693                 :            :         }
     694                 :            : 
     695                 :          0 :         r = sd_bus_message_exit_container(message);
     696         [ #  # ]:          0 :         if (r < 0)
     697                 :          0 :                 return r;
     698                 :            : 
     699                 :          0 :         r = bus_verify_manage_units_async_full(
     700                 :            :                         u,
     701                 :            :                         "clean",
     702                 :            :                         CAP_DAC_OVERRIDE,
     703                 :            :                         N_("Authentication is required to delete files and directories associated with '$(unit)'."),
     704                 :            :                         true,
     705                 :            :                         message,
     706                 :            :                         error);
     707         [ #  # ]:          0 :         if (r < 0)
     708                 :          0 :                 return r;
     709         [ #  # ]:          0 :         if (r == 0)
     710                 :          0 :                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
     711                 :            : 
     712                 :          0 :         r = unit_clean(u, mask);
     713         [ #  # ]:          0 :         if (r == -EOPNOTSUPP)
     714                 :          0 :                 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Unit '%s' does not supporting cleaning.", u->id);
     715         [ #  # ]:          0 :         if (r == -EUNATCH)
     716                 :          0 :                 return sd_bus_error_setf(error, BUS_ERROR_NOTHING_TO_CLEAN, "No matching resources found.");
     717         [ #  # ]:          0 :         if (r == -EBUSY)
     718                 :          0 :                 return sd_bus_error_setf(error, BUS_ERROR_UNIT_BUSY, "Unit is not inactive or has pending job.");
     719         [ #  # ]:          0 :         if (r < 0)
     720                 :          0 :                 return r;
     721                 :            : 
     722                 :          0 :         return sd_bus_reply_method_return(message, NULL);
     723                 :            : }
     724                 :            : 
     725                 :          0 : static int property_get_refs(
     726                 :            :                 sd_bus *bus,
     727                 :            :                 const char *path,
     728                 :            :                 const char *interface,
     729                 :            :                 const char *property,
     730                 :            :                 sd_bus_message *reply,
     731                 :            :                 void *userdata,
     732                 :            :                 sd_bus_error *error) {
     733                 :            : 
     734                 :          0 :         Unit *u = userdata;
     735                 :            :         const char *i;
     736                 :            :         int r;
     737                 :            : 
     738         [ #  # ]:          0 :         assert(bus);
     739         [ #  # ]:          0 :         assert(reply);
     740                 :            : 
     741                 :          0 :         r = sd_bus_message_open_container(reply, 'a', "s");
     742         [ #  # ]:          0 :         if (r < 0)
     743                 :          0 :                 return r;
     744                 :            : 
     745         [ #  # ]:          0 :         for (i = sd_bus_track_first(u->bus_track); i; i = sd_bus_track_next(u->bus_track)) {
     746                 :            :                 int c, k;
     747                 :            : 
     748                 :          0 :                 c = sd_bus_track_count_name(u->bus_track, i);
     749         [ #  # ]:          0 :                 if (c < 0)
     750                 :          0 :                         return c;
     751                 :            : 
     752                 :            :                 /* Add the item multiple times if the ref count for each is above 1 */
     753         [ #  # ]:          0 :                 for (k = 0; k < c; k++) {
     754                 :          0 :                         r = sd_bus_message_append(reply, "s", i);
     755         [ #  # ]:          0 :                         if (r < 0)
     756                 :          0 :                                 return r;
     757                 :            :                 }
     758                 :            :         }
     759                 :            : 
     760                 :          0 :         return sd_bus_message_close_container(reply);
     761                 :            : }
     762                 :            : 
     763                 :            : const sd_bus_vtable bus_unit_vtable[] = {
     764                 :            :         SD_BUS_VTABLE_START(0),
     765                 :            : 
     766                 :            :         SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Unit, id), SD_BUS_VTABLE_PROPERTY_CONST),
     767                 :            :         SD_BUS_PROPERTY("Names", "as", property_get_names, offsetof(Unit, names), SD_BUS_VTABLE_PROPERTY_CONST),
     768                 :            :         SD_BUS_PROPERTY("Following", "s", property_get_following, 0, 0),
     769                 :            :         SD_BUS_PROPERTY("Requires", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRES]), SD_BUS_VTABLE_PROPERTY_CONST),
     770                 :            :         SD_BUS_PROPERTY("Requisite", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE]), SD_BUS_VTABLE_PROPERTY_CONST),
     771                 :            :         SD_BUS_PROPERTY("Wants", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_WANTS]), SD_BUS_VTABLE_PROPERTY_CONST),
     772                 :            :         SD_BUS_PROPERTY("BindsTo", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BINDS_TO]), SD_BUS_VTABLE_PROPERTY_CONST),
     773                 :            :         SD_BUS_PROPERTY("PartOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_PART_OF]), SD_BUS_VTABLE_PROPERTY_CONST),
     774                 :            :         SD_BUS_PROPERTY("RequiredBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRED_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
     775                 :            :         SD_BUS_PROPERTY("RequisiteOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE_OF]), SD_BUS_VTABLE_PROPERTY_CONST),
     776                 :            :         SD_BUS_PROPERTY("WantedBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_WANTED_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
     777                 :            :         SD_BUS_PROPERTY("BoundBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BOUND_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
     778                 :            :         SD_BUS_PROPERTY("ConsistsOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONSISTS_OF]), SD_BUS_VTABLE_PROPERTY_CONST),
     779                 :            :         SD_BUS_PROPERTY("Conflicts", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONFLICTS]), SD_BUS_VTABLE_PROPERTY_CONST),
     780                 :            :         SD_BUS_PROPERTY("ConflictedBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONFLICTED_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
     781                 :            :         SD_BUS_PROPERTY("Before", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BEFORE]), SD_BUS_VTABLE_PROPERTY_CONST),
     782                 :            :         SD_BUS_PROPERTY("After", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_AFTER]), SD_BUS_VTABLE_PROPERTY_CONST),
     783                 :            :         SD_BUS_PROPERTY("OnFailure", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_ON_FAILURE]), SD_BUS_VTABLE_PROPERTY_CONST),
     784                 :            :         SD_BUS_PROPERTY("Triggers", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_TRIGGERS]), SD_BUS_VTABLE_PROPERTY_CONST),
     785                 :            :         SD_BUS_PROPERTY("TriggeredBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_TRIGGERED_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
     786                 :            :         SD_BUS_PROPERTY("PropagatesReloadTo", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_PROPAGATES_RELOAD_TO]), SD_BUS_VTABLE_PROPERTY_CONST),
     787                 :            :         SD_BUS_PROPERTY("ReloadPropagatedFrom", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_RELOAD_PROPAGATED_FROM]), SD_BUS_VTABLE_PROPERTY_CONST),
     788                 :            :         SD_BUS_PROPERTY("JoinsNamespaceOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_JOINS_NAMESPACE_OF]), SD_BUS_VTABLE_PROPERTY_CONST),
     789                 :            :         SD_BUS_PROPERTY("RequiresMountsFor", "as", property_get_requires_mounts_for, offsetof(Unit, requires_mounts_for), SD_BUS_VTABLE_PROPERTY_CONST),
     790                 :            :         SD_BUS_PROPERTY("Documentation", "as", NULL, offsetof(Unit, documentation), SD_BUS_VTABLE_PROPERTY_CONST),
     791                 :            :         SD_BUS_PROPERTY("Description", "s", property_get_description, 0, SD_BUS_VTABLE_PROPERTY_CONST),
     792                 :            :         SD_BUS_PROPERTY("LoadState", "s", property_get_load_state, offsetof(Unit, load_state), SD_BUS_VTABLE_PROPERTY_CONST),
     793                 :            :         SD_BUS_PROPERTY("ActiveState", "s", property_get_active_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     794                 :            :         SD_BUS_PROPERTY("SubState", "s", property_get_sub_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     795                 :            :         SD_BUS_PROPERTY("FragmentPath", "s", NULL, offsetof(Unit, fragment_path), SD_BUS_VTABLE_PROPERTY_CONST),
     796                 :            :         SD_BUS_PROPERTY("SourcePath", "s", NULL, offsetof(Unit, source_path), SD_BUS_VTABLE_PROPERTY_CONST),
     797                 :            :         SD_BUS_PROPERTY("DropInPaths", "as", NULL, offsetof(Unit, dropin_paths), SD_BUS_VTABLE_PROPERTY_CONST),
     798                 :            :         SD_BUS_PROPERTY("UnitFileState", "s", property_get_unit_file_state, 0, 0),
     799                 :            :         SD_BUS_PROPERTY("UnitFilePreset", "s", property_get_unit_file_preset, 0, 0),
     800                 :            :         BUS_PROPERTY_DUAL_TIMESTAMP("StateChangeTimestamp", offsetof(Unit, state_change_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     801                 :            :         BUS_PROPERTY_DUAL_TIMESTAMP("InactiveExitTimestamp", offsetof(Unit, inactive_exit_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     802                 :            :         BUS_PROPERTY_DUAL_TIMESTAMP("ActiveEnterTimestamp", offsetof(Unit, active_enter_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     803                 :            :         BUS_PROPERTY_DUAL_TIMESTAMP("ActiveExitTimestamp", offsetof(Unit, active_exit_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     804                 :            :         BUS_PROPERTY_DUAL_TIMESTAMP("InactiveEnterTimestamp", offsetof(Unit, inactive_enter_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     805                 :            :         SD_BUS_PROPERTY("CanStart", "b", property_get_can_start, 0, SD_BUS_VTABLE_PROPERTY_CONST),
     806                 :            :         SD_BUS_PROPERTY("CanStop", "b", property_get_can_stop, 0, SD_BUS_VTABLE_PROPERTY_CONST),
     807                 :            :         SD_BUS_PROPERTY("CanReload", "b", property_get_can_reload, 0, SD_BUS_VTABLE_PROPERTY_CONST),
     808                 :            :         SD_BUS_PROPERTY("CanIsolate", "b", property_get_can_isolate, 0, SD_BUS_VTABLE_PROPERTY_CONST),
     809                 :            :         SD_BUS_PROPERTY("CanClean", "as", property_get_can_clean, 0, SD_BUS_VTABLE_PROPERTY_CONST),
     810                 :            :         SD_BUS_PROPERTY("Job", "(uo)", property_get_job, offsetof(Unit, job), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     811                 :            :         SD_BUS_PROPERTY("StopWhenUnneeded", "b", bus_property_get_bool, offsetof(Unit, stop_when_unneeded), SD_BUS_VTABLE_PROPERTY_CONST),
     812                 :            :         SD_BUS_PROPERTY("RefuseManualStart", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_start), SD_BUS_VTABLE_PROPERTY_CONST),
     813                 :            :         SD_BUS_PROPERTY("RefuseManualStop", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_stop), SD_BUS_VTABLE_PROPERTY_CONST),
     814                 :            :         SD_BUS_PROPERTY("AllowIsolate", "b", bus_property_get_bool, offsetof(Unit, allow_isolate), SD_BUS_VTABLE_PROPERTY_CONST),
     815                 :            :         SD_BUS_PROPERTY("DefaultDependencies", "b", bus_property_get_bool, offsetof(Unit, default_dependencies), SD_BUS_VTABLE_PROPERTY_CONST),
     816                 :            :         SD_BUS_PROPERTY("OnFailureJobMode", "s", property_get_job_mode, offsetof(Unit, on_failure_job_mode), SD_BUS_VTABLE_PROPERTY_CONST),
     817                 :            :         SD_BUS_PROPERTY("IgnoreOnIsolate", "b", bus_property_get_bool, offsetof(Unit, ignore_on_isolate), SD_BUS_VTABLE_PROPERTY_CONST),
     818                 :            :         SD_BUS_PROPERTY("NeedDaemonReload", "b", property_get_need_daemon_reload, 0, SD_BUS_VTABLE_PROPERTY_CONST),
     819                 :            :         SD_BUS_PROPERTY("JobTimeoutUSec", "t", bus_property_get_usec, offsetof(Unit, job_timeout), SD_BUS_VTABLE_PROPERTY_CONST),
     820                 :            :         SD_BUS_PROPERTY("JobRunningTimeoutUSec", "t", bus_property_get_usec, offsetof(Unit, job_running_timeout), SD_BUS_VTABLE_PROPERTY_CONST),
     821                 :            :         SD_BUS_PROPERTY("JobTimeoutAction", "s", property_get_emergency_action, offsetof(Unit, job_timeout_action), SD_BUS_VTABLE_PROPERTY_CONST),
     822                 :            :         SD_BUS_PROPERTY("JobTimeoutRebootArgument", "s", NULL, offsetof(Unit, job_timeout_reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
     823                 :            :         SD_BUS_PROPERTY("ConditionResult", "b", bus_property_get_bool, offsetof(Unit, condition_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     824                 :            :         SD_BUS_PROPERTY("AssertResult", "b", bus_property_get_bool, offsetof(Unit, assert_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     825                 :            :         BUS_PROPERTY_DUAL_TIMESTAMP("ConditionTimestamp", offsetof(Unit, condition_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     826                 :            :         BUS_PROPERTY_DUAL_TIMESTAMP("AssertTimestamp", offsetof(Unit, assert_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     827                 :            :         SD_BUS_PROPERTY("Conditions", "a(sbbsi)", property_get_conditions, offsetof(Unit, conditions), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
     828                 :            :         SD_BUS_PROPERTY("Asserts", "a(sbbsi)", property_get_conditions, offsetof(Unit, asserts), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
     829                 :            :         SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error, 0, SD_BUS_VTABLE_PROPERTY_CONST),
     830                 :            :         SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool, offsetof(Unit, transient), SD_BUS_VTABLE_PROPERTY_CONST),
     831                 :            :         SD_BUS_PROPERTY("Perpetual", "b", bus_property_get_bool, offsetof(Unit, perpetual), SD_BUS_VTABLE_PROPERTY_CONST),
     832                 :            :         SD_BUS_PROPERTY("StartLimitIntervalUSec", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST),
     833                 :            :         SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST),
     834                 :            :         SD_BUS_PROPERTY("StartLimitAction", "s", property_get_emergency_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST),
     835                 :            :         SD_BUS_PROPERTY("FailureAction", "s", property_get_emergency_action, offsetof(Unit, failure_action), SD_BUS_VTABLE_PROPERTY_CONST),
     836                 :            :         SD_BUS_PROPERTY("FailureActionExitStatus", "i", bus_property_get_int, offsetof(Unit, failure_action_exit_status), SD_BUS_VTABLE_PROPERTY_CONST),
     837                 :            :         SD_BUS_PROPERTY("SuccessAction", "s", property_get_emergency_action, offsetof(Unit, success_action), SD_BUS_VTABLE_PROPERTY_CONST),
     838                 :            :         SD_BUS_PROPERTY("SuccessActionExitStatus", "i", bus_property_get_int, offsetof(Unit, success_action_exit_status), SD_BUS_VTABLE_PROPERTY_CONST),
     839                 :            :         SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
     840                 :            :         SD_BUS_PROPERTY("InvocationID", "ay", bus_property_get_id128, offsetof(Unit, invocation_id), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     841                 :            :         SD_BUS_PROPERTY("CollectMode", "s", property_get_collect_mode, offsetof(Unit, collect_mode), SD_BUS_VTABLE_PROPERTY_CONST),
     842                 :            :         SD_BUS_PROPERTY("Refs", "as", property_get_refs, 0, 0),
     843                 :            : 
     844                 :            :         SD_BUS_METHOD("Start", "s", "o", method_start, SD_BUS_VTABLE_UNPRIVILEGED),
     845                 :            :         SD_BUS_METHOD("Stop", "s", "o", method_stop, SD_BUS_VTABLE_UNPRIVILEGED),
     846                 :            :         SD_BUS_METHOD("Reload", "s", "o", method_reload, SD_BUS_VTABLE_UNPRIVILEGED),
     847                 :            :         SD_BUS_METHOD("Restart", "s", "o", method_restart, SD_BUS_VTABLE_UNPRIVILEGED),
     848                 :            :         SD_BUS_METHOD("TryRestart", "s", "o", method_try_restart, SD_BUS_VTABLE_UNPRIVILEGED),
     849                 :            :         SD_BUS_METHOD("ReloadOrRestart", "s", "o", method_reload_or_restart, SD_BUS_VTABLE_UNPRIVILEGED),
     850                 :            :         SD_BUS_METHOD("ReloadOrTryRestart", "s", "o", method_reload_or_try_restart, SD_BUS_VTABLE_UNPRIVILEGED),
     851                 :            :         SD_BUS_METHOD("EnqueueJob", "ss", "uososa(uosos)", bus_unit_method_enqueue_job, SD_BUS_VTABLE_UNPRIVILEGED),
     852                 :            :         SD_BUS_METHOD("Kill", "si", NULL, bus_unit_method_kill, SD_BUS_VTABLE_UNPRIVILEGED),
     853                 :            :         SD_BUS_METHOD("ResetFailed", NULL, NULL, bus_unit_method_reset_failed, SD_BUS_VTABLE_UNPRIVILEGED),
     854                 :            :         SD_BUS_METHOD("SetProperties", "ba(sv)", NULL, bus_unit_method_set_properties, SD_BUS_VTABLE_UNPRIVILEGED),
     855                 :            :         SD_BUS_METHOD("Ref", NULL, NULL, bus_unit_method_ref, SD_BUS_VTABLE_UNPRIVILEGED),
     856                 :            :         SD_BUS_METHOD("Unref", NULL, NULL, bus_unit_method_unref, SD_BUS_VTABLE_UNPRIVILEGED),
     857                 :            :         SD_BUS_METHOD("Clean", "as", NULL, bus_unit_method_clean, SD_BUS_VTABLE_UNPRIVILEGED),
     858                 :            : 
     859                 :            :         /* For dependency types we don't support anymore always return an empty array */
     860                 :            :         SD_BUS_PROPERTY("RequiresOverridable", "as", property_get_empty_strv, 0, SD_BUS_VTABLE_HIDDEN),
     861                 :            :         SD_BUS_PROPERTY("RequisiteOverridable", "as", property_get_empty_strv, 0, SD_BUS_VTABLE_HIDDEN),
     862                 :            :         SD_BUS_PROPERTY("RequiredByOverridable", "as", property_get_empty_strv, 0, SD_BUS_VTABLE_HIDDEN),
     863                 :            :         SD_BUS_PROPERTY("RequisiteOfOverridable", "as", property_get_empty_strv, 0, SD_BUS_VTABLE_HIDDEN),
     864                 :            :         /* Obsolete alias names */
     865                 :            :         SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
     866                 :            :         SD_BUS_PROPERTY("StartLimitIntervalSec", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
     867                 :            :         SD_BUS_VTABLE_END
     868                 :            : };
     869                 :            : 
     870                 :          0 : static int property_get_slice(
     871                 :            :                 sd_bus *bus,
     872                 :            :                 const char *path,
     873                 :            :                 const char *interface,
     874                 :            :                 const char *property,
     875                 :            :                 sd_bus_message *reply,
     876                 :            :                 void *userdata,
     877                 :            :                 sd_bus_error *error) {
     878                 :            : 
     879                 :          0 :         Unit *u = userdata;
     880                 :            : 
     881         [ #  # ]:          0 :         assert(bus);
     882         [ #  # ]:          0 :         assert(reply);
     883         [ #  # ]:          0 :         assert(u);
     884                 :            : 
     885                 :          0 :         return sd_bus_message_append(reply, "s", unit_slice_name(u));
     886                 :            : }
     887                 :            : 
     888                 :          0 : static int property_get_current_memory(
     889                 :            :                 sd_bus *bus,
     890                 :            :                 const char *path,
     891                 :            :                 const char *interface,
     892                 :            :                 const char *property,
     893                 :            :                 sd_bus_message *reply,
     894                 :            :                 void *userdata,
     895                 :            :                 sd_bus_error *error) {
     896                 :            : 
     897                 :          0 :         uint64_t sz = (uint64_t) -1;
     898                 :          0 :         Unit *u = userdata;
     899                 :            :         int r;
     900                 :            : 
     901         [ #  # ]:          0 :         assert(bus);
     902         [ #  # ]:          0 :         assert(reply);
     903         [ #  # ]:          0 :         assert(u);
     904                 :            : 
     905                 :          0 :         r = unit_get_memory_current(u, &sz);
     906   [ #  #  #  # ]:          0 :         if (r < 0 && r != -ENODATA)
     907         [ #  # ]:          0 :                 log_unit_warning_errno(u, r, "Failed to get memory.usage_in_bytes attribute: %m");
     908                 :            : 
     909                 :          0 :         return sd_bus_message_append(reply, "t", sz);
     910                 :            : }
     911                 :            : 
     912                 :          0 : static int property_get_current_tasks(
     913                 :            :                 sd_bus *bus,
     914                 :            :                 const char *path,
     915                 :            :                 const char *interface,
     916                 :            :                 const char *property,
     917                 :            :                 sd_bus_message *reply,
     918                 :            :                 void *userdata,
     919                 :            :                 sd_bus_error *error) {
     920                 :            : 
     921                 :          0 :         uint64_t cn = (uint64_t) -1;
     922                 :          0 :         Unit *u = userdata;
     923                 :            :         int r;
     924                 :            : 
     925         [ #  # ]:          0 :         assert(bus);
     926         [ #  # ]:          0 :         assert(reply);
     927         [ #  # ]:          0 :         assert(u);
     928                 :            : 
     929                 :          0 :         r = unit_get_tasks_current(u, &cn);
     930   [ #  #  #  # ]:          0 :         if (r < 0 && r != -ENODATA)
     931         [ #  # ]:          0 :                 log_unit_warning_errno(u, r, "Failed to get pids.current attribute: %m");
     932                 :            : 
     933                 :          0 :         return sd_bus_message_append(reply, "t", cn);
     934                 :            : }
     935                 :            : 
     936                 :          0 : static int property_get_cpu_usage(
     937                 :            :                 sd_bus *bus,
     938                 :            :                 const char *path,
     939                 :            :                 const char *interface,
     940                 :            :                 const char *property,
     941                 :            :                 sd_bus_message *reply,
     942                 :            :                 void *userdata,
     943                 :            :                 sd_bus_error *error) {
     944                 :            : 
     945                 :          0 :         nsec_t ns = (nsec_t) -1;
     946                 :          0 :         Unit *u = userdata;
     947                 :            :         int r;
     948                 :            : 
     949         [ #  # ]:          0 :         assert(bus);
     950         [ #  # ]:          0 :         assert(reply);
     951         [ #  # ]:          0 :         assert(u);
     952                 :            : 
     953                 :          0 :         r = unit_get_cpu_usage(u, &ns);
     954   [ #  #  #  # ]:          0 :         if (r < 0 && r != -ENODATA)
     955         [ #  # ]:          0 :                 log_unit_warning_errno(u, r, "Failed to get cpuacct.usage attribute: %m");
     956                 :            : 
     957                 :          0 :         return sd_bus_message_append(reply, "t", ns);
     958                 :            : }
     959                 :            : 
     960                 :          0 : static int property_get_cgroup(
     961                 :            :                 sd_bus *bus,
     962                 :            :                 const char *path,
     963                 :            :                 const char *interface,
     964                 :            :                 const char *property,
     965                 :            :                 sd_bus_message *reply,
     966                 :            :                 void *userdata,
     967                 :            :                 sd_bus_error *error) {
     968                 :            : 
     969                 :          0 :         Unit *u = userdata;
     970                 :          0 :         const char *t = NULL;
     971                 :            : 
     972         [ #  # ]:          0 :         assert(bus);
     973         [ #  # ]:          0 :         assert(reply);
     974         [ #  # ]:          0 :         assert(u);
     975                 :            : 
     976                 :            :         /* Three cases: a) u->cgroup_path is NULL, in which case the
     977                 :            :          * unit has no control group, which we report as the empty
     978                 :            :          * string. b) u->cgroup_path is the empty string, which
     979                 :            :          * indicates the root cgroup, which we report as "/". c) all
     980                 :            :          * other cases we report as-is. */
     981                 :            : 
     982         [ #  # ]:          0 :         if (u->cgroup_path)
     983                 :          0 :                 t = empty_to_root(u->cgroup_path);
     984                 :            : 
     985                 :          0 :         return sd_bus_message_append(reply, "s", t);
     986                 :            : }
     987                 :            : 
     988                 :          0 : static int append_process(sd_bus_message *reply, const char *p, pid_t pid, Set *pids) {
     989                 :          0 :         _cleanup_free_ char *buf = NULL, *cmdline = NULL;
     990                 :            :         int r;
     991                 :            : 
     992         [ #  # ]:          0 :         assert(reply);
     993         [ #  # ]:          0 :         assert(pid > 0);
     994                 :            : 
     995                 :          0 :         r = set_put(pids, PID_TO_PTR(pid));
     996   [ #  #  #  # ]:          0 :         if (IN_SET(r, 0, -EEXIST))
     997                 :          0 :                 return 0;
     998         [ #  # ]:          0 :         if (r < 0)
     999                 :          0 :                 return r;
    1000                 :            : 
    1001         [ #  # ]:          0 :         if (!p) {
    1002                 :          0 :                 r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &buf);
    1003         [ #  # ]:          0 :                 if (r == -ESRCH)
    1004                 :          0 :                         return 0;
    1005         [ #  # ]:          0 :                 if (r < 0)
    1006                 :          0 :                         return r;
    1007                 :            : 
    1008                 :          0 :                 p = buf;
    1009                 :            :         }
    1010                 :            : 
    1011                 :          0 :         (void) get_process_cmdline(pid, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &cmdline);
    1012                 :            : 
    1013                 :          0 :         return sd_bus_message_append(reply,
    1014                 :            :                                      "(sus)",
    1015                 :            :                                      p,
    1016                 :            :                                      (uint32_t) pid,
    1017                 :            :                                      cmdline);
    1018                 :            : }
    1019                 :            : 
    1020                 :          0 : static int append_cgroup(sd_bus_message *reply, const char *p, Set *pids) {
    1021                 :          0 :         _cleanup_closedir_ DIR *d = NULL;
    1022                 :          0 :         _cleanup_fclose_ FILE *f = NULL;
    1023                 :            :         int r;
    1024                 :            : 
    1025         [ #  # ]:          0 :         assert(reply);
    1026         [ #  # ]:          0 :         assert(p);
    1027                 :            : 
    1028                 :          0 :         r = cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, p, &f);
    1029         [ #  # ]:          0 :         if (r == -ENOENT)
    1030                 :          0 :                 return 0;
    1031         [ #  # ]:          0 :         if (r < 0)
    1032                 :          0 :                 return r;
    1033                 :            : 
    1034                 :          0 :         for (;;) {
    1035                 :            :                 pid_t pid;
    1036                 :            : 
    1037                 :          0 :                 r = cg_read_pid(f, &pid);
    1038         [ #  # ]:          0 :                 if (r < 0)
    1039                 :          0 :                         return r;
    1040         [ #  # ]:          0 :                 if (r == 0)
    1041                 :          0 :                         break;
    1042                 :            : 
    1043         [ #  # ]:          0 :                 if (is_kernel_thread(pid) > 0)
    1044                 :          0 :                         continue;
    1045                 :            : 
    1046                 :          0 :                 r = append_process(reply, p, pid, pids);
    1047         [ #  # ]:          0 :                 if (r < 0)
    1048                 :          0 :                         return r;
    1049                 :            :         }
    1050                 :            : 
    1051                 :          0 :         r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, p, &d);
    1052         [ #  # ]:          0 :         if (r == -ENOENT)
    1053                 :          0 :                 return 0;
    1054         [ #  # ]:          0 :         if (r < 0)
    1055                 :          0 :                 return r;
    1056                 :            : 
    1057                 :          0 :         for (;;) {
    1058   [ #  #  #  #  :          0 :                 _cleanup_free_ char *g = NULL, *j = NULL;
                   #  # ]
    1059                 :            : 
    1060                 :          0 :                 r = cg_read_subgroup(d, &g);
    1061         [ #  # ]:          0 :                 if (r < 0)
    1062                 :          0 :                         return r;
    1063         [ #  # ]:          0 :                 if (r == 0)
    1064                 :          0 :                         break;
    1065                 :            : 
    1066                 :          0 :                 j = path_join(empty_to_root(p), g);
    1067         [ #  # ]:          0 :                 if (!j)
    1068                 :          0 :                         return -ENOMEM;
    1069                 :            : 
    1070                 :          0 :                 r = append_cgroup(reply, j, pids);
    1071         [ #  # ]:          0 :                 if (r < 0)
    1072                 :          0 :                         return r;
    1073                 :            :         }
    1074                 :            : 
    1075                 :          0 :         return 0;
    1076                 :            : }
    1077                 :            : 
    1078                 :          0 : int bus_unit_method_get_processes(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    1079                 :          0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
    1080                 :          0 :         _cleanup_set_free_ Set *pids = NULL;
    1081                 :          0 :         Unit *u = userdata;
    1082                 :            :         pid_t pid;
    1083                 :            :         int r;
    1084                 :            : 
    1085         [ #  # ]:          0 :         assert(message);
    1086                 :            : 
    1087                 :          0 :         r = mac_selinux_unit_access_check(u, message, "status", error);
    1088         [ #  # ]:          0 :         if (r < 0)
    1089                 :          0 :                 return r;
    1090                 :            : 
    1091                 :          0 :         pids = set_new(NULL);
    1092         [ #  # ]:          0 :         if (!pids)
    1093                 :          0 :                 return -ENOMEM;
    1094                 :            : 
    1095                 :          0 :         r = sd_bus_message_new_method_return(message, &reply);
    1096         [ #  # ]:          0 :         if (r < 0)
    1097                 :          0 :                 return r;
    1098                 :            : 
    1099                 :          0 :         r = sd_bus_message_open_container(reply, 'a', "(sus)");
    1100         [ #  # ]:          0 :         if (r < 0)
    1101                 :          0 :                 return r;
    1102                 :            : 
    1103         [ #  # ]:          0 :         if (u->cgroup_path) {
    1104                 :          0 :                 r = append_cgroup(reply, u->cgroup_path, pids);
    1105         [ #  # ]:          0 :                 if (r < 0)
    1106                 :          0 :                         return r;
    1107                 :            :         }
    1108                 :            : 
    1109                 :            :         /* The main and control pids might live outside of the cgroup, hence fetch them separately */
    1110                 :          0 :         pid = unit_main_pid(u);
    1111         [ #  # ]:          0 :         if (pid > 0) {
    1112                 :          0 :                 r = append_process(reply, NULL, pid, pids);
    1113         [ #  # ]:          0 :                 if (r < 0)
    1114                 :          0 :                         return r;
    1115                 :            :         }
    1116                 :            : 
    1117                 :          0 :         pid = unit_control_pid(u);
    1118         [ #  # ]:          0 :         if (pid > 0) {
    1119                 :          0 :                 r = append_process(reply, NULL, pid, pids);
    1120         [ #  # ]:          0 :                 if (r < 0)
    1121                 :          0 :                         return r;
    1122                 :            :         }
    1123                 :            : 
    1124                 :          0 :         r = sd_bus_message_close_container(reply);
    1125         [ #  # ]:          0 :         if (r < 0)
    1126                 :          0 :                 return r;
    1127                 :            : 
    1128                 :          0 :         return sd_bus_send(NULL, reply, NULL);
    1129                 :            : }
    1130                 :            : 
    1131                 :          0 : static int property_get_ip_counter(
    1132                 :            :                 sd_bus *bus,
    1133                 :            :                 const char *path,
    1134                 :            :                 const char *interface,
    1135                 :            :                 const char *property,
    1136                 :            :                 sd_bus_message *reply,
    1137                 :            :                 void *userdata,
    1138                 :            :                 sd_bus_error *error) {
    1139                 :            : 
    1140                 :            :         static const char *const table[_CGROUP_IP_ACCOUNTING_METRIC_MAX] = {
    1141                 :            :                 [CGROUP_IP_INGRESS_BYTES]   = "IPIngressBytes",
    1142                 :            :                 [CGROUP_IP_EGRESS_BYTES]    = "IPEgressBytes",
    1143                 :            :                 [CGROUP_IP_INGRESS_PACKETS] = "IPIngressPackets",
    1144                 :            :                 [CGROUP_IP_EGRESS_PACKETS]  = "IPEgressPackets",
    1145                 :            :         };
    1146                 :            : 
    1147                 :          0 :         uint64_t value = UINT64_MAX;
    1148                 :          0 :         Unit *u = userdata;
    1149                 :            :         ssize_t metric;
    1150                 :            : 
    1151         [ #  # ]:          0 :         assert(bus);
    1152         [ #  # ]:          0 :         assert(reply);
    1153         [ #  # ]:          0 :         assert(property);
    1154         [ #  # ]:          0 :         assert(u);
    1155                 :            : 
    1156         [ #  # ]:          0 :         assert_se((metric = string_table_lookup(table, ELEMENTSOF(table), property)) >= 0);
    1157                 :          0 :         (void) unit_get_ip_accounting(u, metric, &value);
    1158                 :          0 :         return sd_bus_message_append(reply, "t", value);
    1159                 :            : }
    1160                 :            : 
    1161                 :          0 : static int property_get_io_counter(
    1162                 :            :                 sd_bus *bus,
    1163                 :            :                 const char *path,
    1164                 :            :                 const char *interface,
    1165                 :            :                 const char *property,
    1166                 :            :                 sd_bus_message *reply,
    1167                 :            :                 void *userdata,
    1168                 :            :                 sd_bus_error *error) {
    1169                 :            : 
    1170                 :            :         static const char *const table[_CGROUP_IO_ACCOUNTING_METRIC_MAX] = {
    1171                 :            :                 [CGROUP_IO_READ_BYTES]       = "IOReadBytes",
    1172                 :            :                 [CGROUP_IO_WRITE_BYTES]      = "IOWriteBytes",
    1173                 :            :                 [CGROUP_IO_READ_OPERATIONS]  = "IOReadOperations",
    1174                 :            :                 [CGROUP_IO_WRITE_OPERATIONS] = "IOWriteOperations",
    1175                 :            :         };
    1176                 :            : 
    1177                 :          0 :         uint64_t value = UINT64_MAX;
    1178                 :          0 :         Unit *u = userdata;
    1179                 :            :         ssize_t metric;
    1180                 :            : 
    1181         [ #  # ]:          0 :         assert(bus);
    1182         [ #  # ]:          0 :         assert(reply);
    1183         [ #  # ]:          0 :         assert(property);
    1184         [ #  # ]:          0 :         assert(u);
    1185                 :            : 
    1186         [ #  # ]:          0 :         assert_se((metric = string_table_lookup(table, ELEMENTSOF(table), property)) >= 0);
    1187                 :          0 :         (void) unit_get_io_accounting(u, metric, false, &value);
    1188                 :          0 :         return sd_bus_message_append(reply, "t", value);
    1189                 :            : }
    1190                 :            : 
    1191                 :          0 : int bus_unit_method_attach_processes(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    1192                 :            : 
    1193                 :          0 :         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
    1194                 :          0 :         _cleanup_set_free_ Set *pids = NULL;
    1195                 :          0 :         Unit *u = userdata;
    1196                 :            :         const char *path;
    1197                 :            :         int r;
    1198                 :            : 
    1199         [ #  # ]:          0 :         assert(message);
    1200                 :            : 
    1201                 :            :         /* This migrates the processes with the specified PIDs into the cgroup of this unit, optionally below a
    1202                 :            :          * specified cgroup path. Obviously this only works for units that actually maintain a cgroup
    1203                 :            :          * representation. If a process is already in the cgroup no operation is executed – in this case the specified
    1204                 :            :          * subcgroup path has no effect! */
    1205                 :            : 
    1206                 :          0 :         r = mac_selinux_unit_access_check(u, message, "start", error);
    1207         [ #  # ]:          0 :         if (r < 0)
    1208                 :          0 :                 return r;
    1209                 :            : 
    1210                 :          0 :         r = sd_bus_message_read(message, "s", &path);
    1211         [ #  # ]:          0 :         if (r < 0)
    1212                 :          0 :                 return r;
    1213                 :            : 
    1214                 :          0 :         path = empty_to_null(path);
    1215         [ #  # ]:          0 :         if (path) {
    1216         [ #  # ]:          0 :                 if (!path_is_absolute(path))
    1217                 :          0 :                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Control group path is not absolute: %s", path);
    1218                 :            : 
    1219         [ #  # ]:          0 :                 if (!path_is_normalized(path))
    1220                 :          0 :                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Control group path is not normalized: %s", path);
    1221                 :            :         }
    1222                 :            : 
    1223         [ #  # ]:          0 :         if (!unit_cgroup_delegate(u))
    1224                 :          0 :                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Process migration not available on non-delegated units.");
    1225                 :            : 
    1226         [ #  # ]:          0 :         if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(u)))
    1227                 :          0 :                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit is not active, refusing.");
    1228                 :            : 
    1229                 :          0 :         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds);
    1230         [ #  # ]:          0 :         if (r < 0)
    1231                 :          0 :                 return r;
    1232                 :            : 
    1233                 :          0 :         r = sd_bus_message_enter_container(message, 'a', "u");
    1234         [ #  # ]:          0 :         if (r < 0)
    1235                 :          0 :                 return r;
    1236                 :          0 :         for (;;) {
    1237                 :            :                 uid_t process_uid, sender_uid;
    1238                 :            :                 uint32_t upid;
    1239                 :            :                 pid_t pid;
    1240                 :            : 
    1241                 :          0 :                 r = sd_bus_message_read(message, "u", &upid);
    1242         [ #  # ]:          0 :                 if (r < 0)
    1243                 :          0 :                         return r;
    1244         [ #  # ]:          0 :                 if (r == 0)
    1245                 :          0 :                         break;
    1246                 :            : 
    1247         [ #  # ]:          0 :                 if (upid == 0) {
    1248                 :          0 :                         r = sd_bus_creds_get_pid(creds, &pid);
    1249         [ #  # ]:          0 :                         if (r < 0)
    1250                 :          0 :                                 return r;
    1251                 :            :                 } else
    1252                 :          0 :                         pid = (uid_t) upid;
    1253                 :            : 
    1254                 :            :                 /* Filter out duplicates */
    1255         [ #  # ]:          0 :                 if (set_contains(pids, PID_TO_PTR(pid)))
    1256                 :          0 :                         continue;
    1257                 :            : 
    1258                 :            :                 /* Check if this process is suitable for attaching to this unit */
    1259                 :          0 :                 r = unit_pid_attachable(u, pid, error);
    1260         [ #  # ]:          0 :                 if (r < 0)
    1261                 :          0 :                         return r;
    1262                 :            : 
    1263                 :            :                 /* Let's query the sender's UID, so that we can make our security decisions */
    1264                 :          0 :                 r = sd_bus_creds_get_euid(creds, &sender_uid);
    1265         [ #  # ]:          0 :                 if (r < 0)
    1266                 :          0 :                         return r;
    1267                 :            : 
    1268                 :            :                 /* Let's validate security: if the sender is root, then all is OK. If the sender is any other unit,
    1269                 :            :                  * then the process' UID and the target unit's UID have to match the sender's UID */
    1270   [ #  #  #  # ]:          0 :                 if (sender_uid != 0 && sender_uid != getuid()) {
    1271                 :          0 :                         r = get_process_uid(pid, &process_uid);
    1272         [ #  # ]:          0 :                         if (r < 0)
    1273                 :          0 :                                 return sd_bus_error_set_errnof(error, r, "Failed to retrieve process UID: %m");
    1274                 :            : 
    1275         [ #  # ]:          0 :                         if (process_uid != sender_uid)
    1276                 :          0 :                                 return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Process " PID_FMT " not owned by client's UID. Refusing.", pid);
    1277         [ #  # ]:          0 :                         if (process_uid != u->ref_uid)
    1278                 :          0 :                                 return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Process " PID_FMT " not owned by target unit's UID. Refusing.", pid);
    1279                 :            :                 }
    1280                 :            : 
    1281         [ #  # ]:          0 :                 if (!pids) {
    1282                 :          0 :                         pids = set_new(NULL);
    1283         [ #  # ]:          0 :                         if (!pids)
    1284                 :          0 :                                 return -ENOMEM;
    1285                 :            :                 }
    1286                 :            : 
    1287                 :          0 :                 r = set_put(pids, PID_TO_PTR(pid));
    1288         [ #  # ]:          0 :                 if (r < 0)
    1289                 :          0 :                         return r;
    1290                 :            :         }
    1291                 :            : 
    1292                 :          0 :         r = sd_bus_message_exit_container(message);
    1293         [ #  # ]:          0 :         if (r < 0)
    1294                 :          0 :                 return r;
    1295                 :            : 
    1296                 :          0 :         r = unit_attach_pids_to_cgroup(u, pids, path);
    1297         [ #  # ]:          0 :         if (r < 0)
    1298                 :          0 :                 return sd_bus_error_set_errnof(error, r, "Failed to attach processes to control group: %m");
    1299                 :            : 
    1300                 :          0 :         return sd_bus_reply_method_return(message, NULL);
    1301                 :            : }
    1302                 :            : 
    1303                 :            : const sd_bus_vtable bus_unit_cgroup_vtable[] = {
    1304                 :            :         SD_BUS_VTABLE_START(0),
    1305                 :            :         SD_BUS_PROPERTY("Slice", "s", property_get_slice, 0, 0),
    1306                 :            :         SD_BUS_PROPERTY("ControlGroup", "s", property_get_cgroup, 0, 0),
    1307                 :            :         SD_BUS_PROPERTY("MemoryCurrent", "t", property_get_current_memory, 0, 0),
    1308                 :            :         SD_BUS_PROPERTY("CPUUsageNSec", "t", property_get_cpu_usage, 0, 0),
    1309                 :            :         SD_BUS_PROPERTY("TasksCurrent", "t", property_get_current_tasks, 0, 0),
    1310                 :            :         SD_BUS_PROPERTY("IPIngressBytes", "t", property_get_ip_counter, 0, 0),
    1311                 :            :         SD_BUS_PROPERTY("IPIngressPackets", "t", property_get_ip_counter, 0, 0),
    1312                 :            :         SD_BUS_PROPERTY("IPEgressBytes", "t", property_get_ip_counter, 0, 0),
    1313                 :            :         SD_BUS_PROPERTY("IPEgressPackets", "t", property_get_ip_counter, 0, 0),
    1314                 :            :         SD_BUS_PROPERTY("IOReadBytes", "t", property_get_io_counter, 0, 0),
    1315                 :            :         SD_BUS_PROPERTY("IOReadOperations", "t", property_get_io_counter, 0, 0),
    1316                 :            :         SD_BUS_PROPERTY("IOWriteBytes", "t", property_get_io_counter, 0, 0),
    1317                 :            :         SD_BUS_PROPERTY("IOWriteOperations", "t", property_get_io_counter, 0, 0),
    1318                 :            :         SD_BUS_METHOD("GetProcesses", NULL, "a(sus)", bus_unit_method_get_processes, SD_BUS_VTABLE_UNPRIVILEGED),
    1319                 :            :         SD_BUS_METHOD("AttachProcesses", "sau", NULL, bus_unit_method_attach_processes, SD_BUS_VTABLE_UNPRIVILEGED),
    1320                 :            :         SD_BUS_VTABLE_END
    1321                 :            : };
    1322                 :            : 
    1323                 :          0 : static int send_new_signal(sd_bus *bus, void *userdata) {
    1324                 :          0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
    1325                 :          0 :         _cleanup_free_ char *p = NULL;
    1326                 :          0 :         Unit *u = userdata;
    1327                 :            :         int r;
    1328                 :            : 
    1329         [ #  # ]:          0 :         assert(bus);
    1330         [ #  # ]:          0 :         assert(u);
    1331                 :            : 
    1332                 :          0 :         p = unit_dbus_path(u);
    1333         [ #  # ]:          0 :         if (!p)
    1334                 :          0 :                 return -ENOMEM;
    1335                 :            : 
    1336                 :          0 :         r = sd_bus_message_new_signal(
    1337                 :            :                         bus,
    1338                 :            :                         &m,
    1339                 :            :                         "/org/freedesktop/systemd1",
    1340                 :            :                         "org.freedesktop.systemd1.Manager",
    1341                 :            :                         "UnitNew");
    1342         [ #  # ]:          0 :         if (r < 0)
    1343                 :          0 :                 return r;
    1344                 :            : 
    1345                 :          0 :         r = sd_bus_message_append(m, "so", u->id, p);
    1346         [ #  # ]:          0 :         if (r < 0)
    1347                 :          0 :                 return r;
    1348                 :            : 
    1349                 :          0 :         return sd_bus_send(bus, m, NULL);
    1350                 :            : }
    1351                 :            : 
    1352                 :          0 : static int send_changed_signal(sd_bus *bus, void *userdata) {
    1353                 :          0 :         _cleanup_free_ char *p = NULL;
    1354                 :          0 :         Unit *u = userdata;
    1355                 :            :         int r;
    1356                 :            : 
    1357         [ #  # ]:          0 :         assert(bus);
    1358         [ #  # ]:          0 :         assert(u);
    1359                 :            : 
    1360                 :          0 :         p = unit_dbus_path(u);
    1361         [ #  # ]:          0 :         if (!p)
    1362                 :          0 :                 return -ENOMEM;
    1363                 :            : 
    1364                 :            :         /* Send a properties changed signal. First for the specific
    1365                 :            :          * type, then for the generic unit. The clients may rely on
    1366                 :            :          * this order to get atomic behavior if needed. */
    1367                 :            : 
    1368                 :          0 :         r = sd_bus_emit_properties_changed_strv(
    1369                 :            :                         bus, p,
    1370                 :            :                         unit_dbus_interface_from_type(u->type),
    1371                 :            :                         NULL);
    1372         [ #  # ]:          0 :         if (r < 0)
    1373                 :          0 :                 return r;
    1374                 :            : 
    1375                 :          0 :         return sd_bus_emit_properties_changed_strv(
    1376                 :            :                         bus, p,
    1377                 :            :                         "org.freedesktop.systemd1.Unit",
    1378                 :            :                         NULL);
    1379                 :            : }
    1380                 :            : 
    1381                 :         20 : void bus_unit_send_change_signal(Unit *u) {
    1382                 :            :         int r;
    1383         [ -  + ]:         20 :         assert(u);
    1384                 :            : 
    1385         [ -  + ]:         20 :         if (u->in_dbus_queue) {
    1386   [ #  #  #  #  :          0 :                 LIST_REMOVE(dbus_queue, u->manager->dbus_unit_queue, u);
             #  #  #  # ]
    1387                 :          0 :                 u->in_dbus_queue = false;
    1388                 :            :         }
    1389                 :            : 
    1390         [ +  + ]:         20 :         if (!u->id)
    1391                 :          8 :                 return;
    1392                 :            : 
    1393         [ -  + ]:         12 :         r = bus_foreach_bus(u->manager, u->bus_track, u->sent_dbus_new_signal ? send_changed_signal : send_new_signal, u);
    1394         [ -  + ]:         12 :         if (r < 0)
    1395         [ #  # ]:          0 :                 log_unit_debug_errno(u, r, "Failed to send unit change signal for %s: %m", u->id);
    1396                 :            : 
    1397                 :         12 :         u->sent_dbus_new_signal = true;
    1398                 :            : }
    1399                 :            : 
    1400                 :       7484 : void bus_unit_send_pending_change_signal(Unit *u, bool including_new) {
    1401                 :            : 
    1402                 :            :         /* Sends out any pending change signals, but only if they really are pending. This call is used when we are
    1403                 :            :          * about to change state in order to force out a PropertiesChanged signal beforehand if there was one pending
    1404                 :            :          * so that clients can follow the full state transition */
    1405                 :            : 
    1406         [ +  - ]:       7484 :         if (!u->in_dbus_queue) /* If not enqueued, don't bother */
    1407                 :       7484 :                 return;
    1408                 :            : 
    1409   [ #  #  #  # ]:          0 :         if (!u->sent_dbus_new_signal && !including_new) /* If the unit was never announced, don't bother, it's fine if
    1410                 :            :                                                          * the unit appears in the new state right-away (except if the
    1411                 :            :                                                          * caller explicitly asked us to send it anyway) */
    1412                 :          0 :                 return;
    1413                 :            : 
    1414         [ #  # ]:          0 :         if (MANAGER_IS_RELOADING(u->manager)) /* Don't generate unnecessary PropertiesChanged signals for the same unit
    1415                 :            :                                                * when we are reloading. */
    1416                 :          0 :                 return;
    1417                 :            : 
    1418                 :          0 :         bus_unit_send_change_signal(u);
    1419                 :            : }
    1420                 :            : 
    1421                 :          0 : static int send_removed_signal(sd_bus *bus, void *userdata) {
    1422                 :          0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
    1423                 :          0 :         _cleanup_free_ char *p = NULL;
    1424                 :          0 :         Unit *u = userdata;
    1425                 :            :         int r;
    1426                 :            : 
    1427         [ #  # ]:          0 :         assert(bus);
    1428         [ #  # ]:          0 :         assert(u);
    1429                 :            : 
    1430                 :          0 :         p = unit_dbus_path(u);
    1431         [ #  # ]:          0 :         if (!p)
    1432                 :          0 :                 return -ENOMEM;
    1433                 :            : 
    1434                 :          0 :         r = sd_bus_message_new_signal(
    1435                 :            :                         bus,
    1436                 :            :                         &m,
    1437                 :            :                         "/org/freedesktop/systemd1",
    1438                 :            :                         "org.freedesktop.systemd1.Manager",
    1439                 :            :                         "UnitRemoved");
    1440         [ #  # ]:          0 :         if (r < 0)
    1441                 :          0 :                 return r;
    1442                 :            : 
    1443                 :          0 :         r = sd_bus_message_append(m, "so", u->id, p);
    1444         [ #  # ]:          0 :         if (r < 0)
    1445                 :          0 :                 return r;
    1446                 :            : 
    1447                 :          0 :         return sd_bus_send(bus, m, NULL);
    1448                 :            : }
    1449                 :            : 
    1450                 :       8728 : void bus_unit_send_removed_signal(Unit *u) {
    1451                 :            :         int r;
    1452         [ -  + ]:       8728 :         assert(u);
    1453                 :            : 
    1454   [ +  +  -  + ]:       8728 :         if (!u->sent_dbus_new_signal || u->in_dbus_queue)
    1455                 :         20 :                 bus_unit_send_change_signal(u);
    1456                 :            : 
    1457         [ +  + ]:       8728 :         if (!u->id)
    1458                 :          8 :                 return;
    1459                 :            : 
    1460                 :       8720 :         r = bus_foreach_bus(u->manager, u->bus_track, send_removed_signal, u);
    1461         [ -  + ]:       8720 :         if (r < 0)
    1462         [ #  # ]:          0 :                 log_unit_debug_errno(u, r, "Failed to send unit remove signal for %s: %m", u->id);
    1463                 :            : }
    1464                 :            : 
    1465                 :          0 : int bus_unit_queue_job(
    1466                 :            :                 sd_bus_message *message,
    1467                 :            :                 Unit *u,
    1468                 :            :                 JobType type,
    1469                 :            :                 JobMode mode,
    1470                 :            :                 BusUnitQueueFlags flags,
    1471                 :            :                 sd_bus_error *error) {
    1472                 :            : 
    1473                 :          0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
    1474                 :          0 :         _cleanup_free_ char *job_path = NULL, *unit_path = NULL;
    1475                 :          0 :         _cleanup_(set_freep) Set *affected = NULL;
    1476                 :            :         Iterator i;
    1477                 :            :         Job *j, *a;
    1478                 :            :         int r;
    1479                 :            : 
    1480         [ #  # ]:          0 :         assert(message);
    1481         [ #  # ]:          0 :         assert(u);
    1482   [ #  #  #  # ]:          0 :         assert(type >= 0 && type < _JOB_TYPE_MAX);
    1483   [ #  #  #  # ]:          0 :         assert(mode >= 0 && mode < _JOB_MODE_MAX);
    1484                 :            : 
    1485                 :          0 :         r = mac_selinux_unit_access_check(
    1486                 :            :                         u, message,
    1487                 :            :                         job_type_to_access_method(type),
    1488                 :            :                         error);
    1489         [ #  # ]:          0 :         if (r < 0)
    1490                 :          0 :                 return r;
    1491                 :            : 
    1492   [ #  #  #  # ]:          0 :         if (FLAGS_SET(flags, BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE) && unit_can_reload(u)) {
    1493         [ #  # ]:          0 :                 if (type == JOB_RESTART)
    1494                 :          0 :                         type = JOB_RELOAD_OR_START;
    1495         [ #  # ]:          0 :                 else if (type == JOB_TRY_RESTART)
    1496                 :          0 :                         type = JOB_TRY_RELOAD;
    1497                 :            :         }
    1498                 :            : 
    1499         [ #  # ]:          0 :         if (type == JOB_STOP &&
    1500   [ #  #  #  #  :          0 :             IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_ERROR, UNIT_BAD_SETTING) &&
                   #  # ]
    1501                 :          0 :             unit_active_state(u) == UNIT_INACTIVE)
    1502                 :          0 :                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", u->id);
    1503                 :            : 
    1504   [ #  #  #  #  :          0 :         if ((type == JOB_START && u->refuse_manual_start) ||
                   #  # ]
    1505         [ #  # ]:          0 :             (type == JOB_STOP && u->refuse_manual_stop) ||
    1506   [ #  #  #  #  :          0 :             (IN_SET(type, JOB_RESTART, JOB_TRY_RESTART) && (u->refuse_manual_start || u->refuse_manual_stop)) ||
          #  #  #  #  #  
                      # ]
    1507   [ #  #  #  # ]:          0 :             (type == JOB_RELOAD_OR_START && job_type_collapse(type, u) == JOB_START && u->refuse_manual_start))
    1508                 :          0 :                 return sd_bus_error_setf(error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, unit %s may be requested by dependency only (it is configured to refuse manual start/stop).", u->id);
    1509                 :            : 
    1510         [ #  # ]:          0 :         if (FLAGS_SET(flags, BUS_UNIT_QUEUE_VERBOSE_REPLY)) {
    1511                 :          0 :                 affected = set_new(NULL);
    1512         [ #  # ]:          0 :                 if (!affected)
    1513                 :          0 :                         return -ENOMEM;
    1514                 :            :         }
    1515                 :            : 
    1516                 :          0 :         r = manager_add_job(u->manager, type, u, mode, affected, error, &j);
    1517         [ #  # ]:          0 :         if (r < 0)
    1518                 :          0 :                 return r;
    1519                 :            : 
    1520                 :          0 :         r = bus_job_track_sender(j, message);
    1521         [ #  # ]:          0 :         if (r < 0)
    1522                 :          0 :                 return r;
    1523                 :            : 
    1524                 :            :         /* Before we send the method reply, force out the announcement JobNew for this job */
    1525                 :          0 :         bus_job_send_pending_change_signal(j, true);
    1526                 :            : 
    1527                 :          0 :         job_path = job_dbus_path(j);
    1528         [ #  # ]:          0 :         if (!job_path)
    1529                 :          0 :                 return -ENOMEM;
    1530                 :            : 
    1531                 :            :         /* The classic response is just a job object path */
    1532         [ #  # ]:          0 :         if (!FLAGS_SET(flags, BUS_UNIT_QUEUE_VERBOSE_REPLY))
    1533                 :          0 :                 return sd_bus_reply_method_return(message, "o", job_path);
    1534                 :            : 
    1535                 :            :         /* In verbose mode respond with the anchor job plus everything that has been affected */
    1536                 :          0 :         r = sd_bus_message_new_method_return(message, &reply);
    1537         [ #  # ]:          0 :         if (r < 0)
    1538                 :          0 :                 return r;
    1539                 :            : 
    1540                 :          0 :         unit_path = unit_dbus_path(j->unit);
    1541         [ #  # ]:          0 :         if (!unit_path)
    1542                 :          0 :                 return -ENOMEM;
    1543                 :            : 
    1544                 :          0 :         r = sd_bus_message_append(reply, "uosos",
    1545                 :          0 :                                   j->id, job_path,
    1546                 :          0 :                                   j->unit->id, unit_path,
    1547                 :          0 :                                   job_type_to_string(j->type));
    1548         [ #  # ]:          0 :         if (r < 0)
    1549                 :          0 :                 return r;
    1550                 :            : 
    1551                 :          0 :         r = sd_bus_message_open_container(reply, 'a', "(uosos)");
    1552         [ #  # ]:          0 :         if (r < 0)
    1553                 :          0 :                 return r;
    1554                 :            : 
    1555         [ #  # ]:          0 :         SET_FOREACH(a, affected, i) {
    1556                 :            : 
    1557         [ #  # ]:          0 :                 if (a->id == j->id)
    1558                 :          0 :                         continue;
    1559                 :            : 
    1560                 :            :                 /* Free paths from previous iteration */
    1561                 :          0 :                 job_path = mfree(job_path);
    1562                 :          0 :                 unit_path = mfree(unit_path);
    1563                 :            : 
    1564                 :          0 :                 job_path = job_dbus_path(a);
    1565         [ #  # ]:          0 :                 if (!job_path)
    1566                 :          0 :                         return -ENOMEM;
    1567                 :            : 
    1568                 :          0 :                 unit_path = unit_dbus_path(a->unit);
    1569         [ #  # ]:          0 :                 if (!unit_path)
    1570                 :          0 :                         return -ENOMEM;
    1571                 :            : 
    1572                 :          0 :                 r = sd_bus_message_append(reply, "(uosos)",
    1573                 :          0 :                                           a->id, job_path,
    1574                 :          0 :                                           a->unit->id, unit_path,
    1575                 :          0 :                                           job_type_to_string(a->type));
    1576         [ #  # ]:          0 :                 if (r < 0)
    1577                 :          0 :                         return r;
    1578                 :            :         }
    1579                 :            : 
    1580                 :          0 :         r = sd_bus_message_close_container(reply);
    1581         [ #  # ]:          0 :         if (r < 0)
    1582                 :          0 :                 return r;
    1583                 :            : 
    1584                 :          0 :         return sd_bus_send(NULL, reply, NULL);
    1585                 :            : }
    1586                 :            : 
    1587                 :          0 : static int bus_unit_set_live_property(
    1588                 :            :                 Unit *u,
    1589                 :            :                 const char *name,
    1590                 :            :                 sd_bus_message *message,
    1591                 :            :                 UnitWriteFlags flags,
    1592                 :            :                 sd_bus_error *error) {
    1593                 :            : 
    1594                 :            :         int r;
    1595                 :            : 
    1596         [ #  # ]:          0 :         assert(u);
    1597         [ #  # ]:          0 :         assert(name);
    1598         [ #  # ]:          0 :         assert(message);
    1599                 :            : 
    1600                 :            :         /* Handles setting properties both "live" (i.e. at any time during runtime), and during creation (for transient
    1601                 :            :          * units that are being created). */
    1602                 :            : 
    1603         [ #  # ]:          0 :         if (streq(name, "Description")) {
    1604                 :            :                 const char *d;
    1605                 :            : 
    1606                 :          0 :                 r = sd_bus_message_read(message, "s", &d);
    1607         [ #  # ]:          0 :                 if (r < 0)
    1608                 :          0 :                         return r;
    1609                 :            : 
    1610         [ #  # ]:          0 :                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
    1611                 :          0 :                         r = unit_set_description(u, d);
    1612         [ #  # ]:          0 :                         if (r < 0)
    1613                 :          0 :                                 return r;
    1614                 :            : 
    1615                 :          0 :                         unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "Description=%s", d);
    1616                 :            :                 }
    1617                 :            : 
    1618                 :          0 :                 return 1;
    1619                 :            :         }
    1620                 :            : 
    1621                 :          0 :         return 0;
    1622                 :            : }
    1623                 :            : 
    1624                 :          0 : static int bus_set_transient_emergency_action(
    1625                 :            :                 Unit *u,
    1626                 :            :                 const char *name,
    1627                 :            :                 EmergencyAction *p,
    1628                 :            :                 sd_bus_message *message,
    1629                 :            :                 UnitWriteFlags flags,
    1630                 :            :                 sd_bus_error *error) {
    1631                 :            : 
    1632                 :            :         const char *s;
    1633                 :            :         EmergencyAction v;
    1634                 :            :         int r;
    1635                 :            :         bool system;
    1636                 :            : 
    1637         [ #  # ]:          0 :         assert(p);
    1638                 :            : 
    1639                 :          0 :         r = sd_bus_message_read(message, "s", &s);
    1640         [ #  # ]:          0 :         if (r < 0)
    1641                 :          0 :                 return r;
    1642                 :            : 
    1643                 :          0 :         system = MANAGER_IS_SYSTEM(u->manager);
    1644                 :          0 :         r = parse_emergency_action(s, system, &v);
    1645         [ #  # ]:          0 :         if (r < 0)
    1646         [ #  # ]:          0 :                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
    1647                 :            :                                          r == -EOPNOTSUPP ? "%s setting invalid for manager type: %s"
    1648                 :            :                                                           : "Invalid %s setting: %s",
    1649                 :            :                                          name, s);
    1650                 :            : 
    1651         [ #  # ]:          0 :         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
    1652                 :          0 :                 *p = v;
    1653                 :          0 :                 unit_write_settingf(u, flags, name,
    1654                 :            :                                     "%s=%s", name, s);
    1655                 :            :         }
    1656                 :            : 
    1657                 :          0 :         return 1;
    1658                 :            : }
    1659                 :            : 
    1660                 :          0 : static int bus_set_transient_exit_status(
    1661                 :            :                 Unit *u,
    1662                 :            :                 const char *name,
    1663                 :            :                 int *p,
    1664                 :            :                 sd_bus_message *message,
    1665                 :            :                 UnitWriteFlags flags,
    1666                 :            :                 sd_bus_error *error) {
    1667                 :            : 
    1668                 :            :         int32_t k;
    1669                 :            :         int r;
    1670                 :            : 
    1671         [ #  # ]:          0 :         assert(p);
    1672                 :            : 
    1673                 :          0 :         r = sd_bus_message_read(message, "i", &k);
    1674         [ #  # ]:          0 :         if (r < 0)
    1675                 :          0 :                 return r;
    1676                 :            : 
    1677         [ #  # ]:          0 :         if (k > 255)
    1678                 :          0 :                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Exit status must be in range 0…255 or negative.");
    1679                 :            : 
    1680         [ #  # ]:          0 :         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
    1681                 :          0 :                 *p = k < 0 ? -1 : k;
    1682                 :            : 
    1683         [ #  # ]:          0 :                 if (k < 0)
    1684                 :          0 :                         unit_write_settingf(u, flags, name, "%s=", name);
    1685                 :            :                 else
    1686                 :          0 :                         unit_write_settingf(u, flags, name, "%s=%i", name, k);
    1687                 :            :         }
    1688                 :            : 
    1689                 :          0 :         return 1;
    1690                 :            : }
    1691                 :            : 
    1692   [ #  #  #  #  :          0 : static BUS_DEFINE_SET_TRANSIENT_PARSE(collect_mode, CollectMode, collect_mode_from_string);
             #  #  #  # ]
    1693   [ #  #  #  #  :          0 : static BUS_DEFINE_SET_TRANSIENT_PARSE(job_mode, JobMode, job_mode_from_string);
             #  #  #  # ]
    1694                 :            : 
    1695                 :          0 : static int bus_set_transient_conditions(
    1696                 :            :                 Unit *u,
    1697                 :            :                 const char *name,
    1698                 :            :                 Condition **list,
    1699                 :            :                 bool is_condition,
    1700                 :            :                 sd_bus_message *message,
    1701                 :            :                 UnitWriteFlags flags,
    1702                 :            :                 sd_bus_error *error) {
    1703                 :            : 
    1704                 :            :         const char *type_name, *param;
    1705                 :            :         int trigger, negate, r;
    1706                 :          0 :         bool empty = true;
    1707                 :            : 
    1708         [ #  # ]:          0 :         assert(list);
    1709                 :            : 
    1710                 :          0 :         r = sd_bus_message_enter_container(message, 'a', "(sbbs)");
    1711         [ #  # ]:          0 :         if (r < 0)
    1712                 :          0 :                 return r;
    1713                 :            : 
    1714         [ #  # ]:          0 :         while ((r = sd_bus_message_read(message, "(sbbs)", &type_name, &trigger, &negate, &param)) > 0) {
    1715                 :            :                 ConditionType t;
    1716                 :            : 
    1717         [ #  # ]:          0 :                 t = is_condition ? condition_type_from_string(type_name) : assert_type_from_string(type_name);
    1718         [ #  # ]:          0 :                 if (t < 0)
    1719                 :          0 :                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid condition type: %s", type_name);
    1720                 :            : 
    1721         [ #  # ]:          0 :                 if (t != CONDITION_NULL) {
    1722         [ #  # ]:          0 :                         if (isempty(param))
    1723                 :          0 :                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Condition parameter in %s is empty", type_name);
    1724                 :            : 
    1725   [ #  #  #  # ]:          0 :                         if (condition_takes_path(t) && !path_is_absolute(param))
    1726                 :          0 :                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path in condition %s is not absolute: %s", type_name, param);
    1727                 :            :                 } else
    1728                 :          0 :                         param = NULL;
    1729                 :            : 
    1730         [ #  # ]:          0 :                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
    1731                 :            :                         Condition *c;
    1732                 :            : 
    1733                 :          0 :                         c = condition_new(t, param, trigger, negate);
    1734         [ #  # ]:          0 :                         if (!c)
    1735                 :          0 :                                 return -ENOMEM;
    1736                 :            : 
    1737   [ #  #  #  # ]:          0 :                         LIST_PREPEND(conditions, *list, c);
    1738                 :            : 
    1739         [ #  # ]:          0 :                         if (t != CONDITION_NULL)
    1740                 :          0 :                                 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name,
    1741                 :            :                                                     "%s=%s%s%s", type_name,
    1742   [ #  #  #  # ]:          0 :                                                     trigger ? "|" : "", negate ? "!" : "", param);
    1743                 :            :                         else
    1744                 :          0 :                                 unit_write_settingf(u, flags, name,
    1745                 :            :                                                     "%s=%s%s", type_name,
    1746         [ #  # ]:          0 :                                                     trigger ? "|" : "", yes_no(!negate));
    1747                 :            :                 }
    1748                 :            : 
    1749                 :          0 :                 empty = false;
    1750                 :            :         }
    1751         [ #  # ]:          0 :         if (r < 0)
    1752                 :          0 :                 return r;
    1753                 :            : 
    1754                 :          0 :         r = sd_bus_message_exit_container(message);
    1755         [ #  # ]:          0 :         if (r < 0)
    1756                 :          0 :                 return r;
    1757                 :            : 
    1758   [ #  #  #  # ]:          0 :         if (!UNIT_WRITE_FLAGS_NOOP(flags) && empty) {
    1759                 :          0 :                 *list = condition_free_list(*list);
    1760         [ #  # ]:          0 :                 unit_write_settingf(u, flags, name, "%sNull=", is_condition ? "Condition" : "Assert");
    1761                 :            :         }
    1762                 :            : 
    1763                 :          0 :         return 1;
    1764                 :            : }
    1765                 :            : 
    1766                 :          0 : static int bus_unit_set_transient_property(
    1767                 :            :                 Unit *u,
    1768                 :            :                 const char *name,
    1769                 :            :                 sd_bus_message *message,
    1770                 :            :                 UnitWriteFlags flags,
    1771                 :            :                 sd_bus_error *error) {
    1772                 :            : 
    1773                 :          0 :         UnitDependency d = _UNIT_DEPENDENCY_INVALID;
    1774                 :            :         int r;
    1775                 :            : 
    1776         [ #  # ]:          0 :         assert(u);
    1777         [ #  # ]:          0 :         assert(name);
    1778         [ #  # ]:          0 :         assert(message);
    1779                 :            : 
    1780                 :            :         /* Handles settings when transient units are created. This settings cannot be altered anymore after the unit
    1781                 :            :          * has been created. */
    1782                 :            : 
    1783         [ #  # ]:          0 :         if (streq(name, "SourcePath"))
    1784                 :          0 :                 return bus_set_transient_path(u, name, &u->source_path, message, flags, error);
    1785                 :            : 
    1786         [ #  # ]:          0 :         if (streq(name, "StopWhenUnneeded"))
    1787                 :          0 :                 return bus_set_transient_bool(u, name, &u->stop_when_unneeded, message, flags, error);
    1788                 :            : 
    1789         [ #  # ]:          0 :         if (streq(name, "RefuseManualStart"))
    1790                 :          0 :                 return bus_set_transient_bool(u, name, &u->refuse_manual_start, message, flags, error);
    1791                 :            : 
    1792         [ #  # ]:          0 :         if (streq(name, "RefuseManualStop"))
    1793                 :          0 :                 return bus_set_transient_bool(u, name, &u->refuse_manual_stop, message, flags, error);
    1794                 :            : 
    1795         [ #  # ]:          0 :         if (streq(name, "AllowIsolate"))
    1796                 :          0 :                 return bus_set_transient_bool(u, name, &u->allow_isolate, message, flags, error);
    1797                 :            : 
    1798         [ #  # ]:          0 :         if (streq(name, "DefaultDependencies"))
    1799                 :          0 :                 return bus_set_transient_bool(u, name, &u->default_dependencies, message, flags, error);
    1800                 :            : 
    1801         [ #  # ]:          0 :         if (streq(name, "OnFailureJobMode"))
    1802                 :          0 :                 return bus_set_transient_job_mode(u, name, &u->on_failure_job_mode, message, flags, error);
    1803                 :            : 
    1804         [ #  # ]:          0 :         if (streq(name, "IgnoreOnIsolate"))
    1805                 :          0 :                 return bus_set_transient_bool(u, name, &u->ignore_on_isolate, message, flags, error);
    1806                 :            : 
    1807         [ #  # ]:          0 :         if (streq(name, "JobTimeoutUSec")) {
    1808                 :          0 :                 r = bus_set_transient_usec_fix_0(u, name, &u->job_timeout, message, flags, error);
    1809   [ #  #  #  #  :          0 :                 if (r >= 0 && !UNIT_WRITE_FLAGS_NOOP(flags) && !u->job_running_timeout_set)
                   #  # ]
    1810                 :          0 :                         u->job_running_timeout = u->job_timeout;
    1811                 :            :         }
    1812                 :            : 
    1813         [ #  # ]:          0 :         if (streq(name, "JobRunningTimeoutUSec")) {
    1814                 :          0 :                 r = bus_set_transient_usec_fix_0(u, name, &u->job_running_timeout, message, flags, error);
    1815   [ #  #  #  # ]:          0 :                 if (r >= 0 && !UNIT_WRITE_FLAGS_NOOP(flags))
    1816                 :          0 :                         u->job_running_timeout_set = true;
    1817                 :            : 
    1818                 :          0 :                 return r;
    1819                 :            :         }
    1820                 :            : 
    1821         [ #  # ]:          0 :         if (streq(name, "JobTimeoutAction"))
    1822                 :          0 :                 return bus_set_transient_emergency_action(u, name, &u->job_timeout_action, message, flags, error);
    1823                 :            : 
    1824         [ #  # ]:          0 :         if (streq(name, "JobTimeoutRebootArgument"))
    1825                 :          0 :                 return bus_set_transient_string(u, name, &u->job_timeout_reboot_arg, message, flags, error);
    1826                 :            : 
    1827         [ #  # ]:          0 :         if (streq(name, "StartLimitIntervalUSec"))
    1828                 :          0 :                 return bus_set_transient_usec(u, name, &u->start_limit.interval, message, flags, error);
    1829                 :            : 
    1830         [ #  # ]:          0 :         if (streq(name, "StartLimitBurst"))
    1831                 :          0 :                 return bus_set_transient_unsigned(u, name, &u->start_limit.burst, message, flags, error);
    1832                 :            : 
    1833         [ #  # ]:          0 :         if (streq(name, "StartLimitAction"))
    1834                 :          0 :                 return bus_set_transient_emergency_action(u, name, &u->start_limit_action, message, flags, error);
    1835                 :            : 
    1836         [ #  # ]:          0 :         if (streq(name, "FailureAction"))
    1837                 :          0 :                 return bus_set_transient_emergency_action(u, name, &u->failure_action, message, flags, error);
    1838                 :            : 
    1839         [ #  # ]:          0 :         if (streq(name, "SuccessAction"))
    1840                 :          0 :                 return bus_set_transient_emergency_action(u, name, &u->success_action, message, flags, error);
    1841                 :            : 
    1842         [ #  # ]:          0 :         if (streq(name, "FailureActionExitStatus"))
    1843                 :          0 :                 return bus_set_transient_exit_status(u, name, &u->failure_action_exit_status, message, flags, error);
    1844                 :            : 
    1845         [ #  # ]:          0 :         if (streq(name, "SuccessActionExitStatus"))
    1846                 :          0 :                 return bus_set_transient_exit_status(u, name, &u->success_action_exit_status, message, flags, error);
    1847                 :            : 
    1848         [ #  # ]:          0 :         if (streq(name, "RebootArgument"))
    1849                 :          0 :                 return bus_set_transient_string(u, name, &u->reboot_arg, message, flags, error);
    1850                 :            : 
    1851         [ #  # ]:          0 :         if (streq(name, "CollectMode"))
    1852                 :          0 :                 return bus_set_transient_collect_mode(u, name, &u->collect_mode, message, flags, error);
    1853                 :            : 
    1854         [ #  # ]:          0 :         if (streq(name, "Conditions"))
    1855                 :          0 :                 return bus_set_transient_conditions(u, name, &u->conditions, true, message, flags, error);
    1856                 :            : 
    1857         [ #  # ]:          0 :         if (streq(name, "Asserts"))
    1858                 :          0 :                 return bus_set_transient_conditions(u, name, &u->asserts, false, message, flags, error);
    1859                 :            : 
    1860         [ #  # ]:          0 :         if (streq(name, "Documentation")) {
    1861                 :          0 :                 _cleanup_strv_free_ char **l = NULL;
    1862                 :            :                 char **p;
    1863                 :            : 
    1864                 :          0 :                 r = sd_bus_message_read_strv(message, &l);
    1865         [ #  # ]:          0 :                 if (r < 0)
    1866                 :          0 :                         return r;
    1867                 :            : 
    1868   [ #  #  #  # ]:          0 :                 STRV_FOREACH(p, l) {
    1869         [ #  # ]:          0 :                         if (!documentation_url_is_valid(*p))
    1870                 :          0 :                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid URL in %s: %s", name, *p);
    1871                 :            :                 }
    1872                 :            : 
    1873         [ #  # ]:          0 :                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
    1874         [ #  # ]:          0 :                         if (strv_isempty(l)) {
    1875                 :          0 :                                 u->documentation = strv_free(u->documentation);
    1876                 :          0 :                                 unit_write_settingf(u, flags, name, "%s=", name);
    1877                 :            :                         } else {
    1878                 :          0 :                                 strv_extend_strv(&u->documentation, l, false);
    1879                 :            : 
    1880   [ #  #  #  # ]:          0 :                                 STRV_FOREACH(p, l)
    1881                 :          0 :                                         unit_write_settingf(u, flags, name, "%s=%s", name, *p);
    1882                 :            :                         }
    1883                 :            :                 }
    1884                 :            : 
    1885                 :          0 :                 return 1;
    1886                 :            : 
    1887         [ #  # ]:          0 :         } else if (streq(name, "Slice")) {
    1888                 :            :                 Unit *slice;
    1889                 :            :                 const char *s;
    1890                 :            : 
    1891         [ #  # ]:          0 :                 if (!UNIT_HAS_CGROUP_CONTEXT(u))
    1892                 :          0 :                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "The slice property is only available for units with control groups.");
    1893         [ #  # ]:          0 :                 if (u->type == UNIT_SLICE)
    1894                 :          0 :                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Slice may not be set for slice units.");
    1895         [ #  # ]:          0 :                 if (unit_has_name(u, SPECIAL_INIT_SCOPE))
    1896                 :          0 :                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot set slice for init.scope");
    1897                 :            : 
    1898                 :          0 :                 r = sd_bus_message_read(message, "s", &s);
    1899         [ #  # ]:          0 :                 if (r < 0)
    1900                 :          0 :                         return r;
    1901                 :            : 
    1902         [ #  # ]:          0 :                 if (!unit_name_is_valid(s, UNIT_NAME_PLAIN))
    1903                 :          0 :                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name '%s'", s);
    1904                 :            : 
    1905                 :            :                 /* Note that we do not dispatch the load queue here yet, as we don't want our own transient unit to be
    1906                 :            :                  * loaded while we are still setting it up. Or in other words, we use manager_load_unit_prepare()
    1907                 :            :                  * instead of manager_load_unit() on purpose, here. */
    1908                 :          0 :                 r = manager_load_unit_prepare(u->manager, s, NULL, error, &slice);
    1909         [ #  # ]:          0 :                 if (r < 0)
    1910                 :          0 :                         return r;
    1911                 :            : 
    1912         [ #  # ]:          0 :                 if (slice->type != UNIT_SLICE)
    1913                 :          0 :                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit name '%s' is not a slice", s);
    1914                 :            : 
    1915         [ #  # ]:          0 :                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
    1916                 :          0 :                         r = unit_set_slice(u, slice);
    1917         [ #  # ]:          0 :                         if (r < 0)
    1918                 :          0 :                                 return r;
    1919                 :            : 
    1920                 :          0 :                         unit_write_settingf(u, flags|UNIT_PRIVATE, name, "Slice=%s", s);
    1921                 :            :                 }
    1922                 :            : 
    1923                 :          0 :                 return 1;
    1924                 :            : 
    1925         [ #  # ]:          0 :         } else if (streq(name, "RequiresMountsFor")) {
    1926                 :          0 :                 _cleanup_strv_free_ char **l = NULL;
    1927                 :            :                 char **p;
    1928                 :            : 
    1929                 :          0 :                 r = sd_bus_message_read_strv(message, &l);
    1930         [ #  # ]:          0 :                 if (r < 0)
    1931                 :          0 :                         return r;
    1932                 :            : 
    1933   [ #  #  #  # ]:          0 :                 STRV_FOREACH(p, l) {
    1934                 :          0 :                         path_simplify(*p, true);
    1935                 :            : 
    1936         [ #  # ]:          0 :                         if (!path_is_absolute(*p))
    1937                 :          0 :                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path specified in %s is not absolute: %s", name, *p);
    1938                 :            : 
    1939         [ #  # ]:          0 :                         if (!path_is_valid(*p))
    1940                 :          0 :                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path specified in %s has invalid length: %s", name, *p);
    1941                 :            : 
    1942         [ #  # ]:          0 :                         if (!path_is_normalized(*p))
    1943                 :          0 :                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path specified in %s is not normalized: %s", name, *p);
    1944                 :            : 
    1945         [ #  # ]:          0 :                         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
    1946                 :          0 :                                 r = unit_require_mounts_for(u, *p, UNIT_DEPENDENCY_FILE);
    1947         [ #  # ]:          0 :                                 if (r < 0)
    1948                 :          0 :                                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Failed to add required mount \"%s\": %m", *p);
    1949                 :            : 
    1950                 :          0 :                                 unit_write_settingf(u, flags, name, "%s=%s", name, *p);
    1951                 :            :                         }
    1952                 :            :                 }
    1953                 :            : 
    1954                 :          0 :                 return 1;
    1955                 :            :         }
    1956                 :            : 
    1957         [ #  # ]:          0 :         if (streq(name, "RequiresOverridable"))
    1958                 :          0 :                 d = UNIT_REQUIRES; /* redirect for obsolete unit dependency type */
    1959         [ #  # ]:          0 :         else if (streq(name, "RequisiteOverridable"))
    1960                 :          0 :                 d = UNIT_REQUISITE; /* same here */
    1961                 :            :         else
    1962                 :          0 :                 d = unit_dependency_from_string(name);
    1963                 :            : 
    1964         [ #  # ]:          0 :         if (d >= 0) {
    1965                 :            :                 const char *other;
    1966                 :            : 
    1967                 :          0 :                 r = sd_bus_message_enter_container(message, 'a', "s");
    1968         [ #  # ]:          0 :                 if (r < 0)
    1969                 :          0 :                         return r;
    1970                 :            : 
    1971         [ #  # ]:          0 :                 while ((r = sd_bus_message_read(message, "s", &other)) > 0) {
    1972         [ #  # ]:          0 :                         if (!unit_name_is_valid(other, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE))
    1973                 :          0 :                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name %s", other);
    1974                 :            : 
    1975         [ #  # ]:          0 :                         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
    1976         [ #  # ]:          0 :                                 _cleanup_free_ char *label = NULL;
    1977                 :            : 
    1978                 :          0 :                                 r = unit_add_dependency_by_name(u, d, other, true, UNIT_DEPENDENCY_FILE);
    1979         [ #  # ]:          0 :                                 if (r < 0)
    1980                 :          0 :                                         return r;
    1981                 :            : 
    1982                 :          0 :                                 label = strjoin(name, "-", other);
    1983         [ #  # ]:          0 :                                 if (!label)
    1984                 :          0 :                                         return -ENOMEM;
    1985                 :            : 
    1986                 :          0 :                                 unit_write_settingf(u, flags, label, "%s=%s", unit_dependency_to_string(d), other);
    1987                 :            :                         }
    1988                 :            : 
    1989                 :            :                 }
    1990         [ #  # ]:          0 :                 if (r < 0)
    1991                 :          0 :                         return r;
    1992                 :            : 
    1993                 :          0 :                 r = sd_bus_message_exit_container(message);
    1994         [ #  # ]:          0 :                 if (r < 0)
    1995                 :          0 :                         return r;
    1996                 :            : 
    1997                 :          0 :                 return 1;
    1998                 :            : 
    1999         [ #  # ]:          0 :         } else if (streq(name, "AddRef")) {
    2000                 :            : 
    2001                 :            :                 int b;
    2002                 :            : 
    2003                 :            :                 /* Why is this called "AddRef" rather than just "Ref", or "Reference"? There's already a "Ref()" method
    2004                 :            :                  * on the Unit interface, and it's probably not a good idea to expose a property and a method on the
    2005                 :            :                  * same interface (well, strictly speaking AddRef isn't exposed as full property, we just read it for
    2006                 :            :                  * transient units, but still). And "References" and "ReferencedBy" is already used as unit reference
    2007                 :            :                  * dependency type, hence let's not confuse things with that.
    2008                 :            :                  *
    2009                 :            :                  * Note that we don't actually add the reference to the bus track. We do that only after the setup of
    2010                 :            :                  * the transient unit is complete, so that setting this property multiple times in the same transient
    2011                 :            :                  * unit creation call doesn't count as individual references. */
    2012                 :            : 
    2013                 :          0 :                 r = sd_bus_message_read(message, "b", &b);
    2014         [ #  # ]:          0 :                 if (r < 0)
    2015                 :          0 :                         return r;
    2016                 :            : 
    2017         [ #  # ]:          0 :                 if (!UNIT_WRITE_FLAGS_NOOP(flags))
    2018                 :          0 :                         u->bus_track_add = b;
    2019                 :            : 
    2020                 :          0 :                 return 1;
    2021                 :            :         }
    2022                 :            : 
    2023                 :          0 :         return 0;
    2024                 :            : }
    2025                 :            : 
    2026                 :          0 : int bus_unit_set_properties(
    2027                 :            :                 Unit *u,
    2028                 :            :                 sd_bus_message *message,
    2029                 :            :                 UnitWriteFlags flags,
    2030                 :            :                 bool commit,
    2031                 :            :                 sd_bus_error *error) {
    2032                 :            : 
    2033                 :          0 :         bool for_real = false;
    2034                 :          0 :         unsigned n = 0;
    2035                 :            :         int r;
    2036                 :            : 
    2037         [ #  # ]:          0 :         assert(u);
    2038         [ #  # ]:          0 :         assert(message);
    2039                 :            : 
    2040                 :            :         /* We iterate through the array twice. First run we just check
    2041                 :            :          * if all passed data is valid, second run actually applies
    2042                 :            :          * it. This is to implement transaction-like behaviour without
    2043                 :            :          * actually providing full transactions. */
    2044                 :            : 
    2045                 :          0 :         r = sd_bus_message_enter_container(message, 'a', "(sv)");
    2046         [ #  # ]:          0 :         if (r < 0)
    2047                 :          0 :                 return r;
    2048                 :            : 
    2049                 :          0 :         for (;;) {
    2050                 :            :                 const char *name;
    2051                 :            :                 UnitWriteFlags f;
    2052                 :            : 
    2053                 :          0 :                 r = sd_bus_message_enter_container(message, 'r', "sv");
    2054         [ #  # ]:          0 :                 if (r < 0)
    2055                 :          0 :                         return r;
    2056         [ #  # ]:          0 :                 if (r == 0) {
    2057   [ #  #  #  # ]:          0 :                         if (for_real || UNIT_WRITE_FLAGS_NOOP(flags))
    2058                 :            :                                 break;
    2059                 :            : 
    2060                 :            :                         /* Reached EOF. Let's try again, and this time for realz... */
    2061                 :          0 :                         r = sd_bus_message_rewind(message, false);
    2062         [ #  # ]:          0 :                         if (r < 0)
    2063                 :          0 :                                 return r;
    2064                 :            : 
    2065                 :          0 :                         for_real = true;
    2066                 :          0 :                         continue;
    2067                 :            :                 }
    2068                 :            : 
    2069                 :          0 :                 r = sd_bus_message_read(message, "s", &name);
    2070         [ #  # ]:          0 :                 if (r < 0)
    2071                 :          0 :                         return r;
    2072                 :            : 
    2073         [ #  # ]:          0 :                 if (!UNIT_VTABLE(u)->bus_set_property)
    2074                 :          0 :                         return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Objects of this type do not support setting properties.");
    2075                 :            : 
    2076                 :          0 :                 r = sd_bus_message_enter_container(message, 'v', NULL);
    2077         [ #  # ]:          0 :                 if (r < 0)
    2078                 :          0 :                         return r;
    2079                 :            : 
    2080                 :            :                 /* If not for real, then mask out the two target flags */
    2081         [ #  # ]:          0 :                 f = for_real ? flags : (flags & ~(UNIT_RUNTIME|UNIT_PERSISTENT));
    2082                 :            : 
    2083                 :          0 :                 r = UNIT_VTABLE(u)->bus_set_property(u, name, message, f, error);
    2084   [ #  #  #  #  :          0 :                 if (r == 0 && u->transient && u->load_state == UNIT_STUB)
                   #  # ]
    2085                 :          0 :                         r = bus_unit_set_transient_property(u, name, message, f, error);
    2086         [ #  # ]:          0 :                 if (r == 0)
    2087                 :          0 :                         r = bus_unit_set_live_property(u, name, message, f, error);
    2088         [ #  # ]:          0 :                 if (r < 0)
    2089                 :          0 :                         return r;
    2090                 :            : 
    2091         [ #  # ]:          0 :                 if (r == 0)
    2092                 :          0 :                         return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Cannot set property %s, or unknown property.", name);
    2093                 :            : 
    2094                 :          0 :                 r = sd_bus_message_exit_container(message);
    2095         [ #  # ]:          0 :                 if (r < 0)
    2096                 :          0 :                         return r;
    2097                 :            : 
    2098                 :          0 :                 r = sd_bus_message_exit_container(message);
    2099         [ #  # ]:          0 :                 if (r < 0)
    2100                 :          0 :                         return r;
    2101                 :            : 
    2102                 :          0 :                 n += for_real;
    2103                 :            :         }
    2104                 :            : 
    2105                 :          0 :         r = sd_bus_message_exit_container(message);
    2106         [ #  # ]:          0 :         if (r < 0)
    2107                 :          0 :                 return r;
    2108                 :            : 
    2109   [ #  #  #  #  :          0 :         if (commit && n > 0 && UNIT_VTABLE(u)->bus_commit_properties)
                   #  # ]
    2110                 :          0 :                 UNIT_VTABLE(u)->bus_commit_properties(u);
    2111                 :            : 
    2112                 :          0 :         return n;
    2113                 :            : }
    2114                 :            : 
    2115                 :       1136 : int bus_unit_validate_load_state(Unit *u, sd_bus_error *error) {
    2116         [ -  + ]:       1136 :         assert(u);
    2117                 :            : 
    2118                 :            :         /* Generates a pretty error if a unit isn't properly loaded. */
    2119                 :            : 
    2120   [ +  +  -  -  :       1136 :         switch (u->load_state) {
                   -  - ]
    2121                 :            : 
    2122                 :        856 :         case UNIT_LOADED:
    2123                 :        856 :                 return 0;
    2124                 :            : 
    2125                 :        280 :         case UNIT_NOT_FOUND:
    2126                 :        280 :                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not found.", u->id);
    2127                 :            : 
    2128                 :          0 :         case UNIT_BAD_SETTING:
    2129                 :          0 :                 return sd_bus_error_setf(error, BUS_ERROR_BAD_UNIT_SETTING, "Unit %s has a bad unit file setting.", u->id);
    2130                 :            : 
    2131                 :          0 :         case UNIT_ERROR: /* Only show .load_error in UNIT_ERROR state */
    2132                 :          0 :                 return sd_bus_error_set_errnof(error, u->load_error, "Unit %s failed to load properly: %m.", u->id);
    2133                 :            : 
    2134                 :          0 :         case UNIT_MASKED:
    2135                 :          0 :                 return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit %s is masked.", u->id);
    2136                 :            : 
    2137                 :          0 :         case UNIT_STUB:
    2138                 :            :         case UNIT_MERGED:
    2139                 :            :         default:
    2140                 :          0 :                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unexpected load state of unit %s", u->id);
    2141                 :            :         }
    2142                 :            : }
    2143                 :            : 
    2144                 :          0 : static int bus_unit_track_handler(sd_bus_track *t, void *userdata) {
    2145                 :          0 :         Unit *u = userdata;
    2146                 :            : 
    2147         [ #  # ]:          0 :         assert(t);
    2148         [ #  # ]:          0 :         assert(u);
    2149                 :            : 
    2150                 :          0 :         u->bus_track = sd_bus_track_unref(u->bus_track); /* make sure we aren't called again */
    2151                 :            : 
    2152                 :            :         /* If the client that tracks us disappeared, then there's reason to believe that the cgroup is empty now too,
    2153                 :            :          * let's see */
    2154                 :          0 :         unit_add_to_cgroup_empty_queue(u);
    2155                 :            : 
    2156                 :            :         /* Also add the unit to the GC queue, after all if the client left it might be time to GC this unit */
    2157                 :          0 :         unit_add_to_gc_queue(u);
    2158                 :            : 
    2159                 :          0 :         return 0;
    2160                 :            : }
    2161                 :            : 
    2162                 :          0 : static int bus_unit_allocate_bus_track(Unit *u) {
    2163                 :            :         int r;
    2164                 :            : 
    2165         [ #  # ]:          0 :         assert(u);
    2166                 :            : 
    2167         [ #  # ]:          0 :         if (u->bus_track)
    2168                 :          0 :                 return 0;
    2169                 :            : 
    2170                 :          0 :         r = sd_bus_track_new(u->manager->api_bus, &u->bus_track, bus_unit_track_handler, u);
    2171         [ #  # ]:          0 :         if (r < 0)
    2172                 :          0 :                 return r;
    2173                 :            : 
    2174                 :          0 :         r = sd_bus_track_set_recursive(u->bus_track, true);
    2175         [ #  # ]:          0 :         if (r < 0) {
    2176                 :          0 :                 u->bus_track = sd_bus_track_unref(u->bus_track);
    2177                 :          0 :                 return r;
    2178                 :            :         }
    2179                 :            : 
    2180                 :          0 :         return 0;
    2181                 :            : }
    2182                 :            : 
    2183                 :          0 : int bus_unit_track_add_name(Unit *u, const char *name) {
    2184                 :            :         int r;
    2185                 :            : 
    2186         [ #  # ]:          0 :         assert(u);
    2187                 :            : 
    2188                 :          0 :         r = bus_unit_allocate_bus_track(u);
    2189         [ #  # ]:          0 :         if (r < 0)
    2190                 :          0 :                 return r;
    2191                 :            : 
    2192                 :          0 :         return sd_bus_track_add_name(u->bus_track, name);
    2193                 :            : }
    2194                 :            : 
    2195                 :          0 : int bus_unit_track_add_sender(Unit *u, sd_bus_message *m) {
    2196                 :            :         int r;
    2197                 :            : 
    2198         [ #  # ]:          0 :         assert(u);
    2199                 :            : 
    2200                 :          0 :         r = bus_unit_allocate_bus_track(u);
    2201         [ #  # ]:          0 :         if (r < 0)
    2202                 :          0 :                 return r;
    2203                 :            : 
    2204                 :          0 :         return sd_bus_track_add_sender(u->bus_track, m);
    2205                 :            : }
    2206                 :            : 
    2207                 :          0 : int bus_unit_track_remove_sender(Unit *u, sd_bus_message *m) {
    2208         [ #  # ]:          0 :         assert(u);
    2209                 :            : 
    2210                 :            :         /* If we haven't allocated the bus track object yet, then there's definitely no reference taken yet, return an
    2211                 :            :          * error */
    2212         [ #  # ]:          0 :         if (!u->bus_track)
    2213                 :          0 :                 return -EUNATCH;
    2214                 :            : 
    2215                 :          0 :         return sd_bus_track_remove_sender(u->bus_track, m);
    2216                 :            : }

Generated by: LCOV version 1.14