#include <sys/param.h>
#include <sys/inotify.h>
#include <sys/mount.h>
+#include <sys/wait.h>
#include <netinet/in.h>
#include <net/if.h>
#include <stdbool.h>
cgm_dbus_disconnect();
return true;
}
+
+static int wait_for_pid(pid_t pid)
+{
+ int status, ret;
+
+again:
+ ret = waitpid(pid, &status, 0);
+ if (ret == -1) {
+ if (errno == EINTR)
+ goto again;
+ return -1;
+ }
+ if (ret != pid)
+ goto again;
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
+ return -1;
+ return 0;
+}
+
+bool cgm_create(const char *controller, const char *cg, uid_t uid, gid_t gid)
+{
+ int32_t e;
+ pid_t pid = fork();
+
+ if (pid) {
+ if (wait_for_pid(pid) != 0)
+ return false;
+ return true;
+ }
+
+ if (setgroups(0, NULL))
+ exit(1);
+ if (setresgid(gid, gid, gid))
+ exit(1);
+ if (setresuid(uid, uid, uid))
+ exit(1);
+
+ if (!cgm_dbus_connect()) {
+ exit(1);
+ }
+
+ if ( cgmanager_create_sync(NULL, cgroup_manager, controller, cg, &e) != 0) {
+ NihError *nerr;
+ nerr = nih_error_get();
+ fprintf(stderr, "call to create failed: %s", nerr->message);
+ nih_free(nerr);
+ cgm_dbus_disconnect();
+ exit(1);
+ }
+
+ cgm_dbus_disconnect();
+ exit(0);
+}
+
+#if 0
+bool cgm_chown(const char *controller, const char *cg, uid_t uid, gid_t gid)
+{
+ if (!cgm_dbus_connect()) {
+ return false;
+ }
+
+ if ( cgmanager_chown_sync(NULL, cgroup_manager, controller, cg, uid, gid) != 0) {
+ NihError *nerr;
+ nerr = nih_error_get();
+ fprintf(stderr, "call to chown failed: %s", nerr->message);
+ nih_free(nerr);
+ cgm_dbus_disconnect();
+ return false;
+ }
+
+ cgm_dbus_disconnect();
+ return true;
+}
+
+bool cgm_remove(const char *controller, const char *cg)
+{
+ int32_t r = 1, e;
+
+ if (!cgm_dbus_connect()) {
+ return false;
+ }
+
+ if ( cgmanager_remove_sync(NULL, cgroup_manager, controller, cg, r, &e) != 0) {
+ NihError *nerr;
+ nerr = nih_error_get();
+ fprintf(stderr, "call to remove failed: %s", nerr->message);
+ nih_free(nerr);
+ cgm_dbus_disconnect();
+ return false;
+ }
+
+ cgm_dbus_disconnect();
+ return true;
+}
+#endif
char *cgm_get_pid_cgroup(pid_t pid, const char *controller);
bool cgm_get_value(const char *controller, const char *cgroup, const char *file,
char **value);
+bool cgm_create(const char *controller, const char *cg, uid_t uid, gid_t gid);
+#if 0
+bool cgm_chown(const char *controller, const char *cg, uid_t uid, gid_t gid);
+bool cgm_remove(const char *controller, const char *cg);
+#endif
bool cgm_escape_cgroup(void);
return 0;
}
- return -EINVAL;
+ return -ENOENT;
}
static int cg_opendir(const char *path, struct fuse_file_info *fi)
return -EINVAL;
}
+int cg_mkdir(const char *path, mode_t mode)
+{
+ struct fuse_context *fc = fuse_get_context();
+ nih_local struct cgm_keys **list = NULL;
+ char *fpath = NULL, *path1;
+ nih_local char * cgdir = NULL;
+ const char *cgroup;
+ nih_local char *controller = NULL;
+
+fprintf(stderr, "XXX cg_mkdir: starting for %s\n", path);
+ if (!fc)
+ return -EIO;
+
+
+ controller = pick_controller_from_path(fc, path);
+ if (!controller)
+ return -EIO;
+
+ cgroup = find_cgroup_in_path(path);
+ if (!cgroup)
+ return -EIO;
+
+ get_cgdir_and_path(cgroup, &cgdir, &fpath);
+ if (!fpath)
+ path1 = "/";
+ else
+ path1 = cgdir;
+
+ if (!fc_may_access(fc, controller, path1, NULL, O_RDWR))
+ return -EPERM;
+
+
+ if (!cgm_create(controller, cgroup, fc->uid, fc->gid))
+ return -EINVAL;
+
+ return 0;
+}
+
/*
* So far I'm not actually using cg_ops and proc_ops, but listing them
* here makes it clearer who is supporting what. Still I prefer to
.readlink = NULL,
.getdir = NULL,
.mknod = NULL,
- .mkdir = NULL,
+ .mkdir = cg_mkdir,
.unlink = NULL,
.rmdir = NULL,
.symlink = NULL,
return 0;
}
+int lxcfs_mkdir(const char *path, mode_t mode)
+{
+ if (strncmp(path, "/cgroup", 7) == 0)
+ return cg_mkdir(path, mode);
+
+ return -EINVAL;
+}
+
const struct fuse_operations lxcfs_ops = {
.getattr = lxcfs_getattr,
.readlink = NULL,
.getdir = NULL,
.mknod = NULL,
- .mkdir = NULL,
+ .mkdir = lxcfs_mkdir,
.unlink = NULL,
.rmdir = NULL,
.symlink = NULL,