-int cg_path_decode_unit(const char *cgroup, char **unit){
- char *p, *e, *c, *s, *k;
-
- assert(cgroup);
- assert(unit);
-
- e = strchrnul(cgroup, '/');
- c = strndupa(cgroup, e - cgroup);
- c = cg_unescape(c);
-
- /* Could this be a valid unit name? */
- if (!unit_name_is_valid(c, true))
- return -EINVAL;
-
- if (!unit_name_is_template(c))
- s = strdup(c);
- else {
- if (*e != '/')
- return -EINVAL;
-
- e += strspn(e, "/");
-
- p = strchrnul(e, '/');
- k = strndupa(e, p - e);
- k = cg_unescape(k);
-
- if (!unit_name_is_valid(k, false))
- return -EINVAL;
-
- s = strdup(k);
- }
-
- if (!s)
- return -ENOMEM;
-
- *unit = s;
- return 0;
-}
-
-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;
-
- 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);
-}
-
-_pure_ static const char *skip_label(const char *e) {
- assert(e);
-
- e = strchr(e, '/');
- if (!e)
- return NULL;
-
- e += strspn(e, "/");
- return e;
-}
-
-int cg_path_get_user_unit(const char *path, char **unit) {
- const char *e;
-
- 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 */
-
- e = path_startswith(path, "/user/");
- if (!e)
- return -ENOENT;
-
- /* Skip the user name */
- e = skip_label(e);
- if (!e)
- return -ENOENT;
-
- /* Skip the session ID */
- e = skip_label(e);
- if (!e)
- return -ENOENT;
-
- /* Skip the systemd cgroup */
- e = skip_label(e);
- if (!e)
- return -ENOENT;
-
- 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) {
- const char *e, *n;
- char *s, *r;
-
- assert(path);
- assert(machine);
-
- e = path_startswith(path, "/machine/");
- if (!e)
- return -ENOENT;
-
- n = strchrnul(e, '/');
- if (e == n)
- return -ENOENT;
-
- s = strndupa(e, n - e);
-
- r = strdup(cg_unescape(s));
- if (!r)
- return -ENOMEM;
-
- *machine = r;
- return 0;
-}
-
-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);
-}
-
-int cg_path_get_session(const char *path, char **session) {
- const char *e, *n;
- char *s;
-
- assert(path);
- assert(session);
-
- e = path_startswith(path, "/user/");
- if (!e)
- return -ENOENT;
-
- /* Skip the user name */
- e = skip_label(e);
- if (!e)
- return -ENOENT;
-
- n = strchrnul(e, '/');
- if (n - e < 8)
- return -ENOENT;
- if (memcmp(n - 8, ".session", 8) != 0)
- return -ENOENT;
-
- s = strndup(e, n - e - 8);
- if (!s)
- return -ENOMEM;
-
- *session = s;
- return 0;
-}
-