summaryrefslogtreecommitdiff
path: root/src/shared/cgroup-util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/shared/cgroup-util.c')
-rw-r--r--src/shared/cgroup-util.c220
1 files changed, 97 insertions, 123 deletions
diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c
index 4f58affe38..05d026a587 100644
--- a/src/shared/cgroup-util.c
+++ b/src/shared/cgroup-util.c
@@ -38,6 +38,7 @@
#include "strv.h"
#include "unit-name.h"
#include "fileio.h"
+#include "special.h"
int cg_enumerate_processes(const char *controller, const char *path, FILE **_f) {
_cleanup_free_ char *fs = NULL;
@@ -470,19 +471,19 @@ static const char *normalize_controller(const char *controller) {
static int join_path(const char *controller, const char *path, const char *suffix, char **fs) {
char *t = NULL;
- if (controller) {
- if (path && suffix)
+ if (!isempty(controller)) {
+ if (!isempty(path) && !isempty(suffix))
t = strjoin("/sys/fs/cgroup/", controller, "/", path, "/", suffix, NULL);
- else if (path)
+ else if (!isempty(path))
t = strjoin("/sys/fs/cgroup/", controller, "/", path, NULL);
- else if (suffix)
+ else if (!isempty(suffix))
t = strjoin("/sys/fs/cgroup/", controller, "/", suffix, NULL);
else
t = strappend("/sys/fs/cgroup/", controller);
} else {
- if (path && suffix)
+ if (!isempty(path) && !isempty(suffix))
t = strjoin(path, "/", suffix, NULL);
- else if (path)
+ else if (!isempty(path))
t = strdup(path);
else
return -EINVAL;
@@ -1091,96 +1092,20 @@ int cg_mangle_path(const char *path, char **result) {
return cg_get_path(c ? c : SYSTEMD_CGROUP_CONTROLLER, p ? p : "/", NULL, result);
}
-int cg_get_system_path(char **path) {
- char *p;
- int r;
-
- assert(path);
-
- r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, &p);
- if (r < 0) {
- p = strdup("/system");
- if (!p)
- return -ENOMEM;
- }
-
- if (endswith(p, "/system"))
- *path = p;
- else {
- char *q;
-
- q = strappend(p, "/system");
- free(p);
- if (!q)
- return -ENOMEM;
-
- *path = q;
- }
-
- return 0;
-}
-
int cg_get_root_path(char **path) {
- char *root, *e;
+ char *p, *e;
int r;
assert(path);
- r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, &root);
+ r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, &p);
if (r < 0)
return r;
- e = endswith(root, "/system");
- if (e == root)
- e[1] = 0;
- else if (e)
+ e = endswith(p, "/" SPECIAL_SYSTEM_SLICE);
+ if (e)
*e = 0;
- *path = root;
- return 0;
-}
-
-int cg_get_user_path(char **path) {
- _cleanup_free_ char *root = NULL;
- char *p;
-
- assert(path);
-
- /* Figure out the place to put user cgroups below. We use the
- * same as PID 1 has but with the "/system" suffix replaced by
- * "/user" */
-
- if (cg_get_root_path(&root) < 0 || streq(root, "/"))
- p = strdup("/user");
- else
- p = strappend(root, "/user");
-
- if (!p)
- return -ENOMEM;
-
- *path = p;
- return 0;
-}
-
-int cg_get_machine_path(const char *machine, char **path) {
- _cleanup_free_ char *root = NULL, *escaped = NULL;
- char *p;
-
- assert(path);
-
- if (machine) {
- const char *name = strappenda(machine, ".nspawn");
-
- escaped = cg_escape(name);
- if (!escaped)
- return -ENOMEM;
- }
-
- p = strjoin(cg_get_root_path(&root) >= 0 && !streq(root, "/") ? root : "",
- "/machine", machine ? "/" : "", machine ? escaped : "", NULL);
- if (!p)
- return -ENOMEM;
-
*path = p;
return 0;
}
@@ -1301,15 +1226,29 @@ int cg_path_decode_unit(const char *cgroup, char **unit){
return 0;
}
+static const char *skip_slices(const char *p) {
+ size_t n;
+
+ /* Skips over all slice assignments */
+
+ for (;;) {
+ p += strspn(p, "/");
+
+ n = strcspn(p, "/");
+ if (n <= 6 || memcmp(p + n - 6, ".slice", 6) != 0)
+ return p;
+
+ p += n;
+ }
+}
+
int cg_path_get_unit(const char *path, char **unit) {
const char *e;
assert(path);
assert(unit);
- e = path_startswith(path, "/system/");
- if (!e)
- return -ENOENT;
+ e = skip_slices(path);
return cg_path_decode_unit(e, unit);
}
@@ -1327,15 +1266,55 @@ int cg_pid_get_unit(pid_t pid, char **unit) {
return cg_path_get_unit(cgroup, unit);
}
-_pure_ static const char *skip_label(const char *e) {
- assert(e);
+static const char *skip_user(const char *p) {
+ size_t n;
- e = strchr(e, '/');
- if (!e)
+ assert(p);
+
+ p += strspn(p, "/");
+
+ n = strcspn(p, "/");
+ if (n <= 5 || memcmp(p + n - 5, ".user", 5) != 0)
+ return p;
+
+ p += n;
+ p += strspn(p, "/");
+
+ return p;
+}
+
+static const char *skip_session(const char *p) {
+ size_t n;
+
+ assert(p);
+
+ p += strspn(p, "/");
+
+ n = strcspn(p, "/");
+ if (n <= 8 || memcmp(p + n - 8, ".session", 8) != 0)
return NULL;
- e += strspn(e, "/");
- return e;
+ p += n;
+ p += strspn(p, "/");
+
+ return p;
+}
+
+static const char *skip_systemd_label(const char *p) {
+ size_t n;
+
+ assert(p);
+
+ p += strspn(p, "/");
+
+ n = strcspn(p, "/");
+ if (n < 8 || memcmp(p, "systemd-", 8) != 0)
+ return p;
+
+ p += n;
+ p += strspn(p, "/");
+
+ return p;
}
int cg_path_get_user_unit(const char *path, char **unit) {
@@ -1348,24 +1327,19 @@ int cg_path_get_user_unit(const char *path, char **unit) {
* cgroups might have arbitrary child cgroups and we shouldn't get
* confused by those */
- e = path_startswith(path, "/user/");
- if (!e)
- return -ENOENT;
+ /* Skip slices, if there are any */
+ e = skip_slices(path);
- /* Skip the user name */
- e = skip_label(e);
- if (!e)
- return -ENOENT;
+ /* Skip the user name, if there is one */
+ e = skip_user(e);
- /* Skip the session ID */
- e = skip_label(e);
+ /* Skip the session ID, require that there is one */
+ e = skip_session(e);
if (!e)
return -ENOENT;
- /* Skip the systemd cgroup */
- e = skip_label(e);
- if (!e)
- return -ENOENT;
+ /* Skip the systemd cgroup, if there is one */
+ e = skip_systemd_label(e);
return cg_path_decode_unit(e, unit);
}
@@ -1384,23 +1358,27 @@ int cg_pid_get_user_unit(pid_t pid, char **unit) {
}
int cg_path_get_machine_name(const char *path, char **machine) {
- const char *e, *n;
+ const char *e, *n, *x;
char *s, *r;
assert(path);
assert(machine);
- e = path_startswith(path, "/machine/");
- if (!e)
- return -ENOENT;
+ /* Skip slices, if there are any */
+ e = skip_slices(path);
n = strchrnul(e, '/');
if (e == n)
return -ENOENT;
s = strndupa(e, n - e);
+ s = cg_unescape(s);
+
+ x = endswith(s, ".machine");
+ if (!x)
+ return -ENOENT;
- r = strdup(cg_unescape(s));
+ r = strndup(s, x - s);
if (!r)
return -ENOMEM;
@@ -1428,14 +1406,11 @@ int cg_path_get_session(const char *path, char **session) {
assert(path);
assert(session);
- e = path_startswith(path, "/user/");
- if (!e)
- return -ENOENT;
+ /* Skip slices, if there are any */
+ e = skip_slices(path);
- /* Skip the user name */
- e = skip_label(e);
- if (!e)
- return -ENOENT;
+ /* Skip the user name, if there is one */
+ e = skip_user(e);
n = strchrnul(e, '/');
if (n - e < 8)
@@ -1471,9 +1446,8 @@ int cg_path_get_owner_uid(const char *path, uid_t *uid) {
assert(path);
assert(uid);
- e = path_startswith(path, "/user/");
- if (!e)
- return -ENOENT;
+ /* Skip slices, if there are any */
+ e = skip_slices(path);
n = strchrnul(e, '/');
if (n - e < 5)