236 lines
5.4 KiB
C
236 lines
5.4 KiB
C
/*
|
|
* Copyright Red Hat, Inc. 2009
|
|
*
|
|
* Authors: Ivana Hutarova Varekova <varekova@redhat.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of version 2.1 of the GNU Lesser General Public License
|
|
* as published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it would be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
*
|
|
*/
|
|
|
|
#include <libcgroup.h>
|
|
#include <libcgroup-internal.h>
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <pwd.h>
|
|
#include <sys/types.h>
|
|
#include <errno.h>
|
|
#include <unistd.h>
|
|
#include <grp.h>
|
|
#include <getopt.h>
|
|
|
|
#include "tools-common.h"
|
|
|
|
/*
|
|
* Display the usage
|
|
*/
|
|
static void usage(int status, const char *program_name)
|
|
{
|
|
if (status != 0) {
|
|
fprintf(stderr, "Wrong input parameters,"
|
|
" try %s -h' for more information.\n",
|
|
program_name);
|
|
return;
|
|
}
|
|
printf("Usage: %s [-h] [-f mode] [-d mode] [-s mode] "\
|
|
"[-t <tuid>:<tgid>] [-a <agid>:<auid>] "\
|
|
"-g <controllers>:<path> [-g ...]\n", program_name);
|
|
printf("Create control group(s)\n");
|
|
printf(" -a <tuid>:<tgid> Owner of the group and all "\
|
|
"its files\n");
|
|
printf(" -d, --dperm=mode Group directory permissions\n");
|
|
printf(" -f, --fperm=mode Group file permissions\n");
|
|
printf(" -g <controllers>:<path> Control group which should be "\
|
|
"added\n");
|
|
printf(" -h, --help Display this help\n");
|
|
printf(" -s, --tperm=mode Tasks file permissions\n");
|
|
printf(" -t <tuid>:<tgid> Owner of the tasks file\n");
|
|
}
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
int ret = 0;
|
|
int i, j;
|
|
int c;
|
|
|
|
static struct option long_opts[] = {
|
|
{"help", no_argument, NULL, 'h'},
|
|
{"task", required_argument, NULL, 't'},
|
|
{"admin", required_argument, NULL, 'a'},
|
|
{"", required_argument, NULL, 'g'},
|
|
{"dperm", required_argument, NULL, 'd'},
|
|
{"fperm", required_argument, NULL, 'f' },
|
|
{"tperm", required_argument, NULL, 's' },
|
|
{0, 0, 0, 0},
|
|
};
|
|
|
|
uid_t tuid = CGRULE_INVALID, auid = CGRULE_INVALID;
|
|
gid_t tgid = CGRULE_INVALID, agid = CGRULE_INVALID;
|
|
|
|
struct cgroup_group_spec **cgroup_list;
|
|
struct cgroup *cgroup;
|
|
struct cgroup_controller *cgc;
|
|
|
|
/* approximation of max. numbers of groups that will be created */
|
|
int capacity = argc;
|
|
|
|
/* permission variables */
|
|
mode_t dir_mode = NO_PERMS;
|
|
mode_t file_mode = NO_PERMS;
|
|
mode_t tasks_mode = NO_PERMS;
|
|
int dirm_change = 0;
|
|
int filem_change = 0;
|
|
|
|
/* no parametr on input */
|
|
if (argc < 2) {
|
|
usage(1, argv[0]);
|
|
return -1;
|
|
}
|
|
cgroup_list = calloc(capacity, sizeof(struct cgroup_group_spec *));
|
|
if (cgroup_list == NULL) {
|
|
fprintf(stderr, "%s: out of memory\n", argv[0]);
|
|
ret = -1;
|
|
goto err;
|
|
}
|
|
|
|
/* parse arguments */
|
|
while ((c = getopt_long(argc, argv, "a:t:g:hd:f:s:", long_opts, NULL))
|
|
> 0) {
|
|
switch (c) {
|
|
case 'h':
|
|
usage(0, argv[0]);
|
|
ret = 0;
|
|
goto err;
|
|
case 'a':
|
|
/* set admin uid/gid */
|
|
if (parse_uid_gid(optarg, &auid, &agid, argv[0]))
|
|
goto err;
|
|
break;
|
|
case 't':
|
|
/* set task uid/gid */
|
|
if (parse_uid_gid(optarg, &tuid, &tgid, argv[0]))
|
|
goto err;
|
|
break;
|
|
case 'g':
|
|
ret = parse_cgroup_spec(cgroup_list, optarg, capacity);
|
|
if (ret) {
|
|
fprintf(stderr, "%s: "
|
|
"cgroup controller and path"
|
|
"parsing failed (%s)\n",
|
|
argv[0], argv[optind]);
|
|
ret = -1;
|
|
goto err;
|
|
}
|
|
break;
|
|
case 'd':
|
|
dirm_change = 1;
|
|
ret = parse_mode(optarg, &dir_mode, argv[0]);
|
|
if (ret)
|
|
goto err;
|
|
break;
|
|
case 'f':
|
|
filem_change = 1;
|
|
ret = parse_mode(optarg, &file_mode, argv[0]);
|
|
if (ret)
|
|
goto err;
|
|
break;
|
|
case 's':
|
|
filem_change = 1;
|
|
ret = parse_mode(optarg, &tasks_mode, argv[0]);
|
|
if (ret)
|
|
goto err;
|
|
break;
|
|
default:
|
|
usage(1, argv[0]);
|
|
ret = -1;
|
|
goto err;
|
|
}
|
|
}
|
|
|
|
/* no cgroup name */
|
|
if (argv[optind]) {
|
|
fprintf(stderr, "%s: "
|
|
"wrong arguments (%s)\n",
|
|
argv[0], argv[optind]);
|
|
ret = -1;
|
|
goto err;
|
|
}
|
|
|
|
/* initialize libcg */
|
|
ret = cgroup_init();
|
|
if (ret) {
|
|
fprintf(stderr, "%s: "
|
|
"libcgroup initialization failed: %s\n",
|
|
argv[0], cgroup_strerror(ret));
|
|
goto err;
|
|
}
|
|
|
|
/* for each new cgroup */
|
|
for (i = 0; i < capacity; i++) {
|
|
if (!cgroup_list[i])
|
|
break;
|
|
|
|
/* create the new cgroup structure */
|
|
cgroup = cgroup_new_cgroup(cgroup_list[i]->path);
|
|
if (!cgroup) {
|
|
ret = ECGFAIL;
|
|
fprintf(stderr, "%s: can't add new cgroup: %s\n",
|
|
argv[0], cgroup_strerror(ret));
|
|
goto err;
|
|
}
|
|
|
|
/* set uid and gid for the new cgroup based on input options */
|
|
ret = cgroup_set_uid_gid(cgroup, tuid, tgid, auid, agid);
|
|
if (ret)
|
|
goto err;
|
|
|
|
/* add controllers to the new cgroup */
|
|
j = 0;
|
|
while (cgroup_list[i]->controllers[j]) {
|
|
cgc = cgroup_add_controller(cgroup,
|
|
cgroup_list[i]->controllers[j]);
|
|
if (!cgc) {
|
|
ret = ECGINVAL;
|
|
fprintf(stderr, "%s: "
|
|
"controller %s can't be add\n",
|
|
argv[0],
|
|
cgroup_list[i]->controllers[j]);
|
|
cgroup_free(&cgroup);
|
|
goto err;
|
|
}
|
|
j++;
|
|
}
|
|
|
|
/* all variables set so create cgroup */
|
|
if (dirm_change | filem_change)
|
|
cgroup_set_permissions(cgroup, dir_mode, file_mode,
|
|
tasks_mode);
|
|
ret = cgroup_create_cgroup(cgroup, 0);
|
|
if (ret) {
|
|
fprintf(stderr, "%s: "
|
|
"can't create cgroup %s: %s\n",
|
|
argv[0], cgroup->name, cgroup_strerror(ret));
|
|
cgroup_free(&cgroup);
|
|
goto err;
|
|
}
|
|
cgroup_free(&cgroup);
|
|
}
|
|
err:
|
|
if (cgroup_list) {
|
|
for (i = 0; i < capacity; i++) {
|
|
if (cgroup_list[i])
|
|
cgroup_free_group_spec(cgroup_list[i]);
|
|
}
|
|
free(cgroup_list);
|
|
}
|
|
return ret;
|
|
}
|