chiark / gitweb /
[3/5] Apply missing fixes from upstream
authorSven Eden <yamakuzure@gmx.net>
Wed, 29 Mar 2017 08:06:16 +0000 (10:06 +0200)
committerSven Eden <yamakuzure@gmx.net>
Wed, 29 Mar 2017 08:48:15 +0000 (10:48 +0200)
13 files changed:
src/cgroups-agent/cgroups-agent.c
src/core/cgroup.c
src/core/cgroup.h
src/core/mount-setup.c
src/libelogind/libelogind.sym
src/libelogind/sd-bus/bus-container.c
src/libelogind/sd-bus/bus-creds.c
src/libelogind/sd-bus/bus-introspect.c
src/libelogind/sd-bus/bus-objects.c
src/libelogind/sd-bus/sd-bus.c
src/libelogind/sd-daemon/sd-daemon.c
src/libelogind/sd-login/sd-login.c
src/libelogind/sd-login/test-login.c

index c0ce357..0e0ca77 100644 (file)
@@ -45,7 +45,7 @@ int main(int argc, char *argv[]) {
          * this to avoid an activation loop when we start dbus when we
          * are called when the dbus service is shut down. */
 
-        r = bus_open_system_systemd(&bus);
+        r = bus_connect_system_systemd(&bus);
 #else
         /* Unlike in systemd where this has to use a private socket,
            since elogind doesn't associate control groups with services
index 54da471..c877c3c 100644 (file)
 #include <fcntl.h>
 #include <fnmatch.h>
 
-#include "process-util.h"
-#include "path-util.h"
-// #include "special.h"
 #include "cgroup-util.h"
+#include "path-util.h"
+#include "process-util.h"
+//#include "special.h"
+
 #include "cgroup.h"
 
 #define CGROUP_CPU_QUOTA_PERIOD_USEC ((usec_t) 100 * USEC_PER_MSEC)
@@ -38,13 +39,18 @@ void cgroup_context_init(CGroupContext *c) {
         /* Initialize everything to the kernel defaults, assuming the
          * structure is preinitialized to 0 */
 
-        c->cpu_shares = (unsigned long) -1;
-        c->startup_cpu_shares = (unsigned long) -1;
+        c->cpu_shares = CGROUP_CPU_SHARES_INVALID;
+        c->startup_cpu_shares = CGROUP_CPU_SHARES_INVALID;
+        c->cpu_quota_per_sec_usec = USEC_INFINITY;
+
         c->memory_limit = (uint64_t) -1;
-        c->blockio_weight = (unsigned long) -1;
-        c->startup_blockio_weight = (unsigned long) -1;
 
-        c->cpu_quota_per_sec_usec = USEC_INFINITY;
+        c->blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID;
+        c->startup_blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID;
+
+        c->tasks_max = (uint64_t) -1;
+
+        c->netclass_type = CGROUP_NETCLASS_TYPE_NONE;
 }
 
 void cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a) {
@@ -102,23 +108,27 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
                 "%sCPUAccounting=%s\n"
                 "%sBlockIOAccounting=%s\n"
                 "%sMemoryAccounting=%s\n"
-                "%sCPUShares=%lu\n"
-                "%sStartupCPUShares=%lu\n"
+                "%sTasksAccounting=%s\n"
+                "%sCPUShares=%" PRIu64 "\n"
+                "%sStartupCPUShares=%" PRIu64 "\n"
                 "%sCPUQuotaPerSecSec=%s\n"
-                "%sBlockIOWeight=%lu\n"
-                "%sStartupBlockIOWeight=%lu\n"
+                "%sBlockIOWeight=%" PRIu64 "\n"
+                "%sStartupBlockIOWeight=%" PRIu64 "\n"
                 "%sMemoryLimit=%" PRIu64 "\n"
+                "%sTasksMax=%" PRIu64 "\n"
                 "%sDevicePolicy=%s\n"
                 "%sDelegate=%s\n",
                 prefix, yes_no(c->cpu_accounting),
                 prefix, yes_no(c->blockio_accounting),
                 prefix, yes_no(c->memory_accounting),
+                prefix, yes_no(c->tasks_accounting),
                 prefix, c->cpu_shares,
                 prefix, c->startup_cpu_shares,
                 prefix, format_timespan(u, sizeof(u), c->cpu_quota_per_sec_usec, 1),
                 prefix, c->blockio_weight,
                 prefix, c->startup_blockio_weight,
                 prefix, c->memory_limit,
+                prefix, c->tasks_max,
                 prefix, cgroup_device_policy_to_string(c->device_policy),
                 prefix, yes_no(c->delegate));
 
@@ -131,7 +141,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
 
         LIST_FOREACH(device_weights, w, c->blockio_device_weights)
                 fprintf(f,
-                        "%sBlockIODeviceWeight=%s %lu",
+                        "%sBlockIODeviceWeight=%s %" PRIu64,
                         prefix,
                         w->path,
                         w->weight);
@@ -285,7 +295,7 @@ fail:
         return -errno;
 }
 
