On Fri, Sep 17, 2010 at 3:22 PM, Ivana Hutarova Varekova
<[email protected]> wrote:
> CHANGELOGS:
>        CHANGELOG v3
>        * white/blacklist is cached
>        * incorporate jsafraneks feedback
>
>        CHANGELOG v2
>        * add whitelist which describe the set of variables which can be dealt 
> by
> cgsnapshot without any problem (the values which with which have cgsnapshot
> the problems are there with TODO comment and the reason) without -s option
> the skipped variables are output with the warning text
>        * add the possibility to set the whitelist file
>        * add the possibility to redirect the output
>
>        CHANGELOG v1
>        * more verbose comments
>        * tune the variable names/description/usage in display_controller_data
> function
>        * remove unnecesary .stat exception
>
>    SYNOPSIS:
>    cgsnapshot [-h] [-s] [-w] [--whitelist-file file] [-f output_file] 
> [controller] [...]
>    Generate the configuration file from the current hierarchie(s) of
> control groups
>  -h, --help               Display this help
>  -s, --silent             Ignore all warnings
>  -w, --whitelist          Display only variables from whitelist (default 
> /etc/cgsnapshot_whitelist.conf)
>  --whitelist-file file    Set the whitelist configuration file
>  -f, --file               Redirect the output  to output_file
>    the output have the same format as cgconfig.conf file (the values are
> in commas)
>
>        there is also whitelist, which contains all controllers which are dealt
> without any problem (there are several TODOS like devices and so on) if
>
>    EXAMPLE:
>    $ /home/varekova/bg/libcgroup/20100719/libcg/src/tools/cgsnapshot -n
>    # Configuration file generated by cgsnapshot
>    mount {
>         cpuset = /cgroup/cpuset;
>         cpu = /cgroup/devices;
>         cpuacct = /cgroup/memoryd;
>         memory = /cgroup/memory;
>         devices = /cgroup/devices;
>         freezer = /cgroup/freezer;
>         net_cls = /cgroup/net_cls;
>    }
>
>    group daemons {
>        perm {
>                admin {
>                        uid = root;
>                        gid = root;
>                }
>                task {
>                        uid = root;
>                        gid = root;
>                }
>        }
>        cpuset {
>                cpuset.memory_spread_slab="0";
>                cpuset.memory_spread_page="0";
>                cpuset.memory_migrate="0";
>                cpuset.sched_relax_domain_level="-1";
>                cpuset.sched_load_balance="1";
>                cpuset.mem_hardwall="0";
>                cpuset.mem_exclusive="0";
>                cpuset.cpu_exclusive="0";
>        }
>    }
>
> Signed-off-by: Ivana Hutarova Varekova <[email protected]>
> ---
>
>  src/tools/Makefile.am  |    5
>  src/tools/cgsnapshot.c |  722 
> ++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 726 insertions(+), 1 deletions(-)
>  create mode 100644 src/tools/cgsnapshot.c
>
> diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am
> index f755037..92a0078 100644
> --- a/src/tools/Makefile.am
> +++ b/src/tools/Makefile.am
> @@ -3,7 +3,8 @@ LDADD = $(top_builddir)/src/.libs/libcgroup.la
>
>  if WITH_TOOLS
>
> -bin_PROGRAMS = cgexec cgclassify cgcreate cgset cgget cgdelete lssubsys 
> lscgroup
> +bin_PROGRAMS = cgexec cgclassify cgcreate cgset cgget cgdelete lssubsys\
> +               lscgroup cgsnapshot
>
>  sbin_PROGRAMS = cgconfigparser cgclear
>
> @@ -27,6 +28,8 @@ lssubsys_SOURCES = lssubsys.c
>
>  lscgroup_SOURCES = tools-common.c lscgroup.c
>
> +cgsnapshot_SOURCES = cgsnapshot.c
> +
>  install-exec-hook:
>        chmod u+s $(DESTDIR)$(bindir)/cgexec
>
> diff --git a/src/tools/cgsnapshot.c b/src/tools/cgsnapshot.c
> new file mode 100644
> index 0000000..9c60126
> --- /dev/null
> +++ b/src/tools/cgsnapshot.c
> @@ -0,0 +1,722 @@
> +/* " Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
> + * " Written by Ivana Hutarova Varekova <[email protected]>
> + *
> + * 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 <stdio.h>
> +#include <unistd.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <getopt.h>
> +#include <errno.h>
> +
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <libcgroup.h>
> +#include <libcgroup-internal.h>
> +#include <pwd.h>
> +#include <grp.h>
> +
> +enum flag{
> +    FL_LIST =          1,
> +    FL_SILENT =                2,  /* do-not show any warning/error output */
> +    FL_WHITELIST =     4,  /* use the whitelist to parse the variables */
> +    FL_OUTPUT =                8,  /* output should be redirect to the given 
> file */
> +};
> +
> +#define WHITELIST_CONF         "/etc/cgsnapshot_whitelist.conf"
> +
> +struct listt {

A better name please. listt does not tell us anything. possibly, you
can rename it as blacklist_entry ? or something similar. But listt is
too generic

> +       char name[FILENAME_MAX];        /* variable name */
> +       int val;                        /* whitelisted/blacklisted */
> +       struct listt *next;             /* pointer to the next record */
> +};
> +
> +struct listt *list;
> +
> +/* return values for is_on_list function */
> +#define WHITELISTED 0
> +#define BLACKLISTED 1
> +#define NOT_FOUND 2
> +
> +typedef char cont_name_t[FILENAME_MAX];
> +
> +int flags;
> +FILE *of;
> +
> +/*
> + * 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);
> +       } else {
> +               fprintf(stdout, "Usage: %s [-h] [-s] [-w] "\
> +                       "[--whitelist-file file] [-f output_file] "\
> +                       "[controller] [...]\n", program_name);
> +               fprintf(stdout, "Generate the configuration file from "\
> +                       "the given controllers of control groups\n");
> +               fprintf(stdout, "  -h, --help            Display this 
> help\n");
> +               fprintf(stdout, "  -s, --silent          Ignore all "\
> +                       "warnings\n");
> +               fprintf(stdout, "  -w, --whitelist       Display only "\
> +                       "variables from whitelist (default %s)\n",
> +                       WHITELIST_CONF);
> +               fprintf(stdout, "  --whitelist-file file Set the whitelist"\
> +                       " configuration file\n");
> +               fprintf(stdout, "  -f, --file            Redirect the output"\
> +                       " to output_file\n");
> +       }
> +}
> +
> +/* cache values from whitelist file to the list structure */
> +
> +int load_whitelist(char *filename)
> +{
> +       FILE *fw;
> +       int ret = 0;
> +       char buf[FILENAME_MAX];
> +
> +       char  *aux;
> +       struct listt *start = NULL;
> +       struct listt *end = NULL;
> +       struct listt *new;
> +
> +       fw = fopen(filename, "r");
> +       if (fw == NULL) {
> +               if ((flags &  FL_SILENT) == 0) {
> +                       fprintf(stderr, "WARNING: Failed to open file %s: 
> %s\n",
> +                               filename, strerror(errno));
> +               }
> +               return ret;
> +       }
> +
> +       /* go through the all confuguration file and search the line */
> +       while (fgets(buf, FILENAME_MAX, fw) != NULL) {
> +               aux = strchr(buf, '=');
> +
> +               /* no "=", the line should be skipped */
> +               if (aux == NULL)
> +                       continue;
> +               aux[0] = ' ';
> +
> +               while ((aux[0] == ' ') ||  (aux[0] == '\t'))
> +                       aux++;
> +
> +               /* the line is "name=Y" or "name=N" */
> +               if ((aux[0] == 'Y') || (aux[0] == 'y') ||
> +                       (aux[0] == 'N') || (aux[0] == 'n')) {
> +                       new = (struct listt *)malloc(sizeof(struct listt));
> +
> +                       /* whitelisted/blacklisted */
> +                       if ((aux[0] == 'Y') || (aux[0] == 'y'))
> +                               new->val = WHITELISTED;
> +                       else
> +                               new->val = BLACKLISTED;
> +
> +                       /* find the end of the word */
> +                       aux = strchr(buf, ' ');
> +                       aux[0] = '\0';
> +                       strcpy(new->name, buf);
> +
> +                       new->next = NULL;
> +
> +                       /* update the variables list */
> +                       if (start == NULL) {
> +                               start = new;
> +                               end = new;
> +                       } else {
> +                               end->next = new;
> +                               end = new;
> +                       }
> +               }
> +       }
> +
> +
> +       fclose(fw);
> +       list = start;
> +       return 0;
> +}
> +

