From: Jan Safranek Date: Tue, 10 Aug 2010 09:38:14 +0000 (+0530) Subject: Current implementation of cgconfig.conf parser stores parameter values in X-Git-Tag: v0.37.1~53^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=807e7828fd7c2bdb619663fcc6f3b11c8e91a0eb;p=thirdparty%2Flibcgroup.git Current implementation of cgconfig.conf parser stores parameter values in ugly string (name-value pairs separated by ':', name and value themselves separated by ' '), which does not allow users to have ' ' and ':' in parameter values. Both are desired for devices.allow and devices.deny. Let's rewrite the parser to store the parsed name-value pairs in a dictionary, without any limitation on characters allowed in names and values. Signed-off-by: Jan Safranek Signed-off-by: Balbir Singh --- diff --git a/src/config.c b/src/config.c index a29649a9..bce71780 100644 --- a/src/config.c +++ b/src/config.c @@ -121,15 +121,15 @@ int cgroup_config_insert_cgroup(char *cg_name) * entry in the cgroup_table. The index is incremented in * cgroup_config_insert_cgroup */ -int cgroup_config_parse_controller_options(char *controller, char *name_value) +int cgroup_config_parse_controller_options(char *controller, + struct cgroup_dictionary *values) { - char *buffer = NULL; - char *name, *value; + const char *name, *value; struct cgroup_controller *cgc; int error; struct cgroup *config_cgroup = &config_cgroup_table[cgroup_table_index]; - char *nm_pairs, *nv_buf; + void *iter = NULL; cgroup_dbg("Adding controller %s, value %s\n", controller, name_value); cgc = cgroup_add_controller(config_cgroup, controller); @@ -141,56 +141,33 @@ int cgroup_config_parse_controller_options(char *controller, char *name_value) * Did we just specify the controller to create the correct * set of directories, without setting any values? */ - if (!name_value) + if (!values) goto done; - nm_pairs = strtok_r(name_value, ":", &nv_buf); - cgroup_dbg("[1] name value pair being processed is %s\n", nm_pairs); - - name = strtok_r(nm_pairs, " ", &buffer); - - if (!name) - goto parse_error; - - value = strtok_r(NULL, " ", &buffer); - - if (!value) - goto parse_error; - - cgroup_dbg("name is %s, value is %s\n", name, value); - error = cgroup_add_value_string(cgc, name, value); - - if (error) - goto parse_error; - - while ((nm_pairs = strtok_r(NULL, ":", &nv_buf))) { - cgroup_dbg("[2] name value pair being processed is %s\n", - nm_pairs); - name = strtok_r(nm_pairs, " ", &buffer); - + error = cgroup_dictionary_iterator_begin(values, &iter, &name, &value); + while (error == 0) { + cgroup_dbg("[1] name value pair being processed is %s=%s\n", + name, value); if (!name) goto parse_error; - - value = strtok_r(NULL, " ", &buffer); - - if (!value) - goto parse_error; - - cgroup_dbg("name is %s, value is %s\n", name, value); error = cgroup_add_value_string(cgc, name, value); - if (error) goto parse_error; + error = cgroup_dictionary_iterator_next(&iter, &name, &value); } + cgroup_dictionary_iterator_end(&iter); + iter = NULL; + + if (error != ECGEOF) + goto parse_error; done: free(controller); - free(name_value); return 1; parse_error: free(controller); - free(name_value); + cgroup_dictionary_iterator_end(&iter); cgroup_delete_cgroup(config_cgroup, 1); cgroup_table_index--; return 0; diff --git a/src/libcgroup-internal.h b/src/libcgroup-internal.h index 92b9fd8d..801b35e4 100644 --- a/src/libcgroup-internal.h +++ b/src/libcgroup-internal.h @@ -198,7 +198,8 @@ extern __thread char *cg_namespace_table[CG_CONTROLLER_MAX]; * config related API */ int cgroup_config_insert_cgroup(char *cg_name); -int cgroup_config_parse_controller_options(char *controller, char *name_value); +int cgroup_config_parse_controller_options(char *controller, + struct cgroup_dictionary *values); int cgroup_config_group_task_perm(char *perm_type, char *value); int cgroup_config_group_admin_perm(char *perm_type, char *value); int cgroup_config_insert_into_mount_table(char *name, char *mount_point); diff --git a/src/parse.y b/src/parse.y index d4097425..bf68a98e 100644 --- a/src/parse.y +++ b/src/parse.y @@ -43,11 +43,13 @@ int yywrap(void) char *name; char chr; int val; + struct cgroup_dictionary *values; } -%type ID namevalue_conf +%type ID %type mountvalue_conf mount task_namevalue_conf admin_namevalue_conf %type admin_conf task_conf task_or_admin group_conf group start %type namespace namespace_conf +%type namevalue_conf %start start %% @@ -93,6 +95,7 @@ group_conf : ID '{' namevalue_conf '}' { $$ = cgroup_config_parse_controller_options($1, $3); + cgroup_dictionary_free($3); if (!$$) { fprintf(stderr, "parsing failed at line number %d\n", line_no); @@ -103,6 +106,7 @@ group_conf | group_conf ID '{' namevalue_conf '}' { $$ = cgroup_config_parse_controller_options($2, $4); + cgroup_dictionary_free($4); if (!$$) { fprintf(stderr, "parsing failed at line number %d\n", line_no); @@ -125,25 +129,30 @@ group_conf namevalue_conf : ID '=' ID ';' { - $1 = realloc($1, strlen($1) + strlen($3) + 2); - $1 = strncat($1, " ", strlen(" ")); - $$ = strncat($1, $3, strlen($3)); - free($3); + struct cgroup_dictionary *dict; + int ret; + ret = cgroup_dictionary_create(&dict, 0); + if (ret == 0) + ret = cgroup_dictionary_add(dict, $1, $3); + if (ret) { + fprintf(stderr, "parsing failed at line number %d:%s\n", + line_no, cgroup_strerror(ret)); + $$ = NULL; + return ECGCONFIGPARSEFAIL; + } + $$ = dict; } | namevalue_conf ID '=' ID ';' { - int len = 0; - if ($1) - len = strlen($1); - $2 = realloc($2, len + strlen($2) + strlen($4) + 3); - $2 = strncat($2, " ", strlen(" ")); - $$ = strncat($2, $4, strlen($4)); - if ($1) { - $2 = strncat($2, ":", strlen(":")); - $$ = strncat($2, $1, strlen($1)); - free($1); + int ret = 0; + ret = cgroup_dictionary_add($1, $2, $4); + if (ret != 0) { + fprintf(stderr, "parsing failed at line number %d: %s\n", + line_no, cgroup_strerror(ret)); + $$ = NULL; + return ECGCONFIGPARSEFAIL; } - free($4); + $$ = $1; } | {