-void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, ManagerState state) {
+void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, uint32_t netclass, ManagerState state) {
         bool is_root;
         int r;
 
@@ -307,11 +317,11 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, M
          * and missing cgroups, i.e. EROFS and ENOENT. */
 
         if ((mask & CGROUP_MASK_CPU) && !is_root) {
-                char buf[MAX(DECIMAL_STR_MAX(unsigned long), DECIMAL_STR_MAX(usec_t)) + 1];
+                char buf[MAX(DECIMAL_STR_MAX(uint64_t), DECIMAL_STR_MAX(usec_t)) + 1];
 
-                sprintf(buf, "%lu\n",
-                        IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && c->startup_cpu_shares != (unsigned long) -1 ? c->startup_cpu_shares :
-                        c->cpu_shares != (unsigned long) -1 ? c->cpu_shares : 1024);
+                sprintf(buf, "%" PRIu64 "\n",
+                        IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && c->startup_cpu_shares != CGROUP_CPU_SHARES_INVALID ? c->startup_cpu_shares :
+                        c->cpu_shares != CGROUP_CPU_SHARES_INVALID ? c->cpu_shares : CGROUP_CPU_SHARES_DEFAULT);
                 r = cg_set_attribute("cpu", path, "cpu.shares", buf);
                 if (r < 0)
                         log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r,
@@ -334,15 +344,15 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, M
         }
 
         if (mask & CGROUP_MASK_BLKIO) {
-                char buf[MAX3(DECIMAL_STR_MAX(unsigned long)+1,
-                              DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(unsigned long)*1,
+                char buf[MAX(DECIMAL_STR_MAX(uint64_t)+1,
                               DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1)];
                 CGroupBlockIODeviceWeight *w;
                 CGroupBlockIODeviceBandwidth *b;
 
                 if (!is_root) {
-                        sprintf(buf, "%lu\n", IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && c->startup_blockio_weight != (unsigned long) -1 ? c->startup_blockio_weight :
-                                c->blockio_weight != (unsigned long) -1 ? c->blockio_weight : 1000);
+                        sprintf(buf, "%" PRIu64 "\n",
+                                IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && c->startup_blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ? c->startup_blockio_weight :
+                                c->blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ? c->blockio_weight : CGROUP_BLKIO_WEIGHT_DEFAULT);
                         r = cg_set_attribute("blkio", path, "blkio.weight", buf);
                         if (r < 0)
                                 log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r,
@@ -356,7 +366,7 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, M
                                 if (r < 0)
                                         continue;
 
-                                sprintf(buf, "%u:%u %lu", major(dev), minor(dev), w->weight);
+                                sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), w->weight);
                                 r = cg_set_attribute("blkio", path, "blkio.weight_device", buf);
                                 if (r < 0)
                                         log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r,
@@ -406,7 +416,7 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, M
                                        "Failed to set memory.limit_in_bytes/memory.max on %s: %m", path);
         }
 
-        if ((mask & CGROUP_MASK_DEVICE) && !is_root) {
+        if ((mask & CGROUP_MASK_DEVICES) && !is_root) {
                 CGroupDeviceAllow *a;
 
                 /* Changing the devices list of a populated cgroup
@@ -468,6 +478,32 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, M
                                 log_debug("Ignoring device %s while writing cgroup attribute.", a->path);
                 }
         }
+
+        if ((mask & CGROUP_MASK_PIDS) && !is_root) {
+
+                if (c->tasks_max != (uint64_t) -1) {
+                        char buf[DECIMAL_STR_MAX(uint64_t) + 2];
+
+                        sprintf(buf, "%" PRIu64 "\n", c->tasks_max);
+                        r = cg_set_attribute("pids", path, "pids.max", buf);
+                } else
+                        r = cg_set_attribute("pids", path, "pids.max", "max");
+
+                if (r < 0)
+                        log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r,
+                                       "Failed to set pids.max on %s: %m", path);
+        }
+
+        if (mask & CGROUP_MASK_NET_CLS) {
+                char buf[DECIMAL_STR_MAX(uint32_t)];
+
+                sprintf(buf, "%" PRIu32, netclass);
+
+                r = cg_set_attribute("net_cls", path, "net_cls.classid", buf);
+                if (r < 0)
+                        log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r,
+                                       "Failed to set net_cls.classid on %s: %m", path);
+        }
 }
 
 CGroupMask cgroup_context_get_mask(CGroupContext *c) {
@@ -476,14 +512,14 @@ CGroupMask cgroup_context_get_mask(CGroupContext *c) {
         /* Figure out which controllers we need */
 
         if (c->cpu_accounting ||
-            c->cpu_shares != (unsigned long) -1 ||
-            c->startup_cpu_shares != (unsigned long) -1 ||
+            c->cpu_shares != CGROUP_CPU_SHARES_INVALID ||
+            c->startup_cpu_shares != CGROUP_CPU_SHARES_INVALID ||
             c->cpu_quota_per_sec_usec != USEC_INFINITY)
                 mask |= CGROUP_MASK_CPUACCT | CGROUP_MASK_CPU;
 
         if (c->blockio_accounting ||
-            c->blockio_weight != (unsigned long) -1 ||
-            c->startup_blockio_weight != (unsigned long) -1 ||
+            c->blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ||
+            c->startup_blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ||
             c->blockio_device_weights ||
             c->blockio_device_bandwidths)
                 mask |= CGROUP_MASK_BLKIO;
@@ -494,7 +530,14 @@ CGroupMask cgroup_context_get_mask(CGroupContext *c) {
 
         if (c->device_allow ||
             c->device_policy != CGROUP_AUTO)
-                mask |= CGROUP_MASK_DEVICE;
+                mask |= CGROUP_MASK_DEVICES;
+
+        if (c->tasks_accounting ||
+            c->tasks_max != (uint64_t) -1)
+                mask |= CGROUP_MASK_PIDS;
+
+        if (c->netclass_type != CGROUP_NETCLASS_TYPE_NONE)
+                mask |= CGROUP_MASK_NET_CLS;
 
         return mask;
 }
@@ -863,6 +906,103 @@ static bool unit_has_mask_realized(Unit *u, CGroupMask target_mask) {
         return u->cgroup_realized && u->cgroup_realized_mask == target_mask;
 }
 
+static int unit_find_free_netclass_cgroup(Unit *u, uint32_t *ret) {
+
+        uint32_t start, i;
+        Manager *m;
+
+        assert(u);
+
+        m = u->manager;
+
+        i = start = m->cgroup_netclass_registry_last;
+
+        do {
+                i++;
+
+                if (!hashmap_get(m->cgroup_netclass_registry, UINT_TO_PTR(i))) {
+                        m->cgroup_netclass_registry_last = i;
+                        *ret = i;
+                        return 0;
+                }
+
+                if (i == UINT32_MAX)
+                        i = CGROUP_NETCLASS_FIXED_MAX;
+
+        } while (i != start);
+
+        return -ENOBUFS;
+}
+
+int unit_add_to_netclass_cgroup(Unit *u) {
+
+        CGroupContext *cc;
+        Unit *first;
+        void *key;
+        int r;
+
+        assert(u);
+
+        cc = unit_get_cgroup_context(u);
+        if (!cc)
+                return 0;
+
+        switch (cc->netclass_type) {
+        case CGROUP_NETCLASS_TYPE_NONE:
+                return 0;
+
+        case CGROUP_NETCLASS_TYPE_FIXED:
+                u->cgroup_netclass_id = cc->netclass_id;
+                break;
+
+        case CGROUP_NETCLASS_TYPE_AUTO:
+                /* Allocate a new ID in case it was requested and not done yet */
+                if (u->cgroup_netclass_id == 0) {
+                        r = unit_find_free_netclass_cgroup(u, &u->cgroup_netclass_id);
+                        if (r < 0)
+                                return r;
+
+                        log_debug("Dynamically assigned netclass cgroup id %" PRIu32 " to %s", u->cgroup_netclass_id, u->id);
+                }
+
+                break;
+        }
+
+        r = hashmap_ensure_allocated(&u->manager->cgroup_netclass_registry, &trivial_hash_ops);
+        if (r < 0)
+                return r;
+
+        key = UINT32_TO_PTR(u->cgroup_netclass_id);
+        first = hashmap_get(u->manager->cgroup_netclass_registry, key);
+
+        if (first) {
+                LIST_PREPEND(cgroup_netclass, first, u);
+                return hashmap_replace(u->manager->cgroup_netclass_registry, key, u);
+        }
+
+        return hashmap_put(u->manager->cgroup_netclass_registry, key, u);
+}
+
+int unit_remove_from_netclass_cgroup(Unit *u) {
+
+        Unit *head;
+        void *key;
+
+        assert(u);
+
+        key = UINT32_TO_PTR(u->cgroup_netclass_id);
+
+        LIST_FIND_HEAD(cgroup_netclass, u, head);
+        LIST_REMOVE(cgroup_netclass, head, u);
+
+        if (head)
+                return hashmap_replace(u->manager->cgroup_netclass_registry, key, head);
+
+        hashmap_remove(u->manager->cgroup_netclass_registry, key);
+
+        return 0;
+}
+
 /* Check if necessary controllers and attributes for a unit are in place.
  *
  * If so, do nothing.
@@ -898,7 +1038,7 @@ static int unit_realize_cgroup_now(Unit *u, ManagerState state) {
                 return r;
 
         /* Finally, apply the necessary attributes. */
-        cgroup_context_apply(unit_get_cgroup_context(u), target_mask, u->cgroup_path, state);
+        cgroup_context_apply(unit_get_cgroup_context(u), target_mask, u->cgroup_path, u->cgroup_netclass_id, state);
 
         return 0;
 }
@@ -1239,7 +1379,7 @@ int manager_setup_cgroup(Manager *m) {
          * it. This is to support live upgrades from older systemd
          * versions where PID 1 was moved there. Also see
          * cg_get_root_path(). */
-        if (!e) {
+        if (!e && m->running_as == MANAGER_SYSTEM) {
                 e = endswith(m->cgroup_root, "/" SPECIAL_SYSTEM_SLICE);
                 if (!e)
                         e = endswith(m->cgroup_root, "/system"); /* even more legacy */
@@ -1277,6 +1417,7 @@ int manager_setup_cgroup(Manager *m) {
 
                         /* In the unified hierarchy we can can get
                          * cgroup empty notifications via inotify. */
+
 /// elogind does not support the unified hierarchy, yet.
 #if 0
                         m->cgroup_inotify_event_source = sd_event_source_unref(m->cgroup_inotify_event_source);
@@ -1300,6 +1441,7 @@ int manager_setup_cgroup(Manager *m) {
                         return log_error_errno(EOPNOTSUPP, "Unified cgroup hierarchy not supported: %m");
 #endif // 0
                 } else if (m->running_as == MANAGER_SYSTEM) {
+
                         /* On the legacy hierarchy we only get
                          * notifications via cgroup agents. (Which
                          * isn't really reliable, since it does not
@@ -1492,6 +1634,28 @@ int unit_get_memory_current(Unit *u, uint64_t *ret) {
         return safe_atou64(v, ret);
 }
 
+int unit_get_tasks_current(Unit *u, uint64_t *ret) {
+        _cleanup_free_ char *v = NULL;
+        int r;
+
+        assert(u);
+        assert(ret);
+
+        if (!u->cgroup_path)
+                return -ENODATA;
+
+        if ((u->cgroup_realized_mask & CGROUP_MASK_PIDS) == 0)
+                return -ENODATA;
+
+        r = cg_get_attribute("pids", u->cgroup_path, "pids.current", &v);
+        if (r == -ENOENT)
+                return -ENODATA;
+        if (r < 0)
+                return r;
+
+        return safe_atou64(v, ret);
+}
+
 static int unit_get_cpu_usage_raw(Unit *u, nsec_t *ret) {
         _cleanup_free_ char *v = NULL;
         uint64_t ns;
@@ -1565,6 +1729,32 @@ bool unit_cgroup_delegate(Unit *u) {
         return c->delegate;
 }
 
+void unit_invalidate_cgroup(Unit *u, CGroupMask m) {
+        assert(u);
+
+        if (!UNIT_HAS_CGROUP_CONTEXT(u))
+                return;
+
+        if (m == 0)
+                return;
+
+        if ((u->cgroup_realized_mask & m) == 0)
+                return;
+
+        u->cgroup_realized_mask &= ~m;
+        unit_add_to_cgroup_queue(u);
+}
+
+void manager_invalidate_startup_units(Manager *m) {
+        Iterator i;
+        Unit *u;
+
+        assert(m);
+
+        SET_FOREACH(u, m->startup_units, i)
+                unit_invalidate_cgroup(u, CGROUP_MASK_CPU|CGROUP_MASK_BLKIO);
+}
+
 static const char* const cgroup_device_policy_table[_CGROUP_DEVICE_POLICY_MAX] = {
         [CGROUP_AUTO] = "auto",
         [CGROUP_CLOSED] = "closed",
index be882a0..29782c5 100644 (file)
 // UNNEEDED typedef struct CGroupBlockIODeviceWeight CGroupBlockIODeviceWeight;
 // UNNEEDED typedef struct CGroupBlockIODeviceBandwidth CGroupBlockIODeviceBandwidth;
 
+/* Maximum value for fixed (manual) net class ID assignment,
+ * and also the value at which the range of automatic assignments starts
+ */
+// UNNEEDED #define CGROUP_NETCLASS_FIXED_MAX UINT32_C(65535)
+
+// UNNEEDED typedef struct CGroupContext CGroupContext;
+// UNNEEDED typedef struct CGroupDeviceAllow CGroupDeviceAllow;
+// UNNEEDED typedef struct CGroupBlockIODeviceWeight CGroupBlockIODeviceWeight;
+// UNNEEDED typedef struct CGroupBlockIODeviceBandwidth CGroupBlockIODeviceBandwidth;
+
 /// UNNEEDED by elogind
 #if 0
 typedef enum CGroupDevicePolicy {
@@ -50,6 +60,17 @@ typedef enum CGroupDevicePolicy {
         _CGROUP_DEVICE_POLICY_INVALID = -1
 } CGroupDevicePolicy;
 
+typedef enum CGroupNetClassType {
+        /* Default - do not assign a net class */
+        CGROUP_NETCLASS_TYPE_NONE,
+
+        /* Automatically assign a net class */
+        CGROUP_NETCLASS_TYPE_AUTO,
+
+        /* Assign the net class that was provided by the user */
+        CGROUP_NETCLASS_TYPE_FIXED,
+} CGroupNetClassType;
+
 struct CGroupDeviceAllow {
         LIST_FIELDS(CGroupDeviceAllow, device_allow);
         char *path;
@@ -61,7 +82,7 @@ struct CGroupDeviceAllow {
 struct CGroupBlockIODeviceWeight {
         LIST_FIELDS(CGroupBlockIODeviceWeight, device_weights);
         char *path;
-        unsigned long weight;
+        uint64_t weight;
 };
 
 struct CGroupBlockIODeviceBandwidth {
@@ -76,12 +97,12 @@ struct CGroupContext {
         bool blockio_accounting;
         bool memory_accounting;
 
-        unsigned long cpu_shares;
-        unsigned long startup_cpu_shares;
+        uint64_t cpu_shares;
+        uint64_t startup_cpu_shares;
         usec_t cpu_quota_per_sec_usec;
 
-        unsigned long blockio_weight;
-        unsigned long startup_blockio_weight;
+        uint64_t blockio_weight;
+        uint64_t startup_blockio_weight;
         LIST_HEAD(CGroupBlockIODeviceWeight, blockio_device_weights);
         LIST_HEAD(CGroupBlockIODeviceBandwidth, blockio_device_bandwidths);
 
@@ -90,6 +111,11 @@ struct CGroupContext {
         CGroupDevicePolicy device_policy;
         LIST_HEAD(CGroupDeviceAllow, device_allow);
 
+        CGroupNetClassType netclass_type;
+        uint32_t netclass_id;
+
+        uint64_t tasks_max;
+
         bool delegate;
 };
 #endif // 0
@@ -128,6 +154,9 @@ struct CGroupContext {
 
 // UNNEEDED int unit_attach_pids_to_cgroup(Unit *u);
 
+// UNNEEDED int unit_add_to_netclass_cgroup(Unit *u);
+// UNNEEDED int unit_remove_from_netclass_cgroup(Unit *u);
+
 int manager_setup_cgroup(Manager *m);
 void manager_shutdown_cgroup(Manager *m, bool delete);
 
@@ -141,6 +170,7 @@ void manager_shutdown_cgroup(Manager *m, bool delete);
 // UNNEEDED int unit_watch_all_pids(Unit *u);
 
 // UNNEEDED int unit_get_memory_current(Unit *u, uint64_t *ret);
+// UNNEEDED int unit_get_tasks_current(Unit *u, uint64_t *ret);
 // UNNEEDED int unit_get_cpu_usage(Unit *u, nsec_t *ret);
 // UNNEEDED int unit_reset_cpu_usage(Unit *u);
 
@@ -149,5 +179,9 @@ void manager_shutdown_cgroup(Manager *m, bool delete);
 // UNNEEDED int unit_notify_cgroup_empty(Unit *u);
 // UNNEEDED int manager_notify_cgroup_empty(Manager *m, const char *group);
 
+// UNNEEDED void unit_invalidate_cgroup(Unit *u, CGroupMask m);
+
+// UNNEEDED void manager_invalidate_startup_units(Manager *m);
+
 // UNNEEDED const char* cgroup_device_policy_to_string(CGroupDevicePolicy i) _const_;
 // UNNEEDED CGroupDevicePolicy cgroup_device_policy_from_string(const char *s) _pure_;
index 9c96750..9dfa778 100644 (file)
@@ -181,7 +181,7 @@ static int mount_one(const MountPoint *p, bool relabel) {
                 return 0;
 
         /* Skip securityfs in a container */
-        if (!(p->mode & MNT_IN_CONTAINER) && detect_container(NULL) > 0)
+        if (!(p->mode & MNT_IN_CONTAINER) && detect_container() > 0)
                 return 0;
 
         /* The access mode here doesn't really matter too much, since
@@ -412,7 +412,7 @@ int mount_setup(bool loaded_policy) {
          * nspawn and the container tools work out of the box. If
          * specific setups need other settings they can reset the
          * propagation mode to private if needed. */
-        if (detect_container(NULL) <= 0)
+        if (detect_container() <= 0)
                 if (mount(NULL, "/", NULL, MS_REC|MS_SHARED, NULL) < 0)
                         log_warning_errno(errno, "Failed to set up the root directory for shared mount propagation: %m");
 
index b79d0a3..7b9854a 100644 (file)
@@ -473,3 +473,11 @@ global:
         sd_pid_get_cgroup;
         sd_peer_get_cgroup;
 } LIBSYSTEMD_222;
+
+LIBSYSTEMD_227 {
+global:
+        sd_bus_default_flush_close;
+        /* sd_bus_path_decode_many; */
+        /* sd_bus_path_encode_many; */
+        /* sd_listen_fds_with_names; */
+} LIBSYSTEMD_226;
index 5c607f4..435ec92 100644 (file)
@@ -217,15 +217,8 @@ int bus_container_connect_kernel(sd_bus *b) {
                                 _exit(EXIT_FAILURE);
                         }
 
-                        cmsg = CMSG_FIRSTHDR(&mh);
-                        cmsg->cmsg_level = SOL_SOCKET;
-                        cmsg->cmsg_type = SCM_RIGHTS;
-                        cmsg->cmsg_len = CMSG_LEN(sizeof(int));
-                        memcpy(CMSG_DATA(cmsg), &fd, sizeof(int));
-
-                        mh.msg_controllen = cmsg->cmsg_len;
-
-                        if (sendmsg(pair[1], &mh, MSG_NOSIGNAL) < 0)
+                        r = send_one_fd(pair[1], fd, 0);
+                        if (r < 0)
                                 _exit(EXIT_FAILURE);
 
                         _exit(EXIT_SUCCESS);
index 4fccae5..ed82df2 100644 (file)
@@ -109,8 +109,7 @@ _public_ sd_bus_creds *sd_bus_creds_unref(sd_bus_creds *c) {
 
                         c->supplementary_gids = mfree(c->supplementary_gids);
 
-                        strv_free(c->well_known_names);
-                        c->well_known_names = NULL;
+                        c->well_known_names = strv_free(c->well_known_names);
 
                         bus_creds_done(c);
 
@@ -1047,9 +1046,8 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
                         if (r != -EPERM && r != -EACCES)
                                 return r;
                 } else {
-                        if (c->cmdline_size == 0) {
+                        if (c->cmdline_size == 0)
                                 c->cmdline = mfree(c->cmdline);
-                        }
 
                         c->mask |= SD_BUS_CREDS_CMDLINE;
                 }
index 14f4038..c3aaa9b 100644 (file)
@@ -204,8 +204,7 @@ int introspect_finish(struct introspect *i, sd_bus *bus, sd_bus_message *m, sd_b
 void introspect_free(struct introspect *i) {
         assert(i);
 
-        if (i->f)
-                fclose(i->f);
+        safe_fclose(i->f);
 
         free(i->introspection);
         zero(*i);
index 05a00f2..fdfd005 100644 (file)
@@ -1578,25 +1578,14 @@ _public_ int sd_bus_add_fallback(
         return bus_add_object(bus, slot, true, prefix, callback, userdata);
 }
 
-static unsigned long vtable_member_hash_func(const void *a, const uint8_t hash_key[HASH_KEY_SIZE]) {
+static void vtable_member_hash_func(const void *a, struct siphash *state) {
         const struct vtable_member *m = a;
-        uint8_t hash_key2[HASH_KEY_SIZE];
-        unsigned long ret;
 
         assert(m);
 
-        ret = string_hash_func(m->path, hash_key);
-
-        /* Use a slightly different hash key for the interface */
-        memcpy(hash_key2, hash_key, HASH_KEY_SIZE);
-        hash_key2[0]++;
-        ret ^= string_hash_func(m->interface, hash_key2);
-
-        /* And an even different one for the  member */
-        hash_key2[0]++;
-        ret ^= string_hash_func(m->member, hash_key2);
-
-        return ret;
+        string_hash_func(m->path, state);
+        string_hash_func(m->interface, state);
+        string_hash_func(m->member, state);
 }
 
 static int vtable_member_compare_func(const void *a, const void *b) {
index 70f1c93..15f5fe1 100644 (file)
@@ -69,6 +69,10 @@ static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec);
 static int attach_io_events(sd_bus *b);
 static void detach_io_events(sd_bus *b);
 
+static thread_local sd_bus *default_system_bus = NULL;
+static thread_local sd_bus *default_user_bus = NULL;
+static thread_local sd_bus *default_starter_bus = NULL;
+
 static void bus_close_fds(sd_bus *b) {
         assert(b);
 
@@ -3386,16 +3390,13 @@ static int bus_default(int (*bus_open)(sd_bus **), sd_bus **default_bus, sd_bus
 }
 
 _public_ int sd_bus_default_system(sd_bus **ret) {
-        static thread_local sd_bus *default_system_bus = NULL;
-
         return bus_default(sd_bus_open_system, &default_system_bus, ret);
 }
 
+
 _public_ int sd_bus_default_user(sd_bus **ret) {
 /// elogind does not support user buses
 #if 0
-        static thread_local sd_bus *default_user_bus = NULL;
-
         return bus_default(sd_bus_open_user, &default_user_bus, ret);
 #else
         return sd_bus_default_system(ret);
@@ -3428,13 +3429,13 @@ _public_ int sd_bus_default(sd_bus **ret) {
 
         e = secure_getenv("DBUS_STARTER_ADDRESS");
         if (e) {
-                static thread_local sd_bus *default_starter_bus = NULL;
 
                 return bus_default(sd_bus_open, &default_starter_bus, ret);
         }
 
         /* Finally, if nothing is set use the cached connection for
          * the right scope */
+
 /// elogind does not support systemd units
 #if 0
         if (cg_pid_get_owner_uid(0, NULL) >= 0)
@@ -3503,6 +3504,171 @@ _public_ int sd_bus_path_decode(const char *path, const char *prefix, char **ext
         *external_id = ret;
         return 1;
 }
+
+_public_ int sd_bus_path_encode_many(char **out, const char *path_template, ...) {
+        _cleanup_strv_free_ char **labels = NULL;
+        char *path, *path_pos, **label_pos;
+        const char *sep, *template_pos;
+        size_t path_length;
+        va_list list;
+        int r;
+
+        assert_return(out, -EINVAL);
+        assert_return(path_template, -EINVAL);
+
+        path_length = strlen(path_template);
+
+        va_start(list, path_template);
+        for (sep = strchr(path_template, '%'); sep; sep = strchr(sep + 1, '%')) {
+                const char *arg;
+                char *label;
+
+                arg = va_arg(list, const char *);
+                if (!arg) {
+                        va_end(list);
+                        return -EINVAL;
+                }
+
+                label = bus_label_escape(arg);
+                if (!label) {
+                        va_end(list);
+                        return -ENOMEM;
+                }
+
+                r = strv_consume(&labels, label);
+                if (r < 0) {
+                        va_end(list);
+                        return r;
+                }
+
+                /* add label length, but account for the format character */
+                path_length += strlen(label) - 1;
+        }
+        va_end(list);
+
+        path = malloc(path_length + 1);
+        if (!path)
+                return -ENOMEM;
+
+        path_pos = path;
+        label_pos = labels;
+
+        for (template_pos = path_template; *template_pos; ) {
+                sep = strchrnul(template_pos, '%');
+                path_pos = mempcpy(path_pos, template_pos, sep - template_pos);
+                if (!*sep)
+                        break;
+
+                path_pos = stpcpy(path_pos, *label_pos++);
+                template_pos = sep + 1;
+        }
+
+        *path_pos = 0;
+        *out = path;
+        return 0;
+}
+
+_public_ int sd_bus_path_decode_many(const char *path, const char *path_template, ...) {
+        _cleanup_strv_free_ char **labels = NULL;
+        const char *template_pos, *path_pos;
+        char **label_pos;
+        va_list list;
+        int r;
+
+        /*
+         * This decodes an object-path based on a template argument. The
+         * template consists of a verbatim path, optionally including special
+         * directives:
+         *
+         *   - Each occurrence of '%' in the template matches an arbitrary
+         *     substring of a label in the given path. At most one such
+         *     directive is allowed per label. For each such directive, the
+         *     caller must provide an output parameter (char **) via va_arg. If
+         *     NULL is passed, the given label is verified, but not returned.
+         *     For each matched label, the *decoded* label is stored in the
+         *     passed output argument, and the caller is responsible to free
+         *     it. Note that the output arguments are only modified if the
+         *     actualy path matched the template. Otherwise, they're left
+         *     untouched.
+         *
+         * This function returns <0 on error, 0 if the path does not match the
+         * template, 1 if it matched.
+         */
+
+        assert_return(path, -EINVAL);
+        assert_return(path_template, -EINVAL);
+
+        path_pos = path;
+
+        for (template_pos = path_template; *template_pos; ) {
+                const char *sep;
+                size_t length;
+                char *label;
+
+                /* verify everything until the next '%' matches verbatim */
+                sep = strchrnul(template_pos, '%');
+                length = sep - template_pos;
+                if (strncmp(path_pos, template_pos, length))
+                        return 0;
+
+                path_pos += length;
+                template_pos += length;
+
+                if (!*template_pos)
+                        break;
+
+                /* We found the next '%' character. Everything up until here
+                 * matched. We now skip ahead to the end of this label and make
+                 * sure it matches the tail of the label in the path. Then we
+                 * decode the string in-between and save it for later use. */
+
+                ++template_pos; /* skip over '%' */
+
+                sep = strchrnul(template_pos, '/');
+                length = sep - template_pos; /* length of suffix to match verbatim */
+
+                /* verify the suffixes match */
+                sep = strchrnul(path_pos, '/');
+                if (sep - path_pos < (ssize_t)length ||
+                    strncmp(sep - length, template_pos, length))
+                        return 0;
+
+                template_pos += length; /* skip over matched label */
+                length = sep - path_pos - length; /* length of sub-label to decode */
+
+                /* store unescaped label for later use */
+                label = bus_label_unescape_n(path_pos, length);
+                if (!label)
+                        return -ENOMEM;
+
+                r = strv_consume(&labels, label);
+                if (r < 0)
+                        return r;
+
+                path_pos = sep; /* skip decoded label and suffix */
+        }
+
+        /* end of template must match end of path */
+        if (*path_pos)
+                return 0;
+
+        /* copy the labels over to the caller */
+        va_start(list, path_template);
+        for (label_pos = labels; label_pos && *label_pos; ++label_pos) {
+                char **arg;
+
+                arg = va_arg(list, char **);
+                if (arg)
+                        *arg = *label_pos;
+                else
+                        free(*label_pos);
+        }
+        va_end(list);
+
+        free(labels);
+        labels = NULL;
+        return 1;
+}
 #endif // 0
 
 _public_ int sd_bus_try_close(sd_bus *bus) {
@@ -3662,3 +3828,20 @@ _public_ int sd_bus_is_monitor(sd_bus *bus) {
         return !!(bus->hello_flags & KDBUS_HELLO_MONITOR);
 }
 #endif // 0
+
+static void flush_close(sd_bus *bus) {
+        if (!bus)
+                return;
+
+        /* Flushes and closes the specified bus. We take a ref before,
+         * to ensure the flushing does not cause the bus to be
+         * unreferenced. */
+
+        sd_bus_flush_close_unref(sd_bus_ref(bus));
+}
+
+_public_ void sd_bus_default_flush_close(void) {
+        flush_close(default_starter_bus);
+        flush_close(default_user_bus);
+        flush_close(default_system_bus);
+}
index f74f44c..c6224f8 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <netinet/in.h>
-#include <stdlib.h>
 #include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stddef.h>
 #include <limits.h>
 //#include <mqueue.h>
+#include <netinet/in.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include <unistd.h>
 
-#include "util.h"
 #include "path-util.h"
 #include "socket-util.h"
+//#include "strv.h"
+#include "util.h"
+
 #include "sd-daemon.h"
 
 /// UNNEEDED by elogind
 #if 0
+static void unsetenv_all(bool unset_environment) {
+
+        if (!unset_environment)
+                return;
+
+        unsetenv("LISTEN_PID");
+        unsetenv("LISTEN_FDS");
+        unsetenv("LISTEN_FDNAMES");
+}
+
 _public_ int sd_listen_fds(int unset_environment) {
         const char *e;
         unsigned n;
@@ -81,14 +93,51 @@ _public_ int sd_listen_fds(int unset_environment) {
         r = (int) n;
 
 finish:
-        if (unset_environment) {
-                unsetenv("LISTEN_PID");
-                unsetenv("LISTEN_FDS");
+        unsetenv_all(unset_environment);
+        return r;
         }
 
+_public_ int sd_listen_fds_with_names(int unset_environment, char ***names) {
+        _cleanup_strv_free_ char **l = NULL;
+        bool have_names;
+        int n_names = 0, n_fds;
+        const char *e;
+        int r;
+
+        if (!names)
+                return sd_listen_fds(unset_environment);
+
+        e = getenv("LISTEN_FDNAMES");
+        if (e) {
+                n_names = strv_split_extract(&l, e, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
+                if (n_names < 0) {
+                        unsetenv_all(unset_environment);
+                        return n_names;
+                }
+
+                have_names = true;
+        } else
+                have_names = false;
+
+        n_fds = sd_listen_fds(unset_environment);
+        if (n_fds <= 0)
+                return n_fds;
+
+        if (have_names) {
+                if (n_names != n_fds)
+                        return -EINVAL;
+        } else {
+                r = strv_extend_n(&l, "unknown", n_fds);
+                if (r < 0)
         return r;
 }
 
+        *names = l;
+        l = NULL;
+
+        return n_fds;
+}
+
 _public_ int sd_is_fifo(int fd, const char *path) {
         struct stat st_fd;
 
@@ -511,16 +560,11 @@ _public_ int sd_notifyf(int unset_environment, const char *format, ...) {
 }
 
 _public_ int sd_booted(void) {
-        struct stat st;
-
         /* We test whether the runtime unit file directory has been
          * created. This takes place in mount-setup.c, so is
          * guaranteed to happen very early during boot. */
 
-        if (lstat("/run/systemd/system/", &st) < 0)
-                return 0;
-
-        return !!S_ISDIR(st.st_mode);
+        return laccess("/run/systemd/system/", F_OK) >= 0;
 }
 #endif // 0
 
index 2041d87..6c81c18 100644 (file)
@@ -305,6 +305,8 @@ _public_ int sd_peer_get_cgroup(int fd, char **cgroup) {
 }
 
 static int file_of_uid(uid_t uid, char **p) {
+
+        assert_return(uid_is_valid(uid), -EINVAL);
         assert(p);
 
         if (asprintf(p, "/run/systemd/users/" UID_FMT, uid) < 0)
@@ -331,11 +333,15 @@ _public_ int sd_uid_get_state(uid_t uid, char**state) {
                 if (!s)
                         return -ENOMEM;
 
-        } else if (r < 0) {
+        }
+        if (r < 0) {
                 free(s);
                 return r;
-        } else if (!s)
+        }
+        if (isempty(s)) {
+                free(s);
                 return -EIO;
+        }
 
         *state = s;
         return 0;
@@ -353,12 +359,11 @@ _public_ int sd_uid_get_display(uid_t uid, char **session) {
 
         r = parse_env_file(p, NEWLINE, "DISPLAY", &s, NULL);
         if (r == -ENOENT)
-                return -ENXIO;
+                return -ENODATA;
         if (r < 0)
                 return r;
-
         if (isempty(s))
-                return -ENXIO;
+                return -ENODATA;
 
         *session = s;
         s = NULL;
@@ -366,35 +371,63 @@ _public_ int sd_uid_get_display(uid_t uid, char **session) {
         return 0;
 }
 
-_public_ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat) {
-        _cleanup_free_ char *t = NULL, *s = NULL, *p = NULL;
-        size_t l;
+static int file_of_seat(const char *seat, char **_p) {
+        char *p;
         int r;
-        const char *word, *variable, *state;
 
-        assert_return(seat, -EINVAL);
+        assert(_p);
 
-        variable = require_active ? "ACTIVE_UID" : "UIDS";
+        if (seat) {
+                if (!filename_is_valid(seat))
+                        return -EINVAL;
 
         p = strappend("/run/systemd/seats/", seat);
+        } else {
+                _cleanup_free_ char *buf = NULL;
+
+                r = sd_session_get_seat(NULL, &buf);
+                if (r < 0)
+                        return r;
+
+                p = strappend("/run/systemd/seats/", buf);
+        }
+
         if (!p)
                 return -ENOMEM;
 
-        r = parse_env_file(p, NEWLINE, variable, &s, NULL);
+        *_p = p;
+        p = NULL;
+        return 0;
+}
+
+_public_ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat) {
+        _cleanup_free_ char *t = NULL, *s = NULL, *p = NULL;
+        size_t l;
+        int r;
+        const char *word, *variable, *state;
+
+        assert_return(uid_is_valid(uid), -EINVAL);
 
+        r = file_of_seat(seat, &p);
         if (r < 0)
                 return r;
 
-        if (!s)
-                return -EIO;
+        variable = require_active ? "ACTIVE_UID" : "UIDS";
+
+        r = parse_env_file(p, NEWLINE, variable, &s, NULL);
+        if (r == -ENOENT)
+                return 0;
+        if (r < 0)
+                return r;
+        if (isempty(s))
+                return 0;
 
         if (asprintf(&t, UID_FMT, uid) < 0)
                 return -ENOMEM;
 
-        FOREACH_WORD(word, l, s, state) {
+        FOREACH_WORD(word, l, s, state)
                 if (strneq(t, word, l))
                         return 1;
-        }
 
         return 0;
 }
@@ -404,31 +437,22 @@ static int uid_get_array(uid_t uid, const char *variable, char ***array) {
         char **a;
         int r;
 
+        assert(variable);
+
         r = file_of_uid(uid, &p);
         if (r < 0)
                 return r;
 
-        r = parse_env_file(p, NEWLINE,
-                           variable, &s,
-                           NULL);
-        if (r < 0) {
-                if (r == -ENOENT) {
+        r = parse_env_file(p, NEWLINE, variable, &s, NULL);
+        if (r == -ENOENT || (r >= 0 && isempty(s))) {
                         if (array)
                                 *array = NULL;
                         return 0;
                 }
-
+        if (r < 0)
                 return r;
-        }
-
-        if (!s) {
-                if (array)
-                        *array = NULL;
-                return 0;
-        }
 
         a = strv_split(s, " ");
-
         if (!a)
                 return -ENOMEM;
 
@@ -490,37 +514,39 @@ static int file_of_session(const char *session, char **_p) {
 }
 
 _public_ int sd_session_is_active(const char *session) {
-        int r;
         _cleanup_free_ char *p = NULL, *s = NULL;
+        int r;
 
         r = file_of_session(session, &p);
         if (r < 0)
                 return r;
 
         r = parse_env_file(p, NEWLINE, "ACTIVE", &s, NULL);
+        if (r == -ENOENT)
+                return -ENXIO;
         if (r < 0)
                 return r;
-
-        if (!s)
+        if (isempty(s))
                 return -EIO;
 
         return parse_boolean(s);
 }
 
 _public_ int sd_session_is_remote(const char *session) {
-        int r;
         _cleanup_free_ char *p = NULL, *s = NULL;
+        int r;
 
         r = file_of_session(session, &p);
         if (r < 0)
                 return r;
 
         r = parse_env_file(p, NEWLINE, "REMOTE", &s, NULL);
+        if (r == -ENOENT)
+                return -ENXIO;
         if (r < 0)
                 return r;
-
-        if (!s)
-                return -EIO;
+        if (isempty(s))
+                return -ENODATA;
 
         return parse_boolean(s);
 }
@@ -536,9 +562,11 @@ _public_ int sd_session_get_state(const char *session, char **state) {
                 return r;
 
         r = parse_env_file(p, NEWLINE, "STATE", &s, NULL);
+        if (r == -ENOENT)
+                return -ENXIO;
         if (r < 0)
                 return r;
-        else if (!s)
+        if (isempty(s))
                 return -EIO;
 
         *state = s;
@@ -558,10 +586,11 @@ _public_ int sd_session_get_uid(const char *session, uid_t *uid) {
                 return r;
 
         r = parse_env_file(p, NEWLINE, "UID", &s, NULL);
+        if (r == -ENOENT)
+                return -ENXIO;
         if (r < 0)
                 return r;
-
-        if (!s)
+        if (isempty(s))
                 return -EIO;
 
         return parse_uid(s, uid);
@@ -572,17 +601,19 @@ static int session_get_string(const char *session, const char *field, char **val
         int r;
 
         assert_return(value, -EINVAL);
+        assert(field);
 
         r = file_of_session(session, &p);
         if (r < 0)
                 return r;
 
         r = parse_env_file(p, NEWLINE, field, &s, NULL);
+        if (r == -ENOENT)
+                return -ENXIO;
         if (r < 0)
                 return r;
-
         if (isempty(s))
-                return -ENXIO;
+                return -ENODATA;
 
         *value = s;
         s = NULL;
@@ -602,6 +633,8 @@ _public_ int sd_session_get_vt(const char *session, unsigned *vtnr) {
         unsigned u;
         int r;
 
+        assert_return(vtnr, -EINVAL);
+
         r = session_get_string(session, "VTNR", &vtnr_string);
         if (r < 0)
                 return r;
@@ -657,32 +690,6 @@ _public_ int sd_session_get_remote_host(const char *session, char **remote_host)
         return session_get_string(session, "REMOTE_HOST", remote_host);
 }
 
-static int file_of_seat(const char *seat, char **_p) {
-        char *p;
-        int r;
-
-        assert(_p);
-
-        if (seat)
-                p = strappend("/run/systemd/seats/", seat);
-        else {
-                _cleanup_free_ char *buf = NULL;
-
-                r = sd_session_get_seat(NULL, &buf);
-                if (r < 0)
-                        return r;
-
-                p = strappend("/run/systemd/seats/", buf);
-        }
-
-        if (!p)
-                return -ENOMEM;
-
-        *_p = p;
-        p = NULL;
-        return 0;
-}
-
 _public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) {
         _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL;
         int r;
@@ -697,14 +704,16 @@ _public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) {
                            "ACTIVE", &s,
                            "ACTIVE_UID", &t,
                            NULL);
+        if (r == -ENOENT)
+                return -ENXIO;
         if (r < 0)
                 return r;
 
         if (session && !s)
-                return -ENOENT;
+                return -ENODATA;
 
         if (uid && !t)
-                return -ENOENT;
+                return -ENODATA;
 
         if (uid && t) {
                 r = parse_uid(t, uid);
@@ -735,7 +744,8 @@ _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **ui
                            "SESSIONS", &s,
                            "ACTIVE_SESSIONS", &t,
                            NULL);
-
+        if (r == -ENOENT)
+                return -ENXIO;
         if (r < 0)
                 return r;
 
@@ -767,7 +777,6 @@ _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **ui
                                         return -ENOMEM;
 
                                 r = parse_uid(k, b + i);
-
                                 if (r < 0)
                                         continue;
 
@@ -798,7 +807,7 @@ static int seat_get_can(const char *seat, const char *variable) {
         _cleanup_free_ char *p = NULL, *s = NULL;
         int r;
 
-        assert_return(variable, -EINVAL);
+        assert(variable);
 
         r = file_of_seat(seat, &p);
         if (r < 0)
@@ -807,10 +816,12 @@ static int seat_get_can(const char *seat, const char *variable) {
         r = parse_env_file(p, NEWLINE,
                            variable, &s,
                            NULL);
+        if (r == -ENOENT)
+                return -ENXIO;
         if (r < 0)
                 return r;
-        if (!s)
-                return 0;
+        if (isempty(s))
+                return -ENODATA;
 
         return parse_boolean(s);
 }
@@ -934,6 +945,8 @@ _public_ int sd_machine_get_class(const char *machine, char **class) {
 
         p = strjoina("/run/systemd/machines/", machine);
         r = parse_env_file(p, NEWLINE, "CLASS", &c, NULL);
+        if (r == -ENOENT)
+                return -ENXIO;
         if (r < 0)
                 return r;
         if (!c)
@@ -957,6 +970,8 @@ _public_ int sd_machine_get_ifindices(const char *machine, int **ifindices) {
 
         p = strjoina("/run/systemd/machines/", machine);
         r = parse_env_file(p, NEWLINE, "NETIF", &netif, NULL);
+        if (r == -ENOENT)
+                return -ENXIO;
         if (r < 0)
                 return r;
         if (!netif) {
index b27c581..b60ad0c 100644 (file)
@@ -33,7 +33,7 @@ static void test_login(void) {
         _cleanup_free_ char *pp = NULL, *qq = NULL;
         int r, k;
         uid_t u, u2;
-        char *seat, *type, *class, *display, *remote_user, *remote_host, *display_session;
+        char *seat, *type, *class, *display, *remote_user, *remote_host, *display_session, *cgroup;
         char *session;
         char *state;
         char *session2;
@@ -50,6 +50,10 @@ static void test_login(void) {
         assert_se(sd_pid_get_owner_uid(0, &u2) == 0);
         printf("user = "UID_FMT"\n", u2);
 
+        assert_se(sd_pid_get_cgroup(0, &cgroup) == 0);
+        printf("cgroup = %s\n", cgroup);
+        free(cgroup);
+
         display_session = NULL;
         r = sd_uid_get_display(u2, &display_session);
         assert_se(r >= 0 || r == -ENODATA);