X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fshared%2Fcgroup-util.c;h=27eee8eacddae52da0f30baab8320f2bd6fb5f3a;hb=db69869f264af2d1afcdd3e573e0e9fdd5bef065;hp=88bc33e3d55c21e6da797a1ec30c77476ecc852e;hpb=674eb68520107d771e3458287025a73387f938c4;p=elogind.git diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c index 88bc33e3d..27eee8eac 100644 --- a/src/shared/cgroup-util.c +++ b/src/shared/cgroup-util.c @@ -480,7 +480,7 @@ static int join_path(const char *controller, const char *path, const char *suffi int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs) { const char *p; - static __thread bool good = false; + static thread_local bool good = false; assert(fs); @@ -1082,43 +1082,63 @@ int cg_get_root_path(char **path) { return 0; } -int cg_pid_get_path_shifted(pid_t pid, char **root, char **cgroup) { - _cleanup_free_ char *cg_root = NULL; - char *cg_process, *p; +int cg_shift_path(const char *cgroup, const char *root, const char **shifted) { + _cleanup_free_ char *rt = NULL; + char *p; int r; - r = cg_get_root_path(&cg_root); + assert(cgroup); + assert(shifted); + + if (!root) { + /* If the root was specified let's use that, otherwise + * let's determine it from PID 1 */ + + r = cg_get_root_path(&rt); + if (r < 0) + return r; + + root = rt; + } + + p = path_startswith(cgroup, root); + if (p) + *shifted = p - 1; + else + *shifted = cgroup; + + return 0; +} + +int cg_pid_get_path_shifted(pid_t pid, const char *root, char **cgroup) { + _cleanup_free_ char *raw = NULL; + const char *c; + int r; + + assert(pid >= 0); + assert(cgroup); + + r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &raw); if (r < 0) return r; - r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cg_process); + r = cg_shift_path(raw, root, &c); if (r < 0) return r; - p = path_startswith(cg_process, cg_root); - if (p) - p--; - else - p = cg_process; - - if (cgroup) { - char* c; + if (c == raw) { + *cgroup = raw; + raw = NULL; + } else { + char *n; - c = strdup(p); - if (!c) { - free(cg_process); + n = strdup(c); + if (!n) return -ENOMEM; - } - *cgroup = c; + *cgroup = n; } - if (root) { - cg_process[p-cg_process] = 0; - *root = cg_process; - } else - free(cg_process); - return 0; } @@ -1183,6 +1203,9 @@ int cg_pid_get_unit(pid_t pid, char **unit) { return cg_path_get_unit(cgroup, unit); } +/** + * Skip session-*.scope, but require it to be there. + */ static const char *skip_session(const char *p) { size_t n; @@ -1191,7 +1214,27 @@ static const char *skip_session(const char *p) { p += strspn(p, "/"); n = strcspn(p, "/"); - if (n <= 12 || memcmp(p, "session-", 8) != 0 || memcmp(p + n - 6, ".scope", 6) != 0) + if (n < strlen("session-x.scope") || memcmp(p, "session-", 8) != 0 || memcmp(p + n - 6, ".scope", 6) != 0) + return NULL; + + p += n; + p += strspn(p, "/"); + + return p; +} + +/** + * Skip user@*.service, but require it to be there. + */ +static const char *skip_user_manager(const char *p) { + size_t n; + + assert(p); + + p += strspn(p, "/"); + + n = strcspn(p, "/"); + if (n < strlen("user@x.service") || memcmp(p, "user@", 5) != 0 || memcmp(p + n - 8, ".service", 8) != 0) return NULL; p += n; @@ -1201,7 +1244,7 @@ static const char *skip_session(const char *p) { } int cg_path_get_user_unit(const char *path, char **unit) { - const char *e; + const char *e, *t; assert(path); assert(unit); @@ -1213,13 +1256,17 @@ int cg_path_get_user_unit(const char *path, char **unit) { /* Skip slices, if there are any */ e = skip_slices(path); - /* Skip the session scope, require that there is one */ - e = skip_session(e); - if (!e) - return -ENOENT; - - /* And skip more slices */ - e = skip_slices(e); + /* Skip the session scope... */ + t = skip_session(e); + if (t) + /* ... and skip more slices if there's one */ + e = skip_slices(t); + else { + /* ... or require a user manager unit to be there */ + e = skip_user_manager(e); + if (!e) + return -ENOENT; + } return cg_path_decode_unit(e, unit); }