-int cg_kill(const char *controller, const char *path, int sig, bool ignore_self) {
- bool killed = false, done = false;
- Set *s;
- pid_t my_pid;
+int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d) {
+ char *fs;
+ int r;
+ DIR *d;
+
+ assert(controller);
+ assert(path);
+ assert(_d);
+
+ /* This is not recursive! */
+
+ if ((r = cg_get_path(controller, path, NULL, &fs)) < 0)
+ return r;
+
+ d = opendir(fs);
+ free(fs);
+
+ if (!d)
+ return -errno;
+
+ *_d = d;
+ return 0;
+}
+
+int cg_read_subgroup(DIR *d, char **fn) {
+ struct dirent *de;
+
+ assert(d);
+
+ errno = 0;
+ while ((de = readdir(d))) {
+ char *b;
+
+ if (de->d_type != DT_DIR)
+ continue;
+
+ if (streq(de->d_name, ".") ||
+ streq(de->d_name, ".."))
+ continue;
+
+ if (!(b = strdup(de->d_name)))
+ return -ENOMEM;
+
+ *fn = b;
+ return 1;
+ }
+
+ if (errno)
+ return -errno;
+
+ return 0;
+}
+
+int cg_rmdir(const char *controller, const char *path, bool honour_sticky) {
+ char *p;
+ int r;
+
+ r = cg_get_path(controller, path, NULL, &p);
+ if (r < 0)
+ return r;
+
+ if (honour_sticky) {
+ char *tasks;
+
+ /* If the sticky bit is set don't remove the directory */
+
+ tasks = strappend(p, "/tasks");
+ if (!tasks) {
+ free(p);
+ return -ENOMEM;
+ }
+
+ r = file_is_priv_sticky(tasks);
+ free(tasks);
+
+ if (r > 0) {
+ free(p);
+ return 0;
+ }
+ }
+
+ r = rmdir(p);
+ free(p);
+
+ return (r < 0 && errno != ENOENT) ? -errno : 0;
+}
+
+int cg_kill(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, Set *s) {
+ bool done = false;