As we discussed on IRC, the whitelist is just not maintainable. Let us
just work with a blacklist, and then merge it in.

> +/* free list structure */
> +void free_whitelist()
> +{
> +       struct listt *now;
> +       struct listt *next;
> +
> +       now = list;
> +       while (now != NULL) {
> +               next = now->next;
> +               free(now);
> +               now = next;
> +       }
> +       return;
> +}
> +
> +/* Test whether the variable is on the whitelist
> + * whitelist file name is in wf_name variable
> + * if the line is "name=Y" or "name=N"
> + * return values are:
> + * WHITELISTED ... name=Y was found
> + * BLACKLISTED ... name=N was found
> + * NOT_FOUND ... no record was found
> + */
> +int is_on_list(char *name)
> +{
> +       struct listt *record;
> +
> +       record = list;
> +       /* go through the list of all values */
> +       while (record != NULL) {
> +               /* if the variable name is found */
> +               if (strcmp(record->name, name) == 0) {
> +                       /* return its value */
> +                       return record->val;
> +               }
> +               record = record->next;
> +       }
> +
> +       /* the variable was not found */
> +       return NOT_FOUND;
> +
> +}
> +
> +/* Display permissions record for the given group
> + * defined by path
> + */
> +static int display_permissions(char *path,
> +               const char *program_name)
> +{
> +       int ret;
> +       struct stat sb;
> +       struct passwd *pw;
> +       struct group *gr;
> +       char tasks_path[FILENAME_MAX];
> +
> +       /* print the header */
> +       fprintf(of, "\tperm {\n");
> +
> +       /* admin permissions record */
> +       /* get the directory statistic */
> +       ret = stat(path, &sb);
> +       if (ret) {
> +               fprintf(stderr, "ERROR: can't read statistics about %s\n",
> +                       path);
> +               return -1;
> +       }
> +
> +       /* find out the user and group name */
> +       pw = getpwuid(sb.st_uid);
> +       if (pw == NULL) {
> +               fprintf(stderr, "ERROR: can't get %d user name\n", sb.st_uid);
> +               return -1;
> +       }
> +
> +       gr = getgrgid(sb.st_gid);
> +       if (gr == NULL) {
> +               fprintf(stderr, "ERROR: can't get %d group name\n", 
> sb.st_gid);
> +               return -1;
> +       }
> +
> +       /* print the admin record */
> +       fprintf(of, "\t\tadmin {\n"\
> +               "\t\t\tuid = %s;\n"\
> +               "\t\t\tgid = %s;\n"\
> +               "\t\t}\n", pw->pw_name, gr->gr_name);
> +
> +       /* tasks permissions record */
> +       /* get tasks file statistic */
> +       strncpy(tasks_path, path, FILENAME_MAX);
> +       tasks_path[FILENAME_MAX-1] = '\0';
> +       strncat(tasks_path, "/tasks", FILENAME_MAX);
> +       tasks_path[FILENAME_MAX-1] = '\0';
> +
> +       ret = stat(tasks_path, &sb);
> +       if (ret) {
> +               fprintf(stderr, "ERROR: can't read statistics about %s\n",
> +                       tasks_path);
> +               return -1;
> +       }
> +
> +       /* find out the user and group name */
> +       pw = getpwuid(sb.st_uid);
> +       if (pw == NULL) {
> +               fprintf(stderr, "ERROR: can't get %d user name\n", sb.st_uid);
> +               return -1;
> +       }
> +
> +       gr = getgrgid(sb.st_gid);
> +       if (gr == NULL) {
> +               fprintf(stderr, "ERROR: can't get %d group name\n", 
> sb.st_gid);
> +               return -1;
> +       }
> +
> +       /* print the task record */
> +       fprintf(of, "\t\ttask {\n"\
> +               "\t\t\tuid = %s;\n"\
> +               "\t\t\tgid = %s;\n"\
> +               "\t\t}\n", pw->pw_name, gr->gr_name);
> +
> +       fprintf(of, "\t}\n");
> +
> +       return 0;
> +}
> +
> +/* Displey the control group record:
> + * header
> + *   permission record
> + *   controllers records
> + * tail
> + */
> +
> +static int display_cgroup_data(struct cgroup *group,
> +               char controller[CG_CONTROLLER_MAX][FILENAME_MAX],
> +               char *path, int first,
> +               const char *program_name)
> +{
> +       int i = 0, j, k = 0;
> +       int nr_var = 0;
> +       char *name;
> +       struct cgroup_controller *group_controller = NULL;
> +       char *value = NULL;
> +       int ret = 0;
> +       char group_path[FILENAME_MAX];  /* path to the given group */
> +       /* path to the variable in root group */
> +       char root_var_path[FILENAME_MAX];
> +       struct stat sb;
> +
> +       /* print the  group definition header */
> +       fprintf(of, "group %s {\n", group->name);
> +
> +       /* create the full path to the given group */
> +       strncpy(group_path, path, FILENAME_MAX);
> +       group_path[FILENAME_MAX-1] = '\0';
> +       strncat(group_path, "/", FILENAME_MAX);
> +       group_path[FILENAME_MAX-1] = '\0';
> +       strncat(group_path, group->name, FILENAME_MAX);
> +       group_path[FILENAME_MAX-1] = '\0';
> +
> +       /* display the permission tags */
> +       ret = display_permissions(group_path, program_name);
> +       if (ret)
> +               return ret;
> +
> +       /* for all wanted controllers display controllers tag */
> +       while (controller[i][0] != '\0') {
> +
> +               group_controller = cgroup_get_controller(group, 
> controller[i]);
> +               if (group_controller == NULL) {
> +                       printf("cannot find controller "\
> +                               "'%s' in group '%s'\n",
> +                               controller[i], group->name);
> +                       ret = -1;
> +                       continue;
> +               }
> +
> +               /* print the controller header */
> +               fprintf(of, "\t%s {\n", controller[i]);
> +               i++;
> +               nr_var = cgroup_get_value_name_count(group_controller);
> +
> +               for (j = 0; j < nr_var; j++) {
> +                       name = cgroup_get_value_name(group_controller, j);
> +
> +                       /* test whether the variable file is writable */
> +
> +                       /* find the path to the equal variable in
> +                        * root control group
> +                        */
> +                       strncpy(root_var_path, path, FILENAME_MAX);
> +                       root_var_path[FILENAME_MAX-1] = '\0';
> +                       strncat(root_var_path, "/", FILENAME_MAX);
> +                       root_var_path[FILENAME_MAX-1] = '\0';
> +                       strncat(root_var_path, name, FILENAME_MAX);
> +                       root_var_path[FILENAME_MAX-1] = '\0';
> +
> +                       /* test whether the  write permissions */
> +                       ret = stat(root_var_path, &sb);
> +                       /* freezer.state is not in root group so ret != 0,
> +                        * but it should be listed
> +                        */
> +                       if ((ret == 0) && ((sb.st_mode & S_IWUSR) == 0)) {
> +                               /* variable is not writable */
> +                               continue;
> +                       }
> +
> +                       /* if whitelist option is used display only
> +                        * the variables which are listed on
> +                        */
> +
> +                       if (flags & FL_WHITELIST) {
> +                               k = is_on_list(name);
> +                               /* the warning message is output if "=n" 
> record
> +                                * was found, and silent flag is not set.
> +                                * Only the first occurance is displayed.
> +                                */
> +                               if (((flags &  FL_SILENT) == 0) &&
> +                                       (k == BLACKLISTED) && (first)) {
> +                                       fprintf(stderr, "WARNING: Skipping "\
> +                                               "blacklisted parameter %s",
> +                                               name);
> +                               }
> +                               /* the error message is output if no record 
> was
> +                                * found, and silent flag is not set.
> +                                * Only the first occurance is displayed.
> +                                */
> +                               if (((flags &  FL_SILENT) == 0) &&
> +                                       (k == NOT_FOUND) && (first)) {
> +                                       fprintf(stderr, "ERROR: Skipping "\
> +                                               "unknown variable %s\n", 
> name);
> +                               }
> +                               if ((k == BLACKLISTED) || (k == NOT_FOUND))
> +                                       continue;
> +                       }
> +
> +                       if (name != NULL) {
> +                               ret = 
> cgroup_get_value_string(group_controller,
> +                                       name, &value);
> +
> +                               /* variable can not be read */
> +                               if (ret != 0) {
> +                                       ret = 0;
> +                                       fprintf(stderr, "ERROR: Value of "\
> +                                               "variable %s can be read\n",
> +                                               name);
> +                                       goto err;
> +                               }
> +                               fprintf(of, "\t\t%s=\"%s\";\n", name, value);
> +                       }
> +               }
> +               fprintf(of, "\t}\n");
> +       }
> +
> +       /* tail of the record */
> +       fprintf(of, "}\n\n");
> +
> +err:
> +       return ret;
> +}
> +
> +/*
> + * creates the record about the hierarchie which contains
> + * "controller" subsystem
> + */
> +static int display_controller_data(
> +               char controller[CG_CONTROLLER_MAX][FILENAME_MAX],
> +               const char *program_name)
> +{
> +       int ret;
> +       void *handle;
> +       int first = 1;
> +
> +       struct cgroup_file_info info;
> +       int lvl;
> +
> +       int prefix_len;
> +       char cgroup_name[FILENAME_MAX];
> +       char *end;
> +
> +       struct cgroup *group = NULL;
> +       char cgroup_path[FILENAME_MAX];
> +
> +       /* start to parse the structure for the first controller -
> +          controller[0] attached to hierarchie */
> +       ret = cgroup_walk_tree_begin(controller[0], "/", 0,
> +               &handle, &info, &lvl);
> +       if (ret != 0)
> +               return ret;
> +
> +       prefix_len = strlen(info.full_path);
> +       /* go through all files and directories */
> +       while ((ret = cgroup_walk_tree_next(0, &handle, &info, lvl)) == 0) {
> +               /* some group starts here */
> +               if (info.type == CGROUP_FILE_TYPE_DIR) {
> +                       /* parse the group name from full_path*/
> +                       strncpy(cgroup_name, &info.full_path[prefix_len],
> +                               FILENAME_MAX);
> +                       cgroup_name[FILENAME_MAX-1] = '\0';
> +
> +                       /* find the path to this cgroup */
> +                       strncpy(cgroup_path, info.full_path, FILENAME_MAX-1);
> +                       cgroup_path[FILENAME_MAX-1] = '\0';
> +                       end = strrchr(cgroup_path, '/');
> +                       if (end != NULL)
> +                               end[0] = '\0';
> +
> +                       /* start to grab data about the new group */
> +                       group = cgroup_new_cgroup(cgroup_name);
> +                       if (group == NULL) {
> +                               printf("cannot create group '%s'\n",
> +                                       cgroup_name);
> +                               return -1;
> +                       }
> +
> +                       ret = cgroup_get_cgroup(group);
> +                       if (ret != 0) {
> +                               printf("cannot read group '%s': %s\n",
> +                               cgroup_name, cgroup_strerror(ret));
> +                       }
> +
> +                       display_cgroup_data(group, controller, cgroup_path,
> +                               first, program_name);
> +                       first = 0;
> +               }
> +       }
> +
> +       /* TODO free the structure */
> +

cgroup_free_cgroup(&group) ?

> +       cgroup_walk_tree_end(&handle);
> +       if (ret == ECGEOF)
> +               ret = 0;
> +
> +       return ret;
> +
> +}
> +
> +static int is_ctlr_on_list(char controllers[CG_CONTROLLER_MAX][FILENAME_MAX],
> +                       cont_name_t wanted_conts[FILENAME_MAX])
> +{
> +       int i = 0;
> +       int j = 0;
> +
> +       while (controllers[i][0] != '\0') {
> +               while (wanted_conts[j][0] != '\0') {
> +                       if (strcmp(controllers[i], wanted_conts[j]) == 0)
> +                               return 1;
> +                       j++;
> +               }
> +               j = 0;
> +               i++;
> +       }
> +
> +       return 0;
> +}
> +
> +
> +/* print data about input cont_name controller */
> +static int parse_controllers(cont_name_t cont_names[CG_CONTROLLER_MAX],
> +       const char *program_name)
> +{
> +       int ret = 0;
> +       void *handle;
> +       char path[FILENAME_MAX];
> +       struct cgroup_mount_point controller;
> +
> +       char controllers[CG_CONTROLLER_MAX][FILENAME_MAX];
> +       int max = 0;
> +
> +       path[0] = '\0';
> +
> +       ret = cgroup_get_controller_begin(&handle, &controller);
> +
> +       /* go through the list of controllers/mount point pairs */
> +       while (ret == 0) {
> +               if (strcmp(path, controller.path) == 0) {
> +                       /* if it is still the same mount point */
> +                       if (max < CG_CONTROLLER_MAX) {
> +                               strncpy(controllers[max],
> +                                       controller.name, FILENAME_MAX);
> +                               (controllers[max])[FILENAME_MAX-1] = '\0';
> +                               max++;
> +                       }
> +               } else {
> +
> +                       /* we got new mount point, print it if needed */
> +                       if ((!(flags & FL_LIST) ||
> +                               (is_ctlr_on_list(controllers, cont_names)))
> +                               && (max != 0)) {
> +                               (controllers[max])[0] = '\0';
> +                               ret = display_controller_data(
> +                                       controllers, program_name);
> +                       }
> +
> +                       strncpy(controllers[0], controller.name, 
> FILENAME_MAX);
> +                       (controllers[0])[FILENAME_MAX-1] = '\0';
> +
> +                       strncpy(path, controller.path, FILENAME_MAX);
> +                       path[FILENAME_MAX-1] = '\0';
> +                       max = 1;
> +               }
> +
> +               /* the actual controller should not be printed */
> +               ret = cgroup_get_controller_next(&handle, &controller);
> +       }
> +
> +       if (max != 0)
> +               ret = display_controller_data(
> +                       controllers, program_name);
> +
> +       cgroup_get_controller_end(&handle);
> +       if (ret != ECGEOF)
> +               return ret;
> +       return 0;
> +}
> +
> +/* print data about input mount points */
> +/* TODO only wanted ones */
> +static int parse_mountpoints(cont_name_t cont_names[CG_CONTROLLER_MAX],
> +       const char *program_name)
> +{
> +       int ret;
> +       void *handle;
> +       struct controller_data info;
> +       char *mount_point;
> +
> +       /* start mount section */
> +       fprintf(of, "mount {\n");
> +
> +       /* go through the controller list */
> +       ret = cgroup_get_all_controller_begin(&handle, &info);
> +       while (ret == 0) {
> +
> +               /* the controller attached to some hierarchy */
> +               if  (info.hierarchy != 0) {
> +                       ret = cgroup_get_subsys_mount_point(info.name,
> +                               &mount_point);
> +                       if (ret != 0) {
> +                               /* the controller is not mounted */
> +                               if ((flags &  FL_SILENT) == 0) {
> +                                       fprintf(stderr, "ERROR: %s hierarchy 
> "\
> +                                               "not mounted\n", info.name);
> +                               }
> +                       } else
> +                               fprintf(of, "\t%s = %s;\n",
> +                                       info.name, mount_point);
> +               }
> +
> +               /* next controller */
> +               ret = cgroup_get_all_controller_next(&handle, &info);
> +       }
> +       if (ret != ECGEOF) {
> +               if ((flags &  FL_SILENT) != 0) {
> +                       fprintf(stderr,
> +                               "E: in get next controller %s\n",
> +                               cgroup_strerror(ret));
> +                       return ret;
> +               }
> +       }
> +
> +       ret |= cgroup_get_all_controller_end(&handle);
> +
> +       /* finish mount section */
> +       fprintf(of, "}\n\n");
> +       return ret;
> +}
> +
> +int main(int argc, char *argv[])
> +{
> +       int ret = 0;
> +       int c;
> +
> +       int i;
> +       int c_number = 0;
> +       cont_name_t wanted_cont[CG_CONTROLLER_MAX];
> +
> +       char wf_name[FILENAME_MAX];  /* whitelist file name */
> +
> +
> +       static struct option long_opts[] = {
> +               {"help", no_argument, NULL, 'h'},
> +               {"no-error" , no_argument, NULL, 'n'},
> +               {"whitelist", no_argument, NULL, 'w'},
> +               {"whitelist-file", required_argument, NULL, CHAR_MAX + 1},
> +               {"file", required_argument, NULL, 'f'},
> +               {0, 0, 0, 0}
> +       };
> +
> +       wf_name[0] = '\0';
> +
> +       for (i = 0; i < CG_CONTROLLER_MAX; i++)
> +               wanted_cont[i][0] = '\0';
> +       flags = 0;
> +
> +       /* parse arguments */
> +       while ((c = getopt_long(argc, argv, "shwf:", long_opts, NULL)) > 0) {
> +               switch (c) {
> +               case 'h':
> +                       usage(0, argv[0]);
> +                       return 0;
> +               case 's':
> +                       flags |= FL_SILENT;
> +                       break;
> +               case CHAR_MAX + 1:
> +                       flags |= FL_WHITELIST;
> +                       strncpy(wf_name, optarg, FILENAME_MAX);
> +                       break;
> +               case 'w':
> +                       flags |= FL_WHITELIST;
> +                       if (wf_name[0] == '\0')
> +                               strncpy(wf_name, WHITELIST_CONF, 
> FILENAME_MAX);
> +                       break;
> +               case 'f':
> +                       flags |= FL_OUTPUT;
> +                       of = fopen(optarg, "w");
> +                       if (of == NULL) {
> +                               fprintf(stderr, "%s: Failed to open file 
> %s\n",
> +                                       argv[0], optarg);
> +                               return ECGOTHER;
> +                       }
> +                       break;
> +               default:
> +                       usage(1, argv[0]);
> +                       return -1;
> +               }
> +       }
> +
> +       /* read the list of controllers */
> +       while (optind < argc) {
> +               flags |= FL_LIST;
> +               strncpy(wanted_cont[c_number], argv[optind], FILENAME_MAX);
> +               (wanted_cont[c_number])[FILENAME_MAX-1] = '\0';
> +               c_number++;
> +               optind++;
> +               if (optind == CG_CONTROLLER_MAX-1) {
> +                       fprintf(stderr, "too many parameters\n");
> +                       break;
> +               }
> +       }
> +
> +       if ((flags & FL_OUTPUT) == 0)
> +               of = stdout;
> +
> +       if ((flags & FL_WHITELIST) != 0) {
> +               ret = load_whitelist(wf_name);
> +               if (ret)
> +                       return ret;
> +       }
> +
> +       /* print the header */
> +       fprintf(of, "# Configuration file generated by cgsnapshot\n");
> +
> +       /* initialize libcgroup */
> +       ret = cgroup_init();
> +
> +       if (ret) {
> +               /* empty configuration file */
> +               return ret;
> +       }
> +
> +       /* print mount points section */
> +       ret = parse_mountpoints(wanted_cont, argv[0]);
> +
> +       /* print hierarchies section */
> +       ret = parse_controllers(wanted_cont, argv[0]);
> +
> +       if (flags & FL_WHITELIST)
> +               free_whitelist();
> +
> +       if (of != stdout)
> +               fclose(of);
> +
> +       return ret;
> +}
>

OK, the patch is fine. I am though wondering if it is possible to
split this patch up into smaller pieces.

Dhaval

------------------------------------------------------------------------------
Start uncovering the many advantages of virtual appliances
and start using them to simplify application deployment and
accelerate your shift to cloud computing.
http://p.sf.net/sfu/novell-sfdev2dev
_______________________________________________
Libcg-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/libcg-devel

Reply via email to