int cgroup_read_stats_end(void **handle);
+/**
+ * Read the tasks file to get the list of tasks in a cgroup
+ * @cgroup: Name of the cgroup
+ * @controller: Name of the cgroup subsystem
+ * @handle: Handle to be used in the iteration
+ * @pid: The pid read from the tasks file. Will be filled in by the API
+ */
+int cgroup_get_task_begin(char *cgroup, char *controller, void **handle,
+ pid_t *pid);
+
+/**
+ * Read the next task value
+ * @handle: The handle used for iterating
+ * @pid: The variable where the value will be stored
+ *
+ * return ECGEOF when the iterator finishes getting the list of tasks.
+ */
+int cgroup_get_task_next(void *handle, pid_t *pid);
+int cgroup_get_task_end(void **handle);
/* The wrappers for filling libcg structures */
struct cgroup *cgroup_new_cgroup(const char *name);
*handle = fp;
return ret;
}
+
+int cgroup_get_task_end(void **handle)
+{
+ if (!cgroup_initialized)
+ return ECGROUPNOTINITIALIZED;
+
+ if (!*handle)
+ return ECGINVAL;
+
+ fclose((FILE *) *handle);
+ *handle = NULL;
+
+ return 0;
+}
+
+int cgroup_get_task_next(void *handle, pid_t *pid)
+{
+ int ret;
+
+ if (!cgroup_initialized)
+ return ECGROUPNOTINITIALIZED;
+
+ if (!handle)
+ return ECGINVAL;
+
+ ret = fscanf((FILE *) handle, "%u", pid);
+
+ if (ret != 1) {
+ if (ret == EOF)
+ return ECGEOF;
+ last_errno = errno;
+ return ECGOTHER;
+ }
+
+ return 0;
+}
+
+int cgroup_get_task_begin(char *cgroup, char *controller, void **handle,
+ pid_t *pid)
+{
+ int ret = 0;
+ char path[FILENAME_MAX];
+ char *fullpath = NULL;
+
+ if (!cgroup_initialized)
+ return ECGROUPNOTINITIALIZED;
+
+ if (!cg_build_path(cgroup, path, controller))
+ return ECGOTHER;
+
+ ret = asprintf(&fullpath, "%s/tasks", path);
+
+ if (ret < 0) {
+ last_errno = errno;
+ return ECGOTHER;
+ }
+
+ *handle = (void *) fopen(fullpath, "r");
+ free(fullpath);
+
+ if (!*handle) {
+ last_errno = errno;
+ return ECGOTHER;
+ }
+ ret = cgroup_get_task_next(*handle, pid);
+
+ return ret;
+}