LCOV - code coverage report
Current view: top level - shared - bus-util.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 66 865 7.6 %
Date: 2019-08-23 13:36:53 Functions: 4 34 11.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 37 758 4.9 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <errno.h>
       4                 :            : #include <fcntl.h>
       5                 :            : #include <inttypes.h>
       6                 :            : #include <stdio.h>
       7                 :            : #include <stdlib.h>
       8                 :            : #include <string.h>
       9                 :            : #include <sys/ioctl.h>
      10                 :            : #include <sys/resource.h>
      11                 :            : #include <sys/socket.h>
      12                 :            : #include <unistd.h>
      13                 :            : 
      14                 :            : #include "sd-bus-protocol.h"
      15                 :            : #include "sd-bus.h"
      16                 :            : #include "sd-daemon.h"
      17                 :            : #include "sd-event.h"
      18                 :            : #include "sd-id128.h"
      19                 :            : 
      20                 :            : #include "alloc-util.h"
      21                 :            : #include "bus-internal.h"
      22                 :            : #include "bus-label.h"
      23                 :            : #include "bus-message.h"
      24                 :            : #include "bus-util.h"
      25                 :            : #include "cap-list.h"
      26                 :            : #include "cgroup-util.h"
      27                 :            : #include "def.h"
      28                 :            : #include "escape.h"
      29                 :            : #include "fd-util.h"
      30                 :            : #include "missing.h"
      31                 :            : #include "mountpoint-util.h"
      32                 :            : #include "nsflags.h"
      33                 :            : #include "parse-util.h"
      34                 :            : #include "path-util.h"
      35                 :            : #include "proc-cmdline.h"
      36                 :            : #include "rlimit-util.h"
      37                 :            : #include "stdio-util.h"
      38                 :            : #include "strv.h"
      39                 :            : #include "user-util.h"
      40                 :            : 
      41                 :          0 : static int name_owner_change_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
      42                 :          0 :         sd_event *e = userdata;
      43                 :            : 
      44         [ #  # ]:          0 :         assert(m);
      45         [ #  # ]:          0 :         assert(e);
      46                 :            : 
      47                 :          0 :         sd_bus_close(sd_bus_message_get_bus(m));
      48                 :          0 :         sd_event_exit(e, 0);
      49                 :            : 
      50                 :          0 :         return 1;
      51                 :            : }
      52                 :            : 
      53                 :          0 : int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name) {
      54                 :            :         const char *match;
      55                 :            :         const char *unique;
      56                 :            :         int r;
      57                 :            : 
      58         [ #  # ]:          0 :         assert(e);
      59         [ #  # ]:          0 :         assert(bus);
      60         [ #  # ]:          0 :         assert(name);
      61                 :            : 
      62                 :            :         /* We unregister the name here and then wait for the
      63                 :            :          * NameOwnerChanged signal for this event to arrive before we
      64                 :            :          * quit. We do this in order to make sure that any queued
      65                 :            :          * requests are still processed before we really exit. */
      66                 :            : 
      67                 :          0 :         r = sd_bus_get_unique_name(bus, &unique);
      68         [ #  # ]:          0 :         if (r < 0)
      69                 :          0 :                 return r;
      70                 :            : 
      71   [ #  #  #  #  :          0 :         match = strjoina(
          #  #  #  #  #  
                #  #  # ]
      72                 :            :                         "sender='org.freedesktop.DBus',"
      73                 :            :                         "type='signal',"
      74                 :            :                         "interface='org.freedesktop.DBus',"
      75                 :            :                         "member='NameOwnerChanged',"
      76                 :            :                         "path='/org/freedesktop/DBus',"
      77                 :            :                         "arg0='", name, "',",
      78                 :            :                         "arg1='", unique, "',",
      79                 :            :                         "arg2=''");
      80                 :            : 
      81                 :          0 :         r = sd_bus_add_match_async(bus, NULL, match, name_owner_change_callback, NULL, e);
      82         [ #  # ]:          0 :         if (r < 0)
      83                 :          0 :                 return r;
      84                 :            : 
      85                 :          0 :         r = sd_bus_release_name_async(bus, NULL, name, NULL, NULL);
      86         [ #  # ]:          0 :         if (r < 0)
      87                 :          0 :                 return r;
      88                 :            : 
      89                 :          0 :         return 0;
      90                 :            : }
      91                 :            : 
      92                 :          0 : int bus_event_loop_with_idle(
      93                 :            :                 sd_event *e,
      94                 :            :                 sd_bus *bus,
      95                 :            :                 const char *name,
      96                 :            :                 usec_t timeout,
      97                 :            :                 check_idle_t check_idle,
      98                 :            :                 void *userdata) {
      99                 :          0 :         bool exiting = false;
     100                 :            :         int r, code;
     101                 :            : 
     102         [ #  # ]:          0 :         assert(e);
     103         [ #  # ]:          0 :         assert(bus);
     104         [ #  # ]:          0 :         assert(name);
     105                 :            : 
     106                 :          0 :         for (;;) {
     107                 :            :                 bool idle;
     108                 :            : 
     109                 :          0 :                 r = sd_event_get_state(e);
     110         [ #  # ]:          0 :                 if (r < 0)
     111                 :          0 :                         return r;
     112         [ #  # ]:          0 :                 if (r == SD_EVENT_FINISHED)
     113                 :          0 :                         break;
     114                 :            : 
     115         [ #  # ]:          0 :                 if (check_idle)
     116                 :          0 :                         idle = check_idle(userdata);
     117                 :            :                 else
     118                 :          0 :                         idle = true;
     119                 :            : 
     120   [ #  #  #  # ]:          0 :                 r = sd_event_run(e, exiting || !idle ? (uint64_t) -1 : timeout);
     121         [ #  # ]:          0 :                 if (r < 0)
     122                 :          0 :                         return r;
     123                 :            : 
     124   [ #  #  #  #  :          0 :                 if (r == 0 && !exiting && idle) {
                   #  # ]
     125                 :            : 
     126                 :          0 :                         r = sd_bus_try_close(bus);
     127         [ #  # ]:          0 :                         if (r == -EBUSY)
     128                 :          0 :                                 continue;
     129                 :            : 
     130                 :            :                         /* Fallback for dbus1 connections: we
     131                 :            :                          * unregister the name and wait for the
     132                 :            :                          * response to come through for it */
     133         [ #  # ]:          0 :                         if (r == -EOPNOTSUPP) {
     134                 :            : 
     135                 :            :                                 /* Inform the service manager that we
     136                 :            :                                  * are going down, so that it will
     137                 :            :                                  * queue all further start requests,
     138                 :            :                                  * instead of assuming we are already
     139                 :            :                                  * running. */
     140                 :          0 :                                 sd_notify(false, "STOPPING=1");
     141                 :            : 
     142                 :          0 :                                 r = bus_async_unregister_and_exit(e, bus, name);
     143         [ #  # ]:          0 :                                 if (r < 0)
     144                 :          0 :                                         return r;
     145                 :            : 
     146                 :          0 :                                 exiting = true;
     147                 :          0 :                                 continue;
     148                 :            :                         }
     149                 :            : 
     150         [ #  # ]:          0 :                         if (r < 0)
     151                 :          0 :                                 return r;
     152                 :            : 
     153                 :          0 :                         sd_event_exit(e, 0);
     154                 :          0 :                         break;
     155                 :            :                 }
     156                 :            :         }
     157                 :            : 
     158                 :          0 :         r = sd_event_get_exit_code(e, &code);
     159         [ #  # ]:          0 :         if (r < 0)
     160                 :          0 :                 return r;
     161                 :            : 
     162                 :          0 :         return code;
     163                 :            : }
     164                 :            : 
     165                 :          0 : int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) {
     166                 :          0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *rep = NULL;
     167                 :          0 :         int r, has_owner = 0;
     168                 :            : 
     169         [ #  # ]:          0 :         assert(c);
     170         [ #  # ]:          0 :         assert(name);
     171                 :            : 
     172                 :          0 :         r = sd_bus_call_method(c,
     173                 :            :                                "org.freedesktop.DBus",
     174                 :            :                                "/org/freedesktop/dbus",
     175                 :            :                                "org.freedesktop.DBus",
     176                 :            :                                "NameHasOwner",
     177                 :            :                                error,
     178                 :            :                                &rep,
     179                 :            :                                "s",
     180                 :            :                                name);
     181         [ #  # ]:          0 :         if (r < 0)
     182                 :          0 :                 return r;
     183                 :            : 
     184                 :          0 :         r = sd_bus_message_read_basic(rep, 'b', &has_owner);
     185         [ #  # ]:          0 :         if (r < 0)
     186                 :          0 :                 return sd_bus_error_set_errno(error, r);
     187                 :            : 
     188                 :          0 :         return has_owner;
     189                 :            : }
     190                 :            : 
     191                 :          0 : static int check_good_user(sd_bus_message *m, uid_t good_user) {
     192                 :          0 :         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
     193                 :            :         uid_t sender_uid;
     194                 :            :         int r;
     195                 :            : 
     196         [ #  # ]:          0 :         assert(m);
     197                 :            : 
     198         [ #  # ]:          0 :         if (good_user == UID_INVALID)
     199                 :          0 :                 return 0;
     200                 :            : 
     201                 :          0 :         r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_EUID, &creds);
     202         [ #  # ]:          0 :         if (r < 0)
     203                 :          0 :                 return r;
     204                 :            : 
     205                 :            :         /* Don't trust augmented credentials for authorization */
     206   [ #  #  #  # ]:          0 :         assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EUID) == 0, -EPERM);
     207                 :            : 
     208                 :          0 :         r = sd_bus_creds_get_euid(creds, &sender_uid);
     209         [ #  # ]:          0 :         if (r < 0)
     210                 :          0 :                 return r;
     211                 :            : 
     212                 :          0 :         return sender_uid == good_user;
     213                 :            : }
     214                 :            : 
     215                 :          0 : int bus_test_polkit(
     216                 :            :                 sd_bus_message *call,
     217                 :            :                 int capability,
     218                 :            :                 const char *action,
     219                 :            :                 const char **details,
     220                 :            :                 uid_t good_user,
     221                 :            :                 bool *_challenge,
     222                 :            :                 sd_bus_error *e) {
     223                 :            : 
     224                 :            :         int r;
     225                 :            : 
     226         [ #  # ]:          0 :         assert(call);
     227         [ #  # ]:          0 :         assert(action);
     228                 :            : 
     229                 :            :         /* Tests non-interactively! */
     230                 :            : 
     231                 :          0 :         r = check_good_user(call, good_user);
     232         [ #  # ]:          0 :         if (r != 0)
     233                 :          0 :                 return r;
     234                 :            : 
     235                 :          0 :         r = sd_bus_query_sender_privilege(call, capability);
     236         [ #  # ]:          0 :         if (r < 0)
     237                 :          0 :                 return r;
     238         [ #  # ]:          0 :         else if (r > 0)
     239                 :          0 :                 return 1;
     240                 :            : #if ENABLE_POLKIT
     241                 :            :         else {
     242         [ #  # ]:          0 :                 _cleanup_(sd_bus_message_unrefp) sd_bus_message *request = NULL;
     243         [ #  # ]:          0 :                 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
     244                 :          0 :                 int authorized = false, challenge = false;
     245                 :            :                 const char *sender, **k, **v;
     246                 :            : 
     247                 :          0 :                 sender = sd_bus_message_get_sender(call);
     248         [ #  # ]:          0 :                 if (!sender)
     249                 :          0 :                         return -EBADMSG;
     250                 :            : 
     251                 :          0 :                 r = sd_bus_message_new_method_call(
     252                 :            :                                 call->bus,
     253                 :            :                                 &request,
     254                 :            :                                 "org.freedesktop.PolicyKit1",
     255                 :            :                                 "/org/freedesktop/PolicyKit1/Authority",
     256                 :            :                                 "org.freedesktop.PolicyKit1.Authority",
     257                 :            :                                 "CheckAuthorization");
     258         [ #  # ]:          0 :                 if (r < 0)
     259                 :          0 :                         return r;
     260                 :            : 
     261                 :          0 :                 r = sd_bus_message_append(
     262                 :            :                                 request,
     263                 :            :                                 "(sa{sv})s",
     264                 :            :                                 "system-bus-name", 1, "name", "s", sender,
     265                 :            :                                 action);
     266         [ #  # ]:          0 :                 if (r < 0)
     267                 :          0 :                         return r;
     268                 :            : 
     269                 :          0 :                 r = sd_bus_message_open_container(request, 'a', "{ss}");
     270         [ #  # ]:          0 :                 if (r < 0)
     271                 :          0 :                         return r;
     272                 :            : 
     273   [ #  #  #  #  :          0 :                 STRV_FOREACH_PAIR(k, v, details) {
                   #  # ]
     274                 :          0 :                         r = sd_bus_message_append(request, "{ss}", *k, *v);
     275         [ #  # ]:          0 :                         if (r < 0)
     276                 :          0 :                                 return r;
     277                 :            :                 }
     278                 :            : 
     279                 :          0 :                 r = sd_bus_message_close_container(request);
     280         [ #  # ]:          0 :                 if (r < 0)
     281                 :          0 :                         return r;
     282                 :            : 
     283                 :          0 :                 r = sd_bus_message_append(request, "us", 0, NULL);
     284         [ #  # ]:          0 :                 if (r < 0)
     285                 :          0 :                         return r;
     286                 :            : 
     287                 :          0 :                 r = sd_bus_call(call->bus, request, 0, e, &reply);
     288         [ #  # ]:          0 :                 if (r < 0) {
     289                 :            :                         /* Treat no PK available as access denied */
     290         [ #  # ]:          0 :                         if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
     291                 :          0 :                                 sd_bus_error_free(e);
     292                 :          0 :                                 return -EACCES;
     293                 :            :                         }
     294                 :            : 
     295                 :          0 :                         return r;
     296                 :            :                 }
     297                 :            : 
     298                 :          0 :                 r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
     299         [ #  # ]:          0 :                 if (r < 0)
     300                 :          0 :                         return r;
     301                 :            : 
     302                 :          0 :                 r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
     303         [ #  # ]:          0 :                 if (r < 0)
     304                 :          0 :                         return r;
     305                 :            : 
     306         [ #  # ]:          0 :                 if (authorized)
     307                 :          0 :                         return 1;
     308                 :            : 
     309         [ #  # ]:          0 :                 if (_challenge) {
     310                 :          0 :                         *_challenge = challenge;
     311                 :          0 :                         return 0;
     312                 :            :                 }
     313                 :            :         }
     314                 :            : #endif
     315                 :            : 
     316                 :          0 :         return -EACCES;
     317                 :            : }
     318                 :            : 
     319                 :            : #if ENABLE_POLKIT
     320                 :            : 
     321                 :            : typedef struct AsyncPolkitQuery {
     322                 :            :         sd_bus_message *request, *reply;
     323                 :            :         sd_bus_message_handler_t callback;
     324                 :            :         void *userdata;
     325                 :            :         sd_bus_slot *slot;
     326                 :            :         Hashmap *registry;
     327                 :            : } AsyncPolkitQuery;
     328                 :            : 
     329                 :          0 : static void async_polkit_query_free(AsyncPolkitQuery *q) {
     330                 :            : 
     331         [ #  # ]:          0 :         if (!q)
     332                 :          0 :                 return;
     333                 :            : 
     334                 :          0 :         sd_bus_slot_unref(q->slot);
     335                 :            : 
     336   [ #  #  #  # ]:          0 :         if (q->registry && q->request)
     337                 :          0 :                 hashmap_remove(q->registry, q->request);
     338                 :            : 
     339                 :          0 :         sd_bus_message_unref(q->request);
     340                 :          0 :         sd_bus_message_unref(q->reply);
     341                 :            : 
     342                 :          0 :         free(q);
     343                 :            : }
     344                 :            : 
     345                 :          0 : static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
     346                 :          0 :         _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
     347                 :          0 :         AsyncPolkitQuery *q = userdata;
     348                 :            :         int r;
     349                 :            : 
     350         [ #  # ]:          0 :         assert(reply);
     351         [ #  # ]:          0 :         assert(q);
     352                 :            : 
     353                 :          0 :         q->slot = sd_bus_slot_unref(q->slot);
     354                 :          0 :         q->reply = sd_bus_message_ref(reply);
     355                 :            : 
     356                 :          0 :         r = sd_bus_message_rewind(q->request, true);
     357         [ #  # ]:          0 :         if (r < 0) {
     358                 :          0 :                 r = sd_bus_reply_method_errno(q->request, r, NULL);
     359                 :          0 :                 goto finish;
     360                 :            :         }
     361                 :            : 
     362                 :          0 :         r = q->callback(q->request, q->userdata, &error_buffer);
     363                 :          0 :         r = bus_maybe_reply_error(q->request, r, &error_buffer);
     364                 :            : 
     365                 :          0 : finish:
     366                 :          0 :         async_polkit_query_free(q);
     367                 :            : 
     368                 :          0 :         return r;
     369                 :            : }
     370                 :            : 
     371                 :            : #endif
     372                 :            : 
     373                 :          0 : int bus_verify_polkit_async(
     374                 :            :                 sd_bus_message *call,
     375                 :            :                 int capability,
     376                 :            :                 const char *action,
     377                 :            :                 const char **details,
     378                 :            :                 bool interactive,
     379                 :            :                 uid_t good_user,
     380                 :            :                 Hashmap **registry,
     381                 :            :                 sd_bus_error *error) {
     382                 :            : 
     383                 :            : #if ENABLE_POLKIT
     384                 :          0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *pk = NULL;
     385                 :            :         AsyncPolkitQuery *q;
     386                 :            :         const char *sender, **k, **v;
     387                 :            :         sd_bus_message_handler_t callback;
     388                 :            :         void *userdata;
     389                 :            :         int c;
     390                 :            : #endif
     391                 :            :         int r;
     392                 :            : 
     393         [ #  # ]:          0 :         assert(call);
     394         [ #  # ]:          0 :         assert(action);
     395         [ #  # ]:          0 :         assert(registry);
     396                 :            : 
     397                 :          0 :         r = check_good_user(call, good_user);
     398         [ #  # ]:          0 :         if (r != 0)
     399                 :          0 :                 return r;
     400                 :            : 
     401                 :            : #if ENABLE_POLKIT
     402                 :          0 :         q = hashmap_get(*registry, call);
     403         [ #  # ]:          0 :         if (q) {
     404                 :            :                 int authorized, challenge;
     405                 :            : 
     406                 :            :                 /* This is the second invocation of this function, and
     407                 :            :                  * there's already a response from polkit, let's
     408                 :            :                  * process it */
     409         [ #  # ]:          0 :                 assert(q->reply);
     410                 :            : 
     411         [ #  # ]:          0 :                 if (sd_bus_message_is_method_error(q->reply, NULL)) {
     412                 :            :                         const sd_bus_error *e;
     413                 :            : 
     414                 :          0 :                         e = sd_bus_message_get_error(q->reply);
     415                 :            : 
     416                 :            :                         /* Treat no PK available as access denied */
     417         [ #  # ]:          0 :                         if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
     418                 :          0 :                                 return -EACCES;
     419                 :            : 
     420                 :            :                         /* Copy error from polkit reply */
     421                 :          0 :                         sd_bus_error_copy(error, e);
     422                 :          0 :                         return -sd_bus_error_get_errno(e);
     423                 :            :                 }
     424                 :            : 
     425                 :          0 :                 r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
     426         [ #  # ]:          0 :                 if (r >= 0)
     427                 :          0 :                         r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
     428                 :            : 
     429         [ #  # ]:          0 :                 if (r < 0)
     430                 :          0 :                         return r;
     431                 :            : 
     432         [ #  # ]:          0 :                 if (authorized)
     433                 :          0 :                         return 1;
     434                 :            : 
     435         [ #  # ]:          0 :                 if (challenge)
     436                 :          0 :                         return sd_bus_error_set(error, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED, "Interactive authentication required.");
     437                 :            : 
     438                 :          0 :                 return -EACCES;
     439                 :            :         }
     440                 :            : #endif
     441                 :            : 
     442                 :          0 :         r = sd_bus_query_sender_privilege(call, capability);
     443         [ #  # ]:          0 :         if (r < 0)
     444                 :          0 :                 return r;
     445         [ #  # ]:          0 :         else if (r > 0)
     446                 :          0 :                 return 1;
     447                 :            : 
     448                 :            : #if ENABLE_POLKIT
     449         [ #  # ]:          0 :         if (sd_bus_get_current_message(call->bus) != call)
     450                 :          0 :                 return -EINVAL;
     451                 :            : 
     452                 :          0 :         callback = sd_bus_get_current_handler(call->bus);
     453         [ #  # ]:          0 :         if (!callback)
     454                 :          0 :                 return -EINVAL;
     455                 :            : 
     456                 :          0 :         userdata = sd_bus_get_current_userdata(call->bus);
     457                 :            : 
     458                 :          0 :         sender = sd_bus_message_get_sender(call);
     459         [ #  # ]:          0 :         if (!sender)
     460                 :          0 :                 return -EBADMSG;
     461                 :            : 
     462                 :          0 :         c = sd_bus_message_get_allow_interactive_authorization(call);
     463         [ #  # ]:          0 :         if (c < 0)
     464                 :          0 :                 return c;
     465         [ #  # ]:          0 :         if (c > 0)
     466                 :          0 :                 interactive = true;
     467                 :            : 
     468                 :          0 :         r = hashmap_ensure_allocated(registry, NULL);
     469         [ #  # ]:          0 :         if (r < 0)
     470                 :          0 :                 return r;
     471                 :            : 
     472                 :          0 :         r = sd_bus_message_new_method_call(
     473                 :            :                         call->bus,
     474                 :            :                         &pk,
     475                 :            :                         "org.freedesktop.PolicyKit1",
     476                 :            :                         "/org/freedesktop/PolicyKit1/Authority",
     477                 :            :                         "org.freedesktop.PolicyKit1.Authority",
     478                 :            :                         "CheckAuthorization");
     479         [ #  # ]:          0 :         if (r < 0)
     480                 :          0 :                 return r;
     481                 :            : 
     482                 :          0 :         r = sd_bus_message_append(
     483                 :            :                         pk,
     484                 :            :                         "(sa{sv})s",
     485                 :            :                         "system-bus-name", 1, "name", "s", sender,
     486                 :            :                         action);
     487         [ #  # ]:          0 :         if (r < 0)
     488                 :          0 :                 return r;
     489                 :            : 
     490                 :          0 :         r = sd_bus_message_open_container(pk, 'a', "{ss}");
     491         [ #  # ]:          0 :         if (r < 0)
     492                 :          0 :                 return r;
     493                 :            : 
     494   [ #  #  #  #  :          0 :         STRV_FOREACH_PAIR(k, v, details) {
                   #  # ]
     495                 :          0 :                 r = sd_bus_message_append(pk, "{ss}", *k, *v);
     496         [ #  # ]:          0 :                 if (r < 0)
     497                 :          0 :                         return r;
     498                 :            :         }
     499                 :            : 
     500                 :          0 :         r = sd_bus_message_close_container(pk);
     501         [ #  # ]:          0 :         if (r < 0)
     502                 :          0 :                 return r;
     503                 :            : 
     504                 :          0 :         r = sd_bus_message_append(pk, "us", interactive, NULL);
     505         [ #  # ]:          0 :         if (r < 0)
     506                 :          0 :                 return r;
     507                 :            : 
     508                 :          0 :         q = new0(AsyncPolkitQuery, 1);
     509         [ #  # ]:          0 :         if (!q)
     510                 :          0 :                 return -ENOMEM;
     511                 :            : 
     512                 :          0 :         q->request = sd_bus_message_ref(call);
     513                 :          0 :         q->callback = callback;
     514                 :          0 :         q->userdata = userdata;
     515                 :            : 
     516                 :          0 :         r = hashmap_put(*registry, call, q);
     517         [ #  # ]:          0 :         if (r < 0) {
     518                 :          0 :                 async_polkit_query_free(q);
     519                 :          0 :                 return r;
     520                 :            :         }
     521                 :            : 
     522                 :          0 :         q->registry = *registry;
     523                 :            : 
     524                 :          0 :         r = sd_bus_call_async(call->bus, &q->slot, pk, async_polkit_callback, q, 0);
     525         [ #  # ]:          0 :         if (r < 0) {
     526                 :          0 :                 async_polkit_query_free(q);
     527                 :          0 :                 return r;
     528                 :            :         }
     529                 :            : 
     530                 :          0 :         return 0;
     531                 :            : #endif
     532                 :            : 
     533                 :            :         return -EACCES;
     534                 :            : }
     535                 :            : 
     536                 :         68 : void bus_verify_polkit_async_registry_free(Hashmap *registry) {
     537                 :            : #if ENABLE_POLKIT
     538         [ -  + ]:         68 :         hashmap_free_with_destructor(registry, async_polkit_query_free);
     539                 :            : #endif
     540                 :         68 : }
     541                 :            : 
     542                 :          0 : int bus_check_peercred(sd_bus *c) {
     543                 :            :         struct ucred ucred;
     544                 :            :         int fd, r;
     545                 :            : 
     546         [ #  # ]:          0 :         assert(c);
     547                 :            : 
     548                 :          0 :         fd = sd_bus_get_fd(c);
     549         [ #  # ]:          0 :         if (fd < 0)
     550                 :          0 :                 return fd;
     551                 :            : 
     552                 :          0 :         r = getpeercred(fd, &ucred);
     553         [ #  # ]:          0 :         if (r < 0)
     554                 :          0 :                 return r;
     555                 :            : 
     556   [ #  #  #  # ]:          0 :         if (ucred.uid != 0 && ucred.uid != geteuid())
     557                 :          0 :                 return -EPERM;
     558                 :            : 
     559                 :          0 :         return 1;
     560                 :            : }
     561                 :            : 
     562                 :          0 : int bus_connect_system_systemd(sd_bus **_bus) {
     563                 :          0 :         _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
     564                 :            :         int r;
     565                 :            : 
     566         [ #  # ]:          0 :         assert(_bus);
     567                 :            : 
     568         [ #  # ]:          0 :         if (geteuid() != 0)
     569                 :          0 :                 return sd_bus_default_system(_bus);
     570                 :            : 
     571                 :            :         /* If we are root then let's talk directly to the system
     572                 :            :          * instance, instead of going via the bus */
     573                 :            : 
     574                 :          0 :         r = sd_bus_new(&bus);
     575         [ #  # ]:          0 :         if (r < 0)
     576                 :          0 :                 return r;
     577                 :            : 
     578                 :          0 :         r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
     579         [ #  # ]:          0 :         if (r < 0)
     580                 :          0 :                 return r;
     581                 :            : 
     582                 :          0 :         r = sd_bus_start(bus);
     583         [ #  # ]:          0 :         if (r < 0)
     584                 :          0 :                 return sd_bus_default_system(_bus);
     585                 :            : 
     586                 :          0 :         r = bus_check_peercred(bus);
     587         [ #  # ]:          0 :         if (r < 0)
     588                 :          0 :                 return r;
     589                 :            : 
     590                 :          0 :         *_bus = TAKE_PTR(bus);
     591                 :            : 
     592                 :          0 :         return 0;
     593                 :            : }
     594                 :            : 
     595                 :          0 : int bus_connect_user_systemd(sd_bus **_bus) {
     596                 :          0 :         _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
     597                 :          0 :         _cleanup_free_ char *ee = NULL;
     598                 :            :         const char *e;
     599                 :            :         int r;
     600                 :            : 
     601         [ #  # ]:          0 :         assert(_bus);
     602                 :            : 
     603                 :          0 :         e = secure_getenv("XDG_RUNTIME_DIR");
     604         [ #  # ]:          0 :         if (!e)
     605                 :          0 :                 return sd_bus_default_user(_bus);
     606                 :            : 
     607                 :          0 :         ee = bus_address_escape(e);
     608         [ #  # ]:          0 :         if (!ee)
     609                 :          0 :                 return -ENOMEM;
     610                 :            : 
     611                 :          0 :         r = sd_bus_new(&bus);
     612         [ #  # ]:          0 :         if (r < 0)
     613                 :          0 :                 return r;
     614                 :            : 
     615                 :          0 :         bus->address = strjoin("unix:path=", ee, "/systemd/private");
     616         [ #  # ]:          0 :         if (!bus->address)
     617                 :          0 :                 return -ENOMEM;
     618                 :            : 
     619                 :          0 :         r = sd_bus_start(bus);
     620         [ #  # ]:          0 :         if (r < 0)
     621                 :          0 :                 return sd_bus_default_user(_bus);
     622                 :            : 
     623                 :          0 :         r = bus_check_peercred(bus);
     624         [ #  # ]:          0 :         if (r < 0)
     625                 :          0 :                 return r;
     626                 :            : 
     627                 :          0 :         *_bus = TAKE_PTR(bus);
     628                 :            : 
     629                 :          0 :         return 0;
     630                 :            : }
     631                 :            : 
     632                 :          0 : int bus_print_property_value(const char *name, const char *expected_value, bool only_value, const char *value) {
     633         [ #  # ]:          0 :         assert(name);
     634                 :            : 
     635   [ #  #  #  # ]:          0 :         if (expected_value && !streq_ptr(expected_value, value))
     636                 :          0 :                 return 0;
     637                 :            : 
     638         [ #  # ]:          0 :         if (only_value)
     639                 :          0 :                 puts(value);
     640                 :            :         else
     641                 :          0 :                 printf("%s=%s\n", name, value);
     642                 :            : 
     643                 :          0 :         return 0;
     644                 :            : }
     645                 :            : 
     646                 :          0 : int bus_print_property_valuef(const char *name, const char *expected_value, bool only_value, const char *fmt, ...) {
     647                 :            :         va_list ap;
     648                 :            :         int r;
     649                 :            : 
     650         [ #  # ]:          0 :         assert(name);
     651         [ #  # ]:          0 :         assert(fmt);
     652                 :            : 
     653         [ #  # ]:          0 :         if (expected_value) {
     654                 :          0 :                 _cleanup_free_ char *s = NULL;
     655                 :            : 
     656                 :          0 :                 va_start(ap, fmt);
     657                 :          0 :                 r = vasprintf(&s, fmt, ap);
     658                 :          0 :                 va_end(ap);
     659         [ #  # ]:          0 :                 if (r < 0)
     660                 :          0 :                         return -ENOMEM;
     661                 :            : 
     662         [ #  # ]:          0 :                 if (streq_ptr(expected_value, s)) {
     663         [ #  # ]:          0 :                         if (only_value)
     664                 :          0 :                                 puts(s);
     665                 :            :                         else
     666                 :          0 :                                 printf("%s=%s\n", name, s);
     667                 :            :                 }
     668                 :            : 
     669                 :          0 :                 return 0;
     670                 :            :         }
     671                 :            : 
     672         [ #  # ]:          0 :         if (!only_value)
     673                 :          0 :                 printf("%s=", name);
     674                 :          0 :         va_start(ap, fmt);
     675                 :          0 :         vprintf(fmt, ap);
     676                 :          0 :         va_end(ap);
     677                 :          0 :         puts("");
     678                 :            : 
     679                 :          0 :         return 0;
     680                 :            : }
     681                 :            : 
     682                 :          0 : static int bus_print_property(const char *name, const char *expected_value, sd_bus_message *m, bool value, bool all) {
     683                 :            :         char type;
     684                 :            :         const char *contents;
     685                 :            :         int r;
     686                 :            : 
     687         [ #  # ]:          0 :         assert(name);
     688         [ #  # ]:          0 :         assert(m);
     689                 :            : 
     690                 :          0 :         r = sd_bus_message_peek_type(m, &type, &contents);
     691         [ #  # ]:          0 :         if (r < 0)
     692                 :          0 :                 return r;
     693                 :            : 
     694   [ #  #  #  #  :          0 :         switch (type) {
             #  #  #  #  
                      # ]
     695                 :            : 
     696                 :          0 :         case SD_BUS_TYPE_STRING: {
     697                 :            :                 const char *s;
     698                 :            : 
     699                 :          0 :                 r = sd_bus_message_read_basic(m, type, &s);
     700         [ #  # ]:          0 :                 if (r < 0)
     701                 :          0 :                         return r;
     702                 :            : 
     703   [ #  #  #  # ]:          0 :                 if (all || !isempty(s)) {
     704                 :            :                         bool good;
     705                 :            : 
     706                 :            :                         /* This property has a single value, so we need to take
     707                 :            :                          * care not to print a new line, everything else is OK. */
     708                 :          0 :                         good = !strchr(s, '\n');
     709         [ #  # ]:          0 :                         bus_print_property_value(name, expected_value, value, good ? s : "[unprintable]");
     710                 :            :                 }
     711                 :            : 
     712                 :          0 :                 return 1;
     713                 :            :         }
     714                 :            : 
     715                 :          0 :         case SD_BUS_TYPE_BOOLEAN: {
     716                 :            :                 int b;
     717                 :            : 
     718                 :          0 :                 r = sd_bus_message_read_basic(m, type, &b);
     719         [ #  # ]:          0 :                 if (r < 0)
     720                 :          0 :                         return r;
     721                 :            : 
     722   [ #  #  #  # ]:          0 :                 if (expected_value && parse_boolean(expected_value) != b)
     723                 :          0 :                         return 1;
     724                 :            : 
     725                 :          0 :                 bus_print_property_value(name, NULL, value, yes_no(b));
     726                 :          0 :                 return 1;
     727                 :            :         }
     728                 :            : 
     729                 :          0 :         case SD_BUS_TYPE_UINT64: {
     730                 :            :                 uint64_t u;
     731                 :            : 
     732                 :          0 :                 r = sd_bus_message_read_basic(m, type, &u);
     733         [ #  # ]:          0 :                 if (r < 0)
     734                 :          0 :                         return r;
     735                 :            : 
     736                 :            :                 /* Yes, heuristics! But we can change this check
     737                 :            :                  * should it turn out to not be sufficient */
     738                 :            : 
     739         [ #  # ]:          0 :                 if (endswith(name, "Timestamp") ||
     740         [ #  # ]:          0 :                     STR_IN_SET(name, "NextElapseUSecRealtime", "LastTriggerUSec", "TimeUSec", "RTCTimeUSec")) {
     741                 :            :                         char timestamp[FORMAT_TIMESTAMP_MAX];
     742                 :            :                         const char *t;
     743                 :            : 
     744                 :          0 :                         t = format_timestamp(timestamp, sizeof(timestamp), u);
     745   [ #  #  #  # ]:          0 :                         if (t || all)
     746                 :          0 :                                 bus_print_property_value(name, expected_value, value, strempty(t));
     747                 :            : 
     748         [ #  # ]:          0 :                 } else if (strstr(name, "USec")) {
     749                 :            :                         char timespan[FORMAT_TIMESPAN_MAX];
     750                 :            : 
     751                 :          0 :                         (void) format_timespan(timespan, sizeof(timespan), u, 0);
     752                 :          0 :                         bus_print_property_value(name, expected_value, value, timespan);
     753                 :            : 
     754         [ #  # ]:          0 :                 } else if (streq(name, "RestrictNamespaces")) {
     755         [ #  # ]:          0 :                         _cleanup_free_ char *s = NULL;
     756                 :            :                         const char *result;
     757                 :            : 
     758         [ #  # ]:          0 :                         if ((u & NAMESPACE_FLAGS_ALL) == 0)
     759                 :          0 :                                 result = "yes";
     760         [ #  # ]:          0 :                         else if (FLAGS_SET(u, NAMESPACE_FLAGS_ALL))
     761                 :          0 :                                 result = "no";
     762                 :            :                         else {
     763                 :          0 :                                 r = namespace_flags_to_string(u, &s);
     764         [ #  # ]:          0 :                                 if (r < 0)
     765                 :          0 :                                         return r;
     766                 :            : 
     767                 :          0 :                                 result = s;
     768                 :            :                         }
     769                 :            : 
     770                 :          0 :                         bus_print_property_value(name, expected_value, value, result);
     771                 :            : 
     772         [ #  # ]:          0 :                 } else if (streq(name, "MountFlags")) {
     773                 :            :                         const char *result;
     774                 :            : 
     775                 :          0 :                         result = mount_propagation_flags_to_string(u);
     776         [ #  # ]:          0 :                         if (!result)
     777                 :          0 :                                 return -EINVAL;
     778                 :            : 
     779                 :          0 :                         bus_print_property_value(name, expected_value, value, result);
     780                 :            : 
     781         [ #  # ]:          0 :                 } else if (STR_IN_SET(name, "CapabilityBoundingSet", "AmbientCapabilities")) {
     782         [ #  # ]:          0 :                         _cleanup_free_ char *s = NULL;
     783                 :            : 
     784                 :          0 :                         r = capability_set_to_string_alloc(u, &s);
     785         [ #  # ]:          0 :                         if (r < 0)
     786                 :          0 :                                 return r;
     787                 :            : 
     788                 :          0 :                         bus_print_property_value(name, expected_value, value, s);
     789                 :            : 
     790   [ #  #  #  # ]:          0 :                 } else if ((STR_IN_SET(name, "CPUWeight", "StartupCPUWeight", "IOWeight", "StartupIOWeight") && u == CGROUP_WEIGHT_INVALID) ||
     791   [ #  #  #  # ]:          0 :                            (STR_IN_SET(name, "CPUShares", "StartupCPUShares") && u == CGROUP_CPU_SHARES_INVALID) ||
     792   [ #  #  #  # ]:          0 :                            (STR_IN_SET(name, "BlockIOWeight", "StartupBlockIOWeight") && u == CGROUP_BLKIO_WEIGHT_INVALID) ||
     793   [ #  #  #  # ]:          0 :                            (STR_IN_SET(name, "MemoryCurrent", "TasksCurrent") && u == (uint64_t) -1) ||
     794   [ #  #  #  # ]:          0 :                            (endswith(name, "NSec") && u == (uint64_t) -1))
     795                 :            : 
     796                 :          0 :                         bus_print_property_value(name, expected_value, value, "[not set]");
     797                 :            : 
     798   [ #  #  #  # ]:          0 :                 else if ((STR_IN_SET(name, "DefaultMemoryLow", "DefaultMemoryMin", "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax", "MemoryLimit") && u == CGROUP_LIMIT_MAX) ||
     799   [ #  #  #  #  :          0 :                          (STR_IN_SET(name, "TasksMax", "DefaultTasksMax") && u == (uint64_t) -1) ||
                   #  # ]
     800   [ #  #  #  # ]:          0 :                          (startswith(name, "Limit") && u == (uint64_t) -1) ||
     801         [ #  # ]:          0 :                          (startswith(name, "DefaultLimit") && u == (uint64_t) -1))
     802                 :            : 
     803                 :          0 :                         bus_print_property_value(name, expected_value, value, "infinity");
     804   [ #  #  #  # ]:          0 :                 else if (STR_IN_SET(name, "IPIngressBytes", "IPIngressPackets", "IPEgressBytes", "IPEgressPackets") && u == (uint64_t) -1)
     805                 :          0 :                         bus_print_property_value(name, expected_value, value, "[no data]");
     806                 :            :                 else
     807                 :          0 :                         bus_print_property_valuef(name, expected_value, value, "%"PRIu64, u);
     808                 :            : 
     809                 :          0 :                 return 1;
     810                 :            :         }
     811                 :            : 
     812                 :          0 :         case SD_BUS_TYPE_INT64: {
     813                 :            :                 int64_t i;
     814                 :            : 
     815                 :          0 :                 r = sd_bus_message_read_basic(m, type, &i);
     816         [ #  # ]:          0 :                 if (r < 0)
     817                 :          0 :                         return r;
     818                 :            : 
     819                 :          0 :                 bus_print_property_valuef(name, expected_value, value, "%"PRIi64, i);
     820                 :          0 :                 return 1;
     821                 :            :         }
     822                 :            : 
     823                 :          0 :         case SD_BUS_TYPE_UINT32: {
     824                 :            :                 uint32_t u;
     825                 :            : 
     826                 :          0 :                 r = sd_bus_message_read_basic(m, type, &u);
     827         [ #  # ]:          0 :                 if (r < 0)
     828                 :          0 :                         return r;
     829                 :            : 
     830   [ #  #  #  # ]:          0 :                 if (strstr(name, "UMask") || strstr(name, "Mode"))
     831                 :          0 :                         bus_print_property_valuef(name, expected_value, value, "%04o", u);
     832                 :            : 
     833         [ #  # ]:          0 :                 else if (streq(name, "UID")) {
     834         [ #  # ]:          0 :                         if (u == UID_INVALID)
     835                 :          0 :                                 bus_print_property_value(name, expected_value, value, "[not set]");
     836                 :            :                         else
     837                 :          0 :                                 bus_print_property_valuef(name, expected_value, value, "%"PRIu32, u);
     838         [ #  # ]:          0 :                 } else if (streq(name, "GID")) {
     839         [ #  # ]:          0 :                         if (u == GID_INVALID)
     840                 :          0 :                                 bus_print_property_value(name, expected_value, value, "[not set]");
     841                 :            :                         else
     842                 :          0 :                                 bus_print_property_valuef(name, expected_value, value, "%"PRIu32, u);
     843                 :            :                 } else
     844                 :          0 :                         bus_print_property_valuef(name, expected_value, value, "%"PRIu32, u);
     845                 :            : 
     846                 :          0 :                 return 1;
     847                 :            :         }
     848                 :            : 
     849                 :          0 :         case SD_BUS_TYPE_INT32: {
     850                 :            :                 int32_t i;
     851                 :            : 
     852                 :          0 :                 r = sd_bus_message_read_basic(m, type, &i);
     853         [ #  # ]:          0 :                 if (r < 0)
     854                 :          0 :                         return r;
     855                 :            : 
     856                 :          0 :                 bus_print_property_valuef(name, expected_value, value, "%"PRIi32, i);
     857                 :          0 :                 return 1;
     858                 :            :         }
     859                 :            : 
     860                 :          0 :         case SD_BUS_TYPE_DOUBLE: {
     861                 :            :                 double d;
     862                 :            : 
     863                 :          0 :                 r = sd_bus_message_read_basic(m, type, &d);
     864         [ #  # ]:          0 :                 if (r < 0)
     865                 :          0 :                         return r;
     866                 :            : 
     867                 :          0 :                 bus_print_property_valuef(name, expected_value, value, "%g", d);
     868                 :          0 :                 return 1;
     869                 :            :         }
     870                 :            : 
     871                 :          0 :         case SD_BUS_TYPE_ARRAY:
     872         [ #  # ]:          0 :                 if (streq(contents, "s")) {
     873                 :          0 :                         bool first = true;
     874                 :            :                         const char *str;
     875                 :            : 
     876                 :          0 :                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, contents);
     877         [ #  # ]:          0 :                         if (r < 0)
     878                 :          0 :                                 return r;
     879                 :            : 
     880         [ #  # ]:          0 :                         while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &str)) > 0) {
     881                 :            :                                 bool good;
     882                 :            : 
     883   [ #  #  #  # ]:          0 :                                 if (first && !value)
     884                 :          0 :                                         printf("%s=", name);
     885                 :            : 
     886                 :            :                                 /* This property has multiple space-separated values, so
     887                 :            :                                  * neither spaces nor newlines can be allowed in a value. */
     888                 :          0 :                                 good = str[strcspn(str, " \n")] == '\0';
     889                 :            : 
     890   [ #  #  #  # ]:          0 :                                 printf("%s%s", first ? "" : " ", good ? str : "[unprintable]");
     891                 :            : 
     892                 :          0 :                                 first = false;
     893                 :            :                         }
     894         [ #  # ]:          0 :                         if (r < 0)
     895                 :          0 :                                 return r;
     896                 :            : 
     897   [ #  #  #  #  :          0 :                         if (first && all && !value)
                   #  # ]
     898                 :          0 :                                 printf("%s=", name);
     899   [ #  #  #  # ]:          0 :                         if (!first || all)
     900                 :          0 :                                 puts("");
     901                 :            : 
     902                 :          0 :                         r = sd_bus_message_exit_container(m);
     903         [ #  # ]:          0 :                         if (r < 0)
     904                 :          0 :                                 return r;
     905                 :            : 
     906                 :          0 :                         return 1;
     907                 :            : 
     908         [ #  # ]:          0 :                 } else if (streq(contents, "y")) {
     909                 :            :                         const uint8_t *u;
     910                 :            :                         size_t n;
     911                 :            : 
     912                 :          0 :                         r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
     913         [ #  # ]:          0 :                         if (r < 0)
     914                 :          0 :                                 return r;
     915                 :            : 
     916   [ #  #  #  # ]:          0 :                         if (all || n > 0) {
     917                 :            :                                 unsigned i;
     918                 :            : 
     919         [ #  # ]:          0 :                                 if (!value)
     920                 :          0 :                                         printf("%s=", name);
     921                 :            : 
     922         [ #  # ]:          0 :                                 for (i = 0; i < n; i++)
     923                 :          0 :                                         printf("%02x", u[i]);
     924                 :            : 
     925                 :          0 :                                 puts("");
     926                 :            :                         }
     927                 :            : 
     928                 :          0 :                         return 1;
     929                 :            : 
     930         [ #  # ]:          0 :                 } else if (streq(contents, "u")) {
     931                 :            :                         uint32_t *u;
     932                 :            :                         size_t n;
     933                 :            : 
     934                 :          0 :                         r = sd_bus_message_read_array(m, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
     935         [ #  # ]:          0 :                         if (r < 0)
     936                 :          0 :                                 return r;
     937                 :            : 
     938   [ #  #  #  # ]:          0 :                         if (all || n > 0) {
     939                 :            :                                 unsigned i;
     940                 :            : 
     941         [ #  # ]:          0 :                                 if (!value)
     942                 :          0 :                                         printf("%s=", name);
     943                 :            : 
     944         [ #  # ]:          0 :                                 for (i = 0; i < n; i++)
     945                 :          0 :                                         printf("%08x", u[i]);
     946                 :            : 
     947                 :          0 :                                 puts("");
     948                 :            :                         }
     949                 :            : 
     950                 :          0 :                         return 1;
     951                 :            :                 }
     952                 :            : 
     953                 :          0 :                 break;
     954                 :            :         }
     955                 :            : 
     956                 :          0 :         return 0;
     957                 :            : }
     958                 :            : 
     959                 :          0 : int bus_message_print_all_properties(
     960                 :            :                 sd_bus_message *m,
     961                 :            :                 bus_message_print_t func,
     962                 :            :                 char **filter,
     963                 :            :                 bool value,
     964                 :            :                 bool all,
     965                 :            :                 Set **found_properties) {
     966                 :            : 
     967                 :            :         int r;
     968                 :            : 
     969         [ #  # ]:          0 :         assert(m);
     970                 :            : 
     971                 :          0 :         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
     972         [ #  # ]:          0 :         if (r < 0)
     973                 :          0 :                 return r;
     974                 :            : 
     975         [ #  # ]:          0 :         while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
     976         [ #  # ]:          0 :                 _cleanup_free_ char *name_with_equal = NULL;
     977                 :          0 :                 const char *name, *contents, *expected_value = NULL;
     978                 :            : 
     979                 :          0 :                 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &name);
     980         [ #  # ]:          0 :                 if (r < 0)
     981                 :          0 :                         return r;
     982                 :            : 
     983         [ #  # ]:          0 :                 if (found_properties) {
     984                 :          0 :                         r = set_ensure_allocated(found_properties, &string_hash_ops);
     985         [ #  # ]:          0 :                         if (r < 0)
     986                 :          0 :                                 return log_oom();
     987                 :            : 
     988                 :          0 :                         r = set_put(*found_properties, name);
     989   [ #  #  #  # ]:          0 :                         if (r < 0 && r != -EEXIST)
     990                 :          0 :                                 return log_oom();
     991                 :            :                 }
     992                 :            : 
     993                 :          0 :                 name_with_equal = strjoin(name, "=");
     994         [ #  # ]:          0 :                 if (!name_with_equal)
     995                 :          0 :                         return log_oom();
     996                 :            : 
     997   [ #  #  #  # ]:          0 :                 if (!filter || strv_find(filter, name) ||
     998         [ #  # ]:          0 :                     (expected_value = strv_find_startswith(filter, name_with_equal))) {
     999                 :          0 :                         r = sd_bus_message_peek_type(m, NULL, &contents);
    1000         [ #  # ]:          0 :                         if (r < 0)
    1001                 :          0 :                                 return r;
    1002                 :            : 
    1003                 :          0 :                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
    1004         [ #  # ]:          0 :                         if (r < 0)
    1005                 :          0 :                                 return r;
    1006                 :            : 
    1007         [ #  # ]:          0 :                         if (func)
    1008                 :          0 :                                 r = func(name, expected_value, m, value, all);
    1009   [ #  #  #  # ]:          0 :                         if (!func || r == 0)
    1010                 :          0 :                                 r = bus_print_property(name, expected_value, m, value, all);
    1011         [ #  # ]:          0 :                         if (r < 0)
    1012                 :          0 :                                 return r;
    1013         [ #  # ]:          0 :                         if (r == 0) {
    1014   [ #  #  #  # ]:          0 :                                 if (all && !expected_value)
    1015                 :          0 :                                         printf("%s=[unprintable]\n", name);
    1016                 :            :                                 /* skip what we didn't read */
    1017                 :          0 :                                 r = sd_bus_message_skip(m, contents);
    1018         [ #  # ]:          0 :                                 if (r < 0)
    1019                 :          0 :                                         return r;
    1020                 :            :                         }
    1021                 :            : 
    1022                 :          0 :                         r = sd_bus_message_exit_container(m);
    1023         [ #  # ]:          0 :                         if (r < 0)
    1024                 :          0 :                                 return r;
    1025                 :            :                 } else {
    1026                 :          0 :                         r = sd_bus_message_skip(m, "v");
    1027         [ #  # ]:          0 :                         if (r < 0)
    1028                 :          0 :                                 return r;
    1029                 :            :                 }
    1030                 :            : 
    1031                 :          0 :                 r = sd_bus_message_exit_container(m);
    1032         [ #  # ]:          0 :                 if (r < 0)
    1033                 :          0 :                         return r;
    1034                 :            :         }
    1035         [ #  # ]:          0 :         if (r < 0)
    1036                 :          0 :                 return r;
    1037                 :            : 
    1038                 :          0 :         r = sd_bus_message_exit_container(m);
    1039         [ #  # ]:          0 :         if (r < 0)
    1040                 :          0 :                 return r;
    1041                 :            : 
    1042                 :          0 :         return 0;
    1043                 :            : }
    1044                 :            : 
    1045                 :          0 : int bus_print_all_properties(
    1046                 :            :                 sd_bus *bus,
    1047                 :            :                 const char *dest,
    1048                 :            :                 const char *path,
    1049                 :            :                 bus_message_print_t func,
    1050                 :            :                 char **filter,
    1051                 :            :                 bool value,
    1052                 :            :                 bool all,
    1053                 :            :                 Set **found_properties) {
    1054                 :            : 
    1055                 :          0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
    1056                 :          0 :         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
    1057                 :            :         int r;
    1058                 :            : 
    1059         [ #  # ]:          0 :         assert(bus);
    1060         [ #  # ]:          0 :         assert(path);
    1061                 :            : 
    1062                 :          0 :         r = sd_bus_call_method(bus,
    1063                 :            :                         dest,
    1064                 :            :                         path,
    1065                 :            :                         "org.freedesktop.DBus.Properties",
    1066                 :            :                         "GetAll",
    1067                 :            :                         &error,
    1068                 :            :                         &reply,
    1069                 :            :                         "s", "");
    1070         [ #  # ]:          0 :         if (r < 0)
    1071                 :          0 :                 return r;
    1072                 :            : 
    1073                 :          0 :         return bus_message_print_all_properties(reply, func, filter, value, all, found_properties);
    1074                 :            : }
    1075                 :            : 
    1076                 :          0 : int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
    1077                 :          0 :         sd_id128_t *p = userdata;
    1078                 :            :         const void *v;
    1079                 :            :         size_t n;
    1080                 :            :         int r;
    1081                 :            : 
    1082                 :          0 :         r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
    1083         [ #  # ]:          0 :         if (r < 0)
    1084                 :          0 :                 return r;
    1085                 :            : 
    1086         [ #  # ]:          0 :         if (n == 0)
    1087                 :          0 :                 *p = SD_ID128_NULL;
    1088         [ #  # ]:          0 :         else if (n == 16)
    1089                 :          0 :                 memcpy((*p).bytes, v, n);
    1090                 :            :         else
    1091                 :          0 :                 return -EINVAL;
    1092                 :            : 
    1093                 :          0 :         return 0;
    1094                 :            : }
    1095                 :            : 
    1096                 :          0 : static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, unsigned flags, sd_bus_error *error, void *userdata) {
    1097                 :            :         char type;
    1098                 :            :         int r;
    1099                 :            : 
    1100                 :          0 :         r = sd_bus_message_peek_type(m, &type, NULL);
    1101         [ #  # ]:          0 :         if (r < 0)
    1102                 :          0 :                 return r;
    1103                 :            : 
    1104   [ #  #  #  #  :          0 :         switch (type) {
                #  #  # ]
    1105                 :            : 
    1106                 :          0 :         case SD_BUS_TYPE_STRING: {
    1107                 :          0 :                 const char **p = userdata;
    1108                 :            :                 const char *s;
    1109                 :            : 
    1110                 :          0 :                 r = sd_bus_message_read_basic(m, type, &s);
    1111         [ #  # ]:          0 :                 if (r < 0)
    1112                 :          0 :                         return r;
    1113                 :            : 
    1114         [ #  # ]:          0 :                 if (isempty(s))
    1115                 :          0 :                         s = NULL;
    1116                 :            : 
    1117         [ #  # ]:          0 :                 if (flags & BUS_MAP_STRDUP)
    1118                 :          0 :                         return free_and_strdup((char **) userdata, s);
    1119                 :            : 
    1120                 :          0 :                 *p = s;
    1121                 :          0 :                 return 0;
    1122                 :            :         }
    1123                 :            : 
    1124                 :          0 :         case SD_BUS_TYPE_ARRAY: {
    1125                 :          0 :                 _cleanup_strv_free_ char **l = NULL;
    1126                 :          0 :                 char ***p = userdata;
    1127                 :            : 
    1128                 :          0 :                 r = bus_message_read_strv_extend(m, &l);
    1129         [ #  # ]:          0 :                 if (r < 0)
    1130                 :          0 :                         return r;
    1131                 :            : 
    1132                 :          0 :                 return strv_free_and_replace(*p, l);
    1133                 :            :         }
    1134                 :            : 
    1135                 :          0 :         case SD_BUS_TYPE_BOOLEAN: {
    1136                 :            :                 int b;
    1137                 :            : 
    1138                 :          0 :                 r = sd_bus_message_read_basic(m, type, &b);
    1139         [ #  # ]:          0 :                 if (r < 0)
    1140                 :          0 :                         return r;
    1141                 :            : 
    1142         [ #  # ]:          0 :                 if (flags & BUS_MAP_BOOLEAN_AS_BOOL)
    1143                 :          0 :                         *(bool*) userdata = b;
    1144                 :            :                 else
    1145                 :          0 :                         *(int*) userdata = b;
    1146                 :            : 
    1147                 :          0 :                 return 0;
    1148                 :            :         }
    1149                 :            : 
    1150                 :          0 :         case SD_BUS_TYPE_INT32:
    1151                 :            :         case SD_BUS_TYPE_UINT32: {
    1152                 :          0 :                 uint32_t u, *p = userdata;
    1153                 :            : 
    1154                 :          0 :                 r = sd_bus_message_read_basic(m, type, &u);
    1155         [ #  # ]:          0 :                 if (r < 0)
    1156                 :          0 :                         return r;
    1157                 :            : 
    1158                 :          0 :                 *p = u;
    1159                 :          0 :                 return 0;
    1160                 :            :         }
    1161                 :            : 
    1162                 :          0 :         case SD_BUS_TYPE_INT64:
    1163                 :            :         case SD_BUS_TYPE_UINT64: {
    1164                 :          0 :                 uint64_t t, *p = userdata;
    1165                 :            : 
    1166                 :          0 :                 r = sd_bus_message_read_basic(m, type, &t);
    1167         [ #  # ]:          0 :                 if (r < 0)
    1168                 :          0 :                         return r;
    1169                 :            : 
    1170                 :          0 :                 *p = t;
    1171                 :          0 :                 return 0;
    1172                 :            :         }
    1173                 :            : 
    1174                 :          0 :         case SD_BUS_TYPE_DOUBLE: {
    1175                 :          0 :                 double d, *p = userdata;
    1176                 :            : 
    1177                 :          0 :                 r = sd_bus_message_read_basic(m, type, &d);
    1178         [ #  # ]:          0 :                 if (r < 0)
    1179                 :          0 :                         return r;
    1180                 :            : 
    1181                 :          0 :                 *p = d;
    1182                 :          0 :                 return 0;
    1183                 :            :         }}
    1184                 :            : 
    1185                 :          0 :         return -EOPNOTSUPP;
    1186                 :            : }
    1187                 :            : 
    1188                 :          0 : int bus_message_map_all_properties(
    1189                 :            :                 sd_bus_message *m,
    1190                 :            :                 const struct bus_properties_map *map,
    1191                 :            :                 unsigned flags,
    1192                 :            :                 sd_bus_error *error,
    1193                 :            :                 void *userdata) {
    1194                 :            : 
    1195                 :            :         int r;
    1196                 :            : 
    1197         [ #  # ]:          0 :         assert(m);
    1198         [ #  # ]:          0 :         assert(map);
    1199                 :            : 
    1200                 :          0 :         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
    1201         [ #  # ]:          0 :         if (r < 0)
    1202                 :          0 :                 return r;
    1203                 :            : 
    1204         [ #  # ]:          0 :         while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
    1205                 :            :                 const struct bus_properties_map *prop;
    1206                 :            :                 const char *member;
    1207                 :            :                 const char *contents;
    1208                 :            :                 void *v;
    1209                 :            :                 unsigned i;
    1210                 :            : 
    1211                 :          0 :                 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
    1212         [ #  # ]:          0 :                 if (r < 0)
    1213                 :          0 :                         return r;
    1214                 :            : 
    1215         [ #  # ]:          0 :                 for (i = 0, prop = NULL; map[i].member; i++)
    1216         [ #  # ]:          0 :                         if (streq(map[i].member, member)) {
    1217                 :          0 :                                 prop = &map[i];
    1218                 :          0 :                                 break;
    1219                 :            :                         }
    1220                 :            : 
    1221         [ #  # ]:          0 :                 if (prop) {
    1222                 :          0 :                         r = sd_bus_message_peek_type(m, NULL, &contents);
    1223         [ #  # ]:          0 :                         if (r < 0)
    1224                 :          0 :                                 return r;
    1225                 :            : 
    1226                 :          0 :                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
    1227         [ #  # ]:          0 :                         if (r < 0)
    1228                 :          0 :                                 return r;
    1229                 :            : 
    1230                 :          0 :                         v = (uint8_t *)userdata + prop->offset;
    1231         [ #  # ]:          0 :                         if (map[i].set)
    1232                 :          0 :                                 r = prop->set(sd_bus_message_get_bus(m), member, m, error, v);
    1233                 :            :                         else
    1234                 :          0 :                                 r = map_basic(sd_bus_message_get_bus(m), member, m, flags, error, v);
    1235         [ #  # ]:          0 :                         if (r < 0)
    1236                 :          0 :                                 return r;
    1237                 :            : 
    1238                 :          0 :                         r = sd_bus_message_exit_container(m);
    1239         [ #  # ]:          0 :                         if (r < 0)
    1240                 :          0 :                                 return r;
    1241                 :            :                 } else {
    1242                 :          0 :                         r = sd_bus_message_skip(m, "v");
    1243         [ #  # ]:          0 :                         if (r < 0)
    1244                 :          0 :                                 return r;
    1245                 :            :                 }
    1246                 :            : 
    1247                 :          0 :                 r = sd_bus_message_exit_container(m);
    1248         [ #  # ]:          0 :                 if (r < 0)
    1249                 :          0 :                         return r;
    1250                 :            :         }
    1251         [ #  # ]:          0 :         if (r < 0)
    1252                 :          0 :                 return r;
    1253                 :            : 
    1254                 :          0 :         return sd_bus_message_exit_container(m);
    1255                 :            : }
    1256                 :            : 
    1257                 :          0 : int bus_map_all_properties(
    1258                 :            :                 sd_bus *bus,
    1259                 :            :                 const char *destination,
    1260                 :            :                 const char *path,
    1261                 :            :                 const struct bus_properties_map *map,
    1262                 :            :                 unsigned flags,
    1263                 :            :                 sd_bus_error *error,
    1264                 :            :                 sd_bus_message **reply,
    1265                 :            :                 void *userdata) {
    1266                 :            : 
    1267                 :          0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
    1268                 :            :         int r;
    1269                 :            : 
    1270         [ #  # ]:          0 :         assert(bus);
    1271         [ #  # ]:          0 :         assert(destination);
    1272         [ #  # ]:          0 :         assert(path);
    1273         [ #  # ]:          0 :         assert(map);
    1274   [ #  #  #  # ]:          0 :         assert(reply || (flags & BUS_MAP_STRDUP));
    1275                 :            : 
    1276                 :          0 :         r = sd_bus_call_method(
    1277                 :            :                         bus,
    1278                 :            :                         destination,
    1279                 :            :                         path,
    1280                 :            :                         "org.freedesktop.DBus.Properties",
    1281                 :            :                         "GetAll",
    1282                 :            :                         error,
    1283                 :            :                         &m,
    1284                 :            :                         "s", "");
    1285         [ #  # ]:          0 :         if (r < 0)
    1286                 :          0 :                 return r;
    1287                 :            : 
    1288                 :          0 :         r = bus_message_map_all_properties(m, map, flags, error, userdata);
    1289         [ #  # ]:          0 :         if (r < 0)
    1290                 :          0 :                 return r;
    1291                 :            : 
    1292         [ #  # ]:          0 :         if (reply)
    1293                 :          0 :                 *reply = sd_bus_message_ref(m);
    1294                 :            : 
    1295                 :          0 :         return r;
    1296                 :            : }
    1297                 :            : 
    1298                 :          0 : int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **ret) {
    1299                 :          0 :         _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
    1300                 :            :         int r;
    1301                 :            : 
    1302         [ #  # ]:          0 :         assert(transport >= 0);
    1303         [ #  # ]:          0 :         assert(transport < _BUS_TRANSPORT_MAX);
    1304         [ #  # ]:          0 :         assert(ret);
    1305                 :            : 
    1306   [ #  #  #  # ]:          0 :         assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
    1307   [ #  #  #  #  :          0 :         assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
                   #  # ]
    1308                 :            : 
    1309   [ #  #  #  # ]:          0 :         switch (transport) {
    1310                 :            : 
    1311                 :          0 :         case BUS_TRANSPORT_LOCAL:
    1312         [ #  # ]:          0 :                 if (user)
    1313                 :          0 :                         r = sd_bus_default_user(&bus);
    1314                 :            :                 else {
    1315         [ #  # ]:          0 :                         if (sd_booted() <= 0) {
    1316                 :            :                                 /* Print a friendly message when the local system is actually not running systemd as PID 1. */
    1317         [ #  # ]:          0 :                                 log_error("System has not been booted with systemd as init system (PID 1). Can't operate.");
    1318                 :            : 
    1319                 :          0 :                                 return -EHOSTDOWN;
    1320                 :            :                         }
    1321                 :          0 :                         r = sd_bus_default_system(&bus);
    1322                 :            :                 }
    1323                 :          0 :                 break;
    1324                 :            : 
    1325                 :          0 :         case BUS_TRANSPORT_REMOTE:
    1326                 :          0 :                 r = sd_bus_open_system_remote(&bus, host);
    1327                 :          0 :                 break;
    1328                 :            : 
    1329                 :          0 :         case BUS_TRANSPORT_MACHINE:
    1330                 :          0 :                 r = sd_bus_open_system_machine(&bus, host);
    1331                 :          0 :                 break;
    1332                 :            : 
    1333                 :          0 :         default:
    1334                 :          0 :                 assert_not_reached("Hmm, unknown transport type.");
    1335                 :            :         }
    1336         [ #  # ]:          0 :         if (r < 0)
    1337                 :          0 :                 return r;
    1338                 :            : 
    1339                 :          0 :         r = sd_bus_set_exit_on_disconnect(bus, true);
    1340         [ #  # ]:          0 :         if (r < 0)
    1341                 :          0 :                 return r;
    1342                 :            : 
    1343                 :          0 :         *ret = TAKE_PTR(bus);
    1344                 :            : 
    1345                 :          0 :         return 0;
    1346                 :            : }
    1347                 :            : 
    1348                 :          0 : int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
    1349                 :            :         int r;
    1350                 :            : 
    1351         [ #  # ]:          0 :         assert(transport >= 0);
    1352         [ #  # ]:          0 :         assert(transport < _BUS_TRANSPORT_MAX);
    1353         [ #  # ]:          0 :         assert(bus);
    1354                 :            : 
    1355   [ #  #  #  # ]:          0 :         assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
    1356   [ #  #  #  #  :          0 :         assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
                   #  # ]
    1357                 :            : 
    1358   [ #  #  #  # ]:          0 :         switch (transport) {
    1359                 :            : 
    1360                 :          0 :         case BUS_TRANSPORT_LOCAL:
    1361         [ #  # ]:          0 :                 if (user)
    1362                 :          0 :                         r = bus_connect_user_systemd(bus);
    1363                 :            :                 else {
    1364         [ #  # ]:          0 :                         if (sd_booted() <= 0)
    1365                 :            :                                 /* Print a friendly message when the local system is actually not running systemd as PID 1. */
    1366         [ #  # ]:          0 :                                 return log_error_errno(SYNTHETIC_ERRNO(EHOSTDOWN),
    1367                 :            :                                                        "System has not been booted with systemd as init system (PID 1). Can't operate.");
    1368                 :          0 :                         r = bus_connect_system_systemd(bus);
    1369                 :            :                 }
    1370                 :          0 :                 break;
    1371                 :            : 
    1372                 :          0 :         case BUS_TRANSPORT_REMOTE:
    1373                 :          0 :                 r = sd_bus_open_system_remote(bus, host);
    1374                 :          0 :                 break;
    1375                 :            : 
    1376                 :          0 :         case BUS_TRANSPORT_MACHINE:
    1377                 :          0 :                 r = sd_bus_open_system_machine(bus, host);
    1378                 :          0 :                 break;
    1379                 :            : 
    1380                 :          0 :         default:
    1381                 :          0 :                 assert_not_reached("Hmm, unknown transport type.");
    1382                 :            :         }
    1383                 :            : 
    1384                 :          0 :         return r;
    1385                 :            : }
    1386                 :            : 
    1387                 :          0 : int bus_property_get_bool(
    1388                 :            :                 sd_bus *bus,
    1389                 :            :                 const char *path,
    1390                 :            :                 const char *interface,
    1391                 :            :                 const char *property,
    1392                 :            :                 sd_bus_message *reply,
    1393                 :            :                 void *userdata,
    1394                 :            :                 sd_bus_error *error) {
    1395                 :            : 
    1396                 :          0 :         int b = *(bool*) userdata;
    1397                 :            : 
    1398                 :          0 :         return sd_bus_message_append_basic(reply, 'b', &b);
    1399                 :            : }
    1400                 :            : 
    1401                 :          0 : int bus_property_set_bool(
    1402                 :            :                 sd_bus *bus,
    1403                 :            :                 const char *path,
    1404                 :            :                 const char *interface,
    1405                 :            :                 const char *property,
    1406                 :            :                 sd_bus_message *value,
    1407                 :            :                 void *userdata,
    1408                 :            :                 sd_bus_error *error) {
    1409                 :            : 
    1410                 :            :         int b, r;
    1411                 :            : 
    1412                 :          0 :         r = sd_bus_message_read(value, "b", &b);
    1413         [ #  # ]:          0 :         if (r < 0)
    1414                 :          0 :                 return r;
    1415                 :            : 
    1416                 :          0 :         *(bool*) userdata = b;
    1417                 :          0 :         return 0;
    1418                 :            : }
    1419                 :            : 
    1420                 :          0 : int bus_property_get_id128(
    1421                 :            :                 sd_bus *bus,
    1422                 :            :                 const char *path,
    1423                 :            :                 const char *interface,
    1424                 :            :                 const char *property,
    1425                 :            :                 sd_bus_message *reply,
    1426                 :            :                 void *userdata,
    1427                 :            :                 sd_bus_error *error) {
    1428                 :            : 
    1429                 :          0 :         sd_id128_t *id = userdata;
    1430                 :            : 
    1431         [ #  # ]:          0 :         if (sd_id128_is_null(*id)) /* Add an empty array if the ID is zero */
    1432                 :          0 :                 return sd_bus_message_append(reply, "ay", 0);
    1433                 :            :         else
    1434                 :          0 :                 return sd_bus_message_append_array(reply, 'y', id->bytes, 16);
    1435                 :            : }
    1436                 :            : 
    1437                 :            : #if __SIZEOF_SIZE_T__ != 8
    1438                 :            : int bus_property_get_size(
    1439                 :            :                 sd_bus *bus,
    1440                 :            :                 const char *path,
    1441                 :            :                 const char *interface,
    1442                 :            :                 const char *property,
    1443                 :            :                 sd_bus_message *reply,
    1444                 :            :                 void *userdata,
    1445                 :            :                 sd_bus_error *error) {
    1446                 :            : 
    1447                 :            :         uint64_t sz = *(size_t*) userdata;
    1448                 :            : 
    1449                 :            :         return sd_bus_message_append_basic(reply, 't', &sz);
    1450                 :            : }
    1451                 :            : #endif
    1452                 :            : 
    1453                 :            : #if __SIZEOF_LONG__ != 8
    1454                 :            : int bus_property_get_long(
    1455                 :            :                 sd_bus *bus,
    1456                 :            :                 const char *path,
    1457                 :            :                 const char *interface,
    1458                 :            :                 const char *property,
    1459                 :            :                 sd_bus_message *reply,
    1460                 :            :                 void *userdata,
    1461                 :            :                 sd_bus_error *error) {
    1462                 :            : 
    1463                 :            :         int64_t l = *(long*) userdata;
    1464                 :            : 
    1465                 :            :         return sd_bus_message_append_basic(reply, 'x', &l);
    1466                 :            : }
    1467                 :            : 
    1468                 :            : int bus_property_get_ulong(
    1469                 :            :                 sd_bus *bus,
    1470                 :            :                 const char *path,
    1471                 :            :                 const char *interface,
    1472                 :            :                 const char *property,
    1473                 :            :                 sd_bus_message *reply,
    1474                 :            :                 void *userdata,
    1475                 :            :                 sd_bus_error *error) {
    1476                 :            : 
    1477                 :            :         uint64_t ul = *(unsigned long*) userdata;
    1478                 :            : 
    1479                 :            :         return sd_bus_message_append_basic(reply, 't', &ul);
    1480                 :            : }
    1481                 :            : #endif
    1482                 :            : 
    1483                 :            : /**
    1484                 :            :  * bus_path_encode_unique() - encode unique object path
    1485                 :            :  * @b: bus connection or NULL
    1486                 :            :  * @prefix: object path prefix
    1487                 :            :  * @sender_id: unique-name of client, or NULL
    1488                 :            :  * @external_id: external ID to be chosen by client, or NULL
    1489                 :            :  * @ret_path: storage for encoded object path pointer
    1490                 :            :  *
    1491                 :            :  * Whenever we provide a bus API that allows clients to create and manage
    1492                 :            :  * server-side objects, we need to provide a unique name for these objects. If
    1493                 :            :  * we let the server choose the name, we suffer from a race condition: If a
    1494                 :            :  * client creates an object asynchronously, it cannot destroy that object until
    1495                 :            :  * it received the method reply. It cannot know the name of the new object,
    1496                 :            :  * thus, it cannot destroy it. Furthermore, it enforces a round-trip.
    1497                 :            :  *
    1498                 :            :  * Therefore, many APIs allow the client to choose the unique name for newly
    1499                 :            :  * created objects. There're two problems to solve, though:
    1500                 :            :  *    1) Object names are usually defined via dbus object paths, which are
    1501                 :            :  *       usually globally namespaced. Therefore, multiple clients must be able
    1502                 :            :  *       to choose unique object names without interference.
    1503                 :            :  *    2) If multiple libraries share the same bus connection, they must be
    1504                 :            :  *       able to choose unique object names without interference.
    1505                 :            :  * The first problem is solved easily by prefixing a name with the
    1506                 :            :  * unique-bus-name of a connection. The server side must enforce this and
    1507                 :            :  * reject any other name. The second problem is solved by providing unique
    1508                 :            :  * suffixes from within sd-bus.
    1509                 :            :  *
    1510                 :            :  * This helper allows clients to create unique object-paths. It uses the
    1511                 :            :  * template '/prefix/sender_id/external_id' and returns the new path in
    1512                 :            :  * @ret_path (must be freed by the caller).
    1513                 :            :  * If @sender_id is NULL, the unique-name of @b is used. If @external_id is
    1514                 :            :  * NULL, this function allocates a unique suffix via @b (by requesting a new
    1515                 :            :  * cookie). If both @sender_id and @external_id are given, @b can be passed as
    1516                 :            :  * NULL.
    1517                 :            :  *
    1518                 :            :  * Returns: 0 on success, negative error code on failure.
    1519                 :            :  */
    1520                 :          4 : int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id, const char *external_id, char **ret_path) {
    1521                 :          4 :         _cleanup_free_ char *sender_label = NULL, *external_label = NULL;
    1522                 :            :         char external_buf[DECIMAL_STR_MAX(uint64_t)], *p;
    1523                 :            :         int r;
    1524                 :            : 
    1525   [ +  -  +  -  :          4 :         assert_return(b || (sender_id && external_id), -EINVAL);
          +  -  -  +  -  
                      + ]
    1526   [ -  +  -  + ]:          4 :         assert_return(object_path_is_valid(prefix), -EINVAL);
    1527   [ -  +  -  + ]:          4 :         assert_return(ret_path, -EINVAL);
    1528                 :            : 
    1529         [ -  + ]:          4 :         if (!sender_id) {
    1530                 :          0 :                 r = sd_bus_get_unique_name(b, &sender_id);
    1531         [ #  # ]:          0 :                 if (r < 0)
    1532                 :          0 :                         return r;
    1533                 :            :         }
    1534                 :            : 
    1535         [ -  + ]:          4 :         if (!external_id) {
    1536         [ #  # ]:          0 :                 xsprintf(external_buf, "%"PRIu64, ++b->cookie);
    1537                 :          0 :                 external_id = external_buf;
    1538                 :            :         }
    1539                 :            : 
    1540                 :          4 :         sender_label = bus_label_escape(sender_id);
    1541         [ -  + ]:          4 :         if (!sender_label)
    1542                 :          0 :                 return -ENOMEM;
    1543                 :            : 
    1544                 :          4 :         external_label = bus_label_escape(external_id);
    1545         [ -  + ]:          4 :         if (!external_label)
    1546                 :          0 :                 return -ENOMEM;
    1547                 :            : 
    1548                 :          4 :         p = path_join(prefix, sender_label, external_label);
    1549         [ -  + ]:          4 :         if (!p)
    1550                 :          0 :                 return -ENOMEM;
    1551                 :            : 
    1552                 :          4 :         *ret_path = p;
    1553                 :          4 :         return 0;
    1554                 :            : }
    1555                 :            : 
    1556                 :            : /**
    1557                 :            :  * bus_path_decode_unique() - decode unique object path
    1558                 :            :  * @path: object path to decode
    1559                 :            :  * @prefix: object path prefix
    1560                 :            :  * @ret_sender: output parameter for sender-id label
    1561                 :            :  * @ret_external: output parameter for external-id label
    1562                 :            :  *
    1563                 :            :  * This does the reverse of bus_path_encode_unique() (see its description for
    1564                 :            :  * details). Both trailing labels, sender-id and external-id, are unescaped and
    1565                 :            :  * returned in the given output parameters (the caller must free them).
    1566                 :            :  *
    1567                 :            :  * Note that this function returns 0 if the path does not match the template
    1568                 :            :  * (see bus_path_encode_unique()), 1 if it matched.
    1569                 :            :  *
    1570                 :            :  * Returns: Negative error code on failure, 0 if the given object path does not
    1571                 :            :  *          match the template (return parameters are set to NULL), 1 if it was
    1572                 :            :  *          parsed successfully (return parameters contain allocated labels).
    1573                 :            :  */
    1574                 :         16 : int bus_path_decode_unique(const char *path, const char *prefix, char **ret_sender, char **ret_external) {
    1575                 :            :         const char *p, *q;
    1576                 :            :         char *sender, *external;
    1577                 :            : 
    1578         [ -  + ]:         16 :         assert(object_path_is_valid(path));
    1579         [ -  + ]:         16 :         assert(object_path_is_valid(prefix));
    1580         [ -  + ]:         16 :         assert(ret_sender);
    1581         [ -  + ]:         16 :         assert(ret_external);
    1582                 :            : 
    1583                 :         16 :         p = object_path_startswith(path, prefix);
    1584         [ +  + ]:         16 :         if (!p) {
    1585                 :          4 :                 *ret_sender = NULL;
    1586                 :          4 :                 *ret_external = NULL;
    1587                 :          4 :                 return 0;
    1588                 :            :         }
    1589                 :            : 
    1590                 :         12 :         q = strchr(p, '/');
    1591         [ +  + ]:         12 :         if (!q) {
    1592                 :          4 :                 *ret_sender = NULL;
    1593                 :          4 :                 *ret_external = NULL;
    1594                 :          4 :                 return 0;
    1595                 :            :         }
    1596                 :            : 
    1597                 :          8 :         sender = bus_label_unescape_n(p, q - p);
    1598                 :          8 :         external = bus_label_unescape(q + 1);
    1599   [ +  -  -  + ]:          8 :         if (!sender || !external) {
    1600                 :          0 :                 free(sender);
    1601                 :          0 :                 free(external);
    1602                 :          0 :                 return -ENOMEM;
    1603                 :            :         }
    1604                 :            : 
    1605                 :          8 :         *ret_sender = sender;
    1606                 :          8 :         *ret_external = external;
    1607                 :          8 :         return 1;
    1608                 :            : }
    1609                 :            : 
    1610                 :          0 : int bus_property_get_rlimit(
    1611                 :            :                 sd_bus *bus,
    1612                 :            :                 const char *path,
    1613                 :            :                 const char *interface,
    1614                 :            :                 const char *property,
    1615                 :            :                 sd_bus_message *reply,
    1616                 :            :                 void *userdata,
    1617                 :            :                 sd_bus_error *error) {
    1618                 :            : 
    1619                 :            :         const char *is_soft;
    1620                 :            :         struct rlimit *rl;
    1621                 :            :         uint64_t u;
    1622                 :            :         rlim_t x;
    1623                 :            : 
    1624         [ #  # ]:          0 :         assert(bus);
    1625         [ #  # ]:          0 :         assert(reply);
    1626         [ #  # ]:          0 :         assert(userdata);
    1627                 :            : 
    1628                 :          0 :         is_soft = endswith(property, "Soft");
    1629                 :            : 
    1630                 :          0 :         rl = *(struct rlimit**) userdata;
    1631         [ #  # ]:          0 :         if (rl)
    1632         [ #  # ]:          0 :                 x = is_soft ? rl->rlim_cur : rl->rlim_max;
    1633                 :            :         else {
    1634                 :          0 :                 struct rlimit buf = {};
    1635                 :            :                 const char *s, *p;
    1636                 :            :                 int z;
    1637                 :            : 
    1638                 :            :                 /* Chop off "Soft" suffix */
    1639         [ #  # ]:          0 :                 s = is_soft ? strndupa(property, is_soft - property) : property;
    1640                 :            : 
    1641                 :            :                 /* Skip over any prefix, such as "Default" */
    1642         [ #  # ]:          0 :                 assert_se(p = strstr(s, "Limit"));
    1643                 :            : 
    1644                 :          0 :                 z = rlimit_from_string(p + 5);
    1645         [ #  # ]:          0 :                 assert(z >= 0);
    1646                 :            : 
    1647                 :          0 :                 (void) getrlimit(z, &buf);
    1648         [ #  # ]:          0 :                 x = is_soft ? buf.rlim_cur : buf.rlim_max;
    1649                 :            :         }
    1650                 :            : 
    1651                 :            :         /* rlim_t might have different sizes, let's map RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on all
    1652                 :            :          * archs */
    1653                 :          0 :         u = x == RLIM_INFINITY ? (uint64_t) -1 : (uint64_t) x;
    1654                 :            : 
    1655                 :          0 :         return sd_bus_message_append(reply, "t", u);
    1656                 :            : }
    1657                 :            : 
    1658                 :          0 : int bus_track_add_name_many(sd_bus_track *t, char **l) {
    1659                 :          0 :         int r = 0;
    1660                 :            :         char **i;
    1661                 :            : 
    1662         [ #  # ]:          0 :         assert(t);
    1663                 :            : 
    1664                 :            :         /* Continues adding after failure, and returns the first failure. */
    1665                 :            : 
    1666   [ #  #  #  # ]:          0 :         STRV_FOREACH(i, l) {
    1667                 :            :                 int k;
    1668                 :            : 
    1669                 :          0 :                 k = sd_bus_track_add_name(t, *i);
    1670   [ #  #  #  # ]:          0 :                 if (k < 0 && r >= 0)
    1671                 :          0 :                         r = k;
    1672                 :            :         }
    1673                 :            : 
    1674                 :          0 :         return r;
    1675                 :            : }
    1676                 :            : 
    1677                 :          4 : int bus_open_system_watch_bind_with_description(sd_bus **ret, const char *description) {
    1678                 :          4 :         _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
    1679                 :            :         const char *e;
    1680                 :            :         int r;
    1681                 :            : 
    1682         [ -  + ]:          4 :         assert(ret);
    1683                 :            : 
    1684                 :            :         /* Match like sd_bus_open_system(), but with the "watch_bind" feature and the Connected() signal turned on. */
    1685                 :            : 
    1686                 :          4 :         r = sd_bus_new(&bus);
    1687         [ -  + ]:          4 :         if (r < 0)
    1688                 :          0 :                 return r;
    1689                 :            : 
    1690         [ +  - ]:          4 :         if (description) {
    1691                 :          4 :                 r = sd_bus_set_description(bus, description);
    1692         [ -  + ]:          4 :                 if (r < 0)
    1693                 :          0 :                         return r;
    1694                 :            :         }
    1695                 :            : 
    1696                 :          4 :         e = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
    1697         [ +  - ]:          4 :         if (!e)
    1698                 :          4 :                 e = DEFAULT_SYSTEM_BUS_ADDRESS;
    1699                 :            : 
    1700                 :          4 :         r = sd_bus_set_address(bus, e);
    1701         [ -  + ]:          4 :         if (r < 0)
    1702                 :          0 :                 return r;
    1703                 :            : 
    1704                 :          4 :         r = sd_bus_set_bus_client(bus, true);
    1705         [ -  + ]:          4 :         if (r < 0)
    1706                 :          0 :                 return r;
    1707                 :            : 
    1708                 :          4 :         r = sd_bus_set_trusted(bus, true);
    1709         [ -  + ]:          4 :         if (r < 0)
    1710                 :          0 :                 return r;
    1711                 :            : 
    1712                 :          4 :         r = sd_bus_negotiate_creds(bus, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS);
    1713         [ -  + ]:          4 :         if (r < 0)
    1714                 :          0 :                 return r;
    1715                 :            : 
    1716                 :          4 :         r = sd_bus_set_watch_bind(bus, true);
    1717         [ -  + ]:          4 :         if (r < 0)
    1718                 :          0 :                 return r;
    1719                 :            : 
    1720                 :          4 :         r = sd_bus_set_connected_signal(bus, true);
    1721         [ -  + ]:          4 :         if (r < 0)
    1722                 :          0 :                 return r;
    1723                 :            : 
    1724                 :          4 :         r = sd_bus_start(bus);
    1725         [ -  + ]:          4 :         if (r < 0)
    1726                 :          0 :                 return r;
    1727                 :            : 
    1728                 :          4 :         *ret = TAKE_PTR(bus);
    1729                 :            : 
    1730                 :          4 :         return 0;
    1731                 :            : }
    1732                 :            : 
    1733                 :          0 : int bus_reply_pair_array(sd_bus_message *m, char **l) {
    1734                 :          0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
    1735                 :            :         char **k, **v;
    1736                 :            :         int r;
    1737                 :            : 
    1738         [ #  # ]:          0 :         assert(m);
    1739                 :            : 
    1740                 :            :         /* Reply to the specified message with a message containing a dictionary put together from the specified
    1741                 :            :          * strv */
    1742                 :            : 
    1743                 :          0 :         r = sd_bus_message_new_method_return(m, &reply);
    1744         [ #  # ]:          0 :         if (r < 0)
    1745                 :          0 :                 return r;
    1746                 :            : 
    1747                 :          0 :         r = sd_bus_message_open_container(reply, 'a', "{ss}");
    1748         [ #  # ]:          0 :         if (r < 0)
    1749                 :          0 :                 return r;
    1750                 :            : 
    1751   [ #  #  #  #  :          0 :         STRV_FOREACH_PAIR(k, v, l) {
                   #  # ]
    1752                 :          0 :                 r = sd_bus_message_append(reply, "{ss}", *k, *v);
    1753         [ #  # ]:          0 :                 if (r < 0)
    1754                 :          0 :                         return r;
    1755                 :            :         }
    1756                 :            : 
    1757                 :          0 :         r = sd_bus_message_close_container(reply);
    1758         [ #  # ]:          0 :         if (r < 0)
    1759                 :          0 :                 return r;
    1760                 :            : 
    1761                 :          0 :         return sd_bus_send(NULL, reply, NULL);
    1762                 :            : }
    1763                 :            : 
    1764                 :          0 : static void bus_message_unref_wrapper(void *m) {
    1765                 :          0 :         sd_bus_message_unref(m);
    1766                 :          0 : }
    1767                 :            : 
    1768                 :            : const struct hash_ops bus_message_hash_ops = {
    1769                 :            :         .hash = trivial_hash_func,
    1770                 :            :         .compare = trivial_compare_func,
    1771                 :            :         .free_value = bus_message_unref_wrapper,
    1772                 :            : };

Generated by: LCOV version 1.14