+ if (controller)
+ if (!(t = strndup(spec, e-spec)))
+ return -ENOMEM;
+
+ if (path)
+ if (!(u = strdup(e+1))) {
+ free(t);
+ return -ENOMEM;
+ }
+
+ if (controller)
+ *controller = t;
+
+ if (path)
+ *path = u;
+
+ return 0;
+}
+
+int cg_join_spec(const char *controller, const char *path, char **spec) {
+ assert(controller);
+ assert(path);
+
+ if (!path_is_absolute(path) ||
+ controller[0] == 0 ||
+ strchr(controller, ':') ||
+ strchr(controller, '/'))
+ return -EINVAL;
+
+ if (asprintf(spec, "%s:%s", controller, path) < 0)
+ return -ENOMEM;
+
+ return 0;
+}
+
+int cg_fix_path(const char *path, char **result) {
+ char *t, *c, *p;
+ int r;
+
+ assert(path);
+ assert(result);
+
+ /* First check if it already is a filesystem path */
+ if (path_is_absolute(path) &&
+ path_startswith(path, "/sys/fs/cgroup") &&
+ access(path, F_OK) >= 0) {
+
+ if (!(t = strdup(path)))
+ return -ENOMEM;
+
+ *result = t;
+ return 0;
+ }
+
+ /* Otherwise treat it as cg spec */
+ if ((r = cg_split_spec(path, &c, &p)) < 0)
+ return r;
+
+ r = cg_get_path(c ? c : SYSTEMD_CGROUP_CONTROLLER, p ? p : "/", NULL, result);
+ free(c);
+ free(p);
+
+ return r;