LCOV - code coverage report
Current view: top level - core - dbus-unit.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 26 1055 2.5 %
Date: 2019-08-22 15:41:25 Functions: 4 75 5.3 %

          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           5 : void bus_unit_send_change_signal(Unit *u) {
    1382             :         int r;
    1383           5 :         assert(u);
    1384             : 
    1385           5 :         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           5 :         if (!u->id)
    1391           2 :                 return;
    1392             : 
    1393           3 :         r = bus_foreach_bus(u->manager, u->bus_track, u->sent_dbus_new_signal ? send_changed_signal : send_new_signal, u);
    1394           3 :         if (r < 0)
    1395           0 :                 log_unit_debug_errno(u, r, "Failed to send unit change signal for %s: %m", u->id);
    1396             : 
    1397           3 :         u->sent_dbus_new_signal = true;
    1398             : }
    1399             : 
    1400        1849 : 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        1849 :         if (!u->in_dbus_queue) /* If not enqueued, don't bother */
    1407        1849 :                 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        2160 : void bus_unit_send_removed_signal(Unit *u) {
    1451             :         int r;
    1452        2160 :         assert(u);
    1453             : 
    1454        2160 :         if (!u->sent_dbus_new_signal || u->in_dbus_queue)
    1455           5 :                 bus_unit_send_change_signal(u);
    1456             : 
    1457        2160 :         if (!u->id)
    1458           2 :                 return;
    1459             : 
    1460        2158 :         r = bus_foreach_bus(u->manager, u->bus_track, send_removed_signal, u);
    1461        2158 :         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         284 : int bus_unit_validate_load_state(Unit *u, sd_bus_error *error) {
    2116         284 :         assert(u);
    2117             : 
    2118             :         /* Generates a pretty error if a unit isn't properly loaded. */
    2119             : 
    2120         284 :         switch (u->load_state) {
    2121             : 
    2122         214 :         case UNIT_LOADED:
    2123         214 :                 return 0;
    2124             : 
    2125          70 :         case UNIT_NOT_FOUND:
    2126          70 :                 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