int cgfs_create(const char *controller, const char *cg, uid_t uid, gid_t gid) { size_t len; char *dirnam, *tmpc = find_mounted_controller(controller); if (!tmpc) return -EINVAL; /* basedir / tmpc / cg \0 */ len = strlen(basedir) + strlen(tmpc) + strlen(cg) + 3; dirnam = alloca(len); snprintf(dirnam, len, "%s/%s/%s", basedir,tmpc, cg); if (mkdir(dirnam, 0755) < 0) return -errno; if (uid == 0 && gid == 0) return 0; if (chown(dirnam, uid, gid) < 0) return -errno; chown_all_cgroup_files(dirnam, uid, gid); return 0; }
FILE *open_pids_file(const char *controller, const char *cgroup) { size_t len; char *pathname, *tmpc = find_mounted_controller(controller); if (!tmpc) return NULL; /* basedir / tmpc / cgroup / "cgroup.procs" \0 */ len = strlen(basedir) + strlen(tmpc) + strlen(cgroup) + 4 + strlen("cgroup.procs"); pathname = alloca(len); snprintf(pathname, len, "%s/%s/%s/cgroup.procs", basedir, tmpc, cgroup); return fopen(pathname, "w"); }
bool cgfs_remove(const char *controller, const char *cg) { size_t len; char *dirnam, *tmpc = find_mounted_controller(controller); if (!tmpc) return false; /* basedir / tmpc / cg \0 */ len = strlen(basedir) + strlen(tmpc) + strlen(cg) + 3; dirnam = alloca(len); snprintf(dirnam, len, "%s/%s/%s", basedir,tmpc, cg); return recursive_rmdir(dirnam); }
bool cgfs_get_value(const char *controller, const char *cgroup, const char *file, char **value) { size_t len; char *fnam, *tmpc = find_mounted_controller(controller); if (!tmpc) return false; /* basedir / tmpc / cgroup / file \0 */ len = strlen(basedir) + strlen(tmpc) + strlen(cgroup) + strlen(file) + 4; fnam = alloca(len); snprintf(fnam, len, "%s/%s/%s/%s", basedir, tmpc, cgroup, file); *value = read_file(fnam); return *value != NULL; }
bool cgfs_chmod_file(const char *controller, const char *file, mode_t mode) { size_t len; char *pathname, *tmpc = find_mounted_controller(controller); if (!tmpc) return false; /* basedir / tmpc / file \0 */ len = strlen(basedir) + strlen(tmpc) + strlen(file) + 3; pathname = alloca(len); snprintf(pathname, len, "%s/%s/%s", basedir, tmpc, file); if (chmod(pathname, mode) < 0) return false; return true; }
bool cgfs_create(const char *controller, const char *cg) { size_t len; char *dirnam, *tmpc = find_mounted_controller(controller); if (!tmpc) return false; /* basedir / tmpc / cg \0 */ len = strlen(basedir) + strlen(tmpc) + strlen(cg) + 3; dirnam = alloca(len); snprintf(dirnam, len, "%s/%s/%s", basedir,tmpc, cg); if (mkdir(dirnam, 0755) < 0 && errno != EEXIST) return false; return true; }
bool is_child_cgroup(const char *controller, const char *cgroup, const char *f) { size_t len; char *fnam, *tmpc = find_mounted_controller(controller); int ret; struct stat sb; if (!tmpc) return false; /* basedir / tmpc / cgroup / f \0 */ len = strlen(basedir) + strlen(tmpc) + strlen(cgroup) + strlen(f) + 4; fnam = alloca(len); snprintf(fnam, len, "%s/%s/%s/%s", basedir, tmpc, cgroup, f); ret = stat(fnam, &sb); if (ret < 0 || !S_ISDIR(sb.st_mode)) return false; return true; }
struct cgfs_files *cgfs_get_key(const char *controller, const char *cgroup, const char *file) { size_t len; char *fnam, *tmpc = find_mounted_controller(controller); struct stat sb; struct cgfs_files *newkey; int ret; if (!tmpc) return false; if (file && *file == '/') file++; if (file && index(file, '/')) return NULL; /* basedir / tmpc / cgroup / file \0 */ len = strlen(basedir) + strlen(tmpc) + strlen(cgroup) + 3; if (file) len += strlen(file) + 1; fnam = alloca(len); snprintf(fnam, len, "%s/%s/%s%s%s", basedir, tmpc, cgroup, file ? "/" : "", file ? file : ""); ret = stat(fnam, &sb); if (ret < 0) return NULL; do { newkey = malloc(sizeof(struct cgfs_files)); } while (!newkey); if (file) newkey->name = must_copy_string(file); else if (rindex(cgroup, '/')) newkey->name = must_copy_string(rindex(cgroup, '/')); else newkey->name = must_copy_string(cgroup); newkey->uid = sb.st_uid; newkey->gid = sb.st_gid; newkey->mode = sb.st_mode; return newkey; }
int cgfs_chown_file(const char *controller, const char *file, uid_t uid, gid_t gid) { size_t len; char *pathname, *tmpc = find_mounted_controller(controller); if (!tmpc) return -EINVAL; /* basedir / tmpc / file \0 */ len = strlen(basedir) + strlen(tmpc) + strlen(file) + 3; pathname = alloca(len); snprintf(pathname, len, "%s/%s/%s", basedir, tmpc, file); if (chown(pathname, uid, gid) < 0) return -errno; if (is_dir(pathname)) // like cgmanager did, we want to chown the tasks file as well return chown_tasks_files(pathname, uid, gid); return 0; }
bool cgfs_list_keys(const char *controller, const char *cgroup, struct cgfs_files ***keys) { size_t len; char *dirname, *tmpc = find_mounted_controller(controller); char pathname[MAXPATHLEN]; size_t sz = 0, asz = 0; struct dirent dirent, *direntp; DIR *dir; int ret; *keys = NULL; if (!tmpc) return NULL; /* basedir / tmpc / cgroup \0 */ len = strlen(basedir) + strlen(tmpc) + strlen(cgroup) + 3; dirname = alloca(len); snprintf(dirname, len, "%s/%s/%s", basedir, tmpc, cgroup); dir = opendir(dirname); if (!dir) return false; while (!readdir_r(dir, &dirent, &direntp)) { struct stat mystat; int rc; if (!direntp) break; if (!strcmp(direntp->d_name, ".") || !strcmp(direntp->d_name, "..")) continue; rc = snprintf(pathname, MAXPATHLEN, "%s/%s", dirname, direntp->d_name); if (rc < 0 || rc >= MAXPATHLEN) { fprintf(stderr, "%s: pathname too long under %s\n", __func__, dirname); continue; } ret = lstat(pathname, &mystat); if (ret) { fprintf(stderr, "%s: failed to stat %s: %s\n", __func__, pathname, strerror(errno)); continue; } if (!S_ISREG(mystat.st_mode)) continue; if (sz+2 >= asz) { struct cgfs_files **tmp; asz += BATCH_SIZE; do { tmp = realloc(*keys, asz * sizeof(struct cgfs_files *)); } while (!tmp); *keys = tmp; } (*keys)[sz] = cgfs_get_key(controller, cgroup, direntp->d_name); (*keys)[sz+1] = NULL; if (!(*keys)[sz]) { fprintf(stderr, "%s: Error getting files under %s:%s\n", __func__, controller, cgroup); continue; } sz++; } if (closedir(dir) < 0) { fprintf(stderr, "%s: failed closedir for %s: %s\n", __func__, dirname, strerror(errno)); return false; } return true; }