+
+ 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;
+}
+
+int cg_pid_get_session(pid_t pid, char **session) {
+ _cleanup_free_ char *cgroup = NULL;
+ int r;
+
+ assert(session);
+
+ r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
+ if (r < 0)
+ return r;
+
+ return cg_path_get_session(cgroup, session);
+}
+
+int cg_path_get_owner_uid(const char *path, uid_t *uid) {
+ const char *e, *n;
+ char *s;
+
+ assert(path);
+ assert(uid);
+
+ e = path_startswith(path, "/user/");
+ if (!e)
+ return -ENOENT;
+
+ n = strchrnul(e, '/');
+ if (n - e < 5)
+ return -ENOENT;
+ if (memcmp(n - 5, ".user", 5) != 0)
+ return -ENOENT;
+
+ s = strndupa(e, n - e - 5);
+ if (!s)
+ return -ENOMEM;
+
+ return parse_uid(s, uid);
+}
+
+int cg_pid_get_owner_uid(pid_t pid, uid_t *uid) {
+ _cleanup_free_ char *cgroup = NULL;
+ int r;
+
+ assert(uid);
+
+ r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
+ if (r < 0)
+ return r;
+
+ return cg_path_get_owner_uid(cgroup, uid);
+}
+
+int cg_controller_from_attr(const char *attr, char **controller) {
+ const char *dot;
+ char *c;
+
+ assert(attr);
+ assert(controller);
+
+ if (!filename_is_safe(attr))
+ return -EINVAL;
+
+ dot = strchr(attr, '.');
+ if (!dot) {
+ *controller = NULL;
+ return 0;