-int cg_path_decode_unit(const char *cgroup, char **unit){
- char *e, *c, *s;
-
- assert(cgroup);
- assert(unit);
-
- e = strchrnul(cgroup, '/');
- c = strndupa(cgroup, e - cgroup);
- c = cg_unescape(c);
-
- if (!unit_name_is_valid(c, TEMPLATE_INVALID))
- return -EINVAL;
-
- s = strdup(c);
- if (!s)
- return -ENOMEM;
-
- *unit = s;
- return 0;
-}
-
-static const char *skip_slices(const char *p) {
- /* Skips over all slice assignments */
-
- for (;;) {
- size_t n;
-
- 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 = skip_slices(path);
-
- return cg_path_decode_unit(e, unit);
-}
-
-int cg_pid_get_unit(pid_t pid, char **unit) {
- _cleanup_free_ char *cgroup = NULL;
- int r;
-
- assert(unit);
-
- r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
- if (r < 0)
- return r;
-
- 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;
-
- assert(p);
-
- p += strspn(p, "/");
-
- n = strcspn(p, "/");
- 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;
- p += strspn(p, "/");
-
- return p;
-}
-
-int cg_path_get_user_unit(const char *path, char **unit) {
- const char *e, *t;
-
- assert(path);
- assert(unit);
-
- /* 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 session scope or user manager... */
- t = skip_session(e);
- if (!t)
- t = skip_user_manager(e);
- if (!t)
- return -ENOENT;
-
- /* ... and skip more slices if there are any */
- e = skip_slices(t);
-
- return cg_path_decode_unit(e, unit);
-}
-
-int cg_pid_get_user_unit(pid_t pid, char **unit) {
- _cleanup_free_ char *cgroup = NULL;
- int r;
-
- assert(unit);
-
- r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
- if (r < 0)
- return r;
-
- return cg_path_get_user_unit(cgroup, unit);
-}
-
-int cg_path_get_machine_name(const char *path, char **machine) {
- _cleanup_free_ char *u = NULL, *sl = NULL;
- int r;
-
- r = cg_path_get_unit(path, &u);
- if (r < 0)
- return r;
-
- sl = strjoin("/run/systemd/machines/unit:", u, NULL);
- if (!sl)
- return -ENOMEM;
-
- return readlink_malloc(sl, machine);
-}
-
-int cg_pid_get_machine_name(pid_t pid, char **machine) {
- _cleanup_free_ char *cgroup = NULL;
- int r;
-
- assert(machine);
-
- r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
- if (r < 0)
- return r;
-
- return cg_path_get_machine_name(cgroup, machine);
-}
-