chiark / gitweb /
core: catch some special cases in cg_slice_to_path()
[elogind.git] / src / shared / cgroup-util.c
index ce951174fb636df5ed9ad0c4d04d06347c15a870..ce8ebb2ca425bc8b3506c085bf0154b3044ca372 100644 (file)
@@ -1316,45 +1316,37 @@ static const char *skip_user_manager(const char *p) {
         return NULL;
 }
 
-int cg_path_get_user_unit(const char *path, char **ret) {
+static const char *skip_user_prefix(const char *path) {
         const char *e, *t;
-        char *unit;
-        int r;
 
         assert(path);
-        assert(ret);
-
-        /* We always have to parse the path from the beginning as unit
-         * cgroups might have arbitrary child cgroups and we shouldn't get
-         * confused by those */
 
         /* Skip slices, if there are any */
         e = skip_slices(path);
 
-        /* Skip the user manager... */
+        /* Skip the user manager, if it's in the path now... */
         t = skip_user_manager(e);
+        if (t)
+                return t;
 
-        /* Alternatively skip the user session... */
-        if (!t)
-                t = skip_session(e);
-        if (!t)
-                return -ENXIO;
+        /* Alternatively skip the user session if it is in the path... */
+        return skip_session(e);
+}
 
-        /* ... and skip more slices if there are any */
-        e = skip_slices(t);
+int cg_path_get_user_unit(const char *path, char **ret) {
+        const char *t;
 
-        r = cg_path_decode_unit(e, &unit);
-        if (r < 0)
-                return r;
+        assert(path);
+        assert(ret);
 
-        /* We skipped over the slices, don't accept any now */
-        if (endswith(unit, ".slice")) {
-                free(unit);
+        t = skip_user_prefix(path);
+        if (!t)
                 return -ENXIO;
-        }
 
-        *ret = unit;
-        return 0;
+        /* And from here on it looks pretty much the same as for a
+         * system unit, hence let's use the same parser from here
+         * on. */
+        return cg_path_get_unit(t, ret);
 }
 
 int cg_pid_get_user_unit(pid_t pid, char **unit) {
@@ -1486,6 +1478,9 @@ int cg_path_get_slice(const char *p, char **slice) {
         assert(p);
         assert(slice);
 
+        /* Finds the right-most slice unit from the beginning, but
+         * stops before we come to the first non-slice unit. */
+
         for (;;) {
                 size_t n;
 
@@ -1526,6 +1521,33 @@ int cg_pid_get_slice(pid_t pid, char **slice) {
         return cg_path_get_slice(cgroup, slice);
 }
 
+int cg_path_get_user_slice(const char *p, char **slice) {
+        const char *t;
+        assert(p);
+        assert(slice);
+
+        t = skip_user_prefix(p);
+        if (!t)
+                return -ENXIO;
+
+        /* And now it looks pretty much the same as for a system
+         * slice, so let's just use the same parser from here on. */
+        return cg_path_get_slice(t, slice);
+}
+
+int cg_pid_get_user_slice(pid_t pid, char **slice) {
+        _cleanup_free_ char *cgroup = NULL;
+        int r;
+
+        assert(slice);
+
+        r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
+        if (r < 0)
+                return r;
+
+        return cg_path_get_user_slice(cgroup, slice);
+}
+
 char *cg_escape(const char *p) {
         bool need_prefix = false;
 
@@ -1619,6 +1641,16 @@ int cg_slice_to_path(const char *unit, char **ret) {
         assert(unit);
         assert(ret);
 
+        if (streq(unit, "-.slice")) {
+                char *x;
+
+                x = strdup("");
+                if (!x)
+                        return -ENOMEM;
+                *ret = x;
+                return 0;
+        }
+
         if (!unit_name_is_valid(unit, TEMPLATE_INVALID))
                 return -EINVAL;
 
@@ -1634,8 +1666,10 @@ int cg_slice_to_path(const char *unit, char **ret) {
                 _cleanup_free_ char *escaped = NULL;
                 char n[dash - p + sizeof(".slice")];
 
-                strcpy(stpncpy(n, p, dash - p), ".slice");
+                if (isempty(dash + 1))
+                        return -EINVAL;
 
+                strcpy(stpncpy(n, p, dash - p), ".slice");
                 if (!unit_name_is_valid(n, TEMPLATE_INVALID))
                         return -EINVAL;