Commit 46b05658 authored by Radostin Stoyanov's avatar Radostin Stoyanov Committed by Andrei Vagin

config: Refactor configuration file parsing

Split the function parse_config() into smaller parts by introducing
the parse_statement(), and add more descriptive comments to improve
readability. In addition, make sure that the last element of the array
of strings 'configuration' is initialised to NULL, which is necessary
to properly count the number of elements after parsing.
Signed-off-by: 's avatarRadostin Stoyanov <rstoyanov1@gmail.com>
Signed-off-by: 's avatarAndrei Vagin <avagin@gmail.com>
parent 7d7f663b
...@@ -40,70 +40,37 @@ static int count_elements(char **to_count) ...@@ -40,70 +40,37 @@ static int count_elements(char **to_count)
return count; return count;
} }
static char ** parse_config(char *filepath) /* Parse one statement in configuration file */
int parse_statement(int i, char *line, char **configuration)
{ {
#define DEFAULT_CONFIG_SIZE 10 int offset = 0, len = 0;
FILE* configfile = fopen(filepath, "r"); bool was_newline = true;
int config_size = DEFAULT_CONFIG_SIZE; char *tmp_string, *quoted, *quotedptr;
int i = 1, len = 0, offset;
size_t limit = 0;
bool was_newline;
char *tmp_string, *line = NULL, *quoted, *quotedptr;
char **configuration, **tmp_conf;
if (!configfile) {
return NULL;
}
configuration = xmalloc(config_size * sizeof(char *));
if (configuration == NULL) {
fclose(configfile);
exit(1);
}
/*
* Initialize first element, getopt ignores it.
*/
configuration[0] = "criu";
while ((len = getline(&line, &limit, configfile)) != -1) {
offset = 0;
was_newline = true;
if (i >= config_size - 1) {
config_size *= 2;
tmp_conf = xrealloc(configuration, config_size * sizeof(char *));
if (tmp_conf == NULL) {
fclose(configfile);
exit(1);
}
configuration = tmp_conf;
}
while (1) { while (1) {
/* Ignore white-space */
while ((isspace(*(line + offset)) && (*(line + offset) != '\n'))) offset++; while ((isspace(*(line + offset)) && (*(line + offset) != '\n'))) offset++;
/* Read a single word. A word is everything
* that doesn't contain white-space characters. */
if (sscanf(line + offset, "%m[^ \t\n]s", &configuration[i]) != 1) { if (sscanf(line + offset, "%m[^ \t\n]s", &configuration[i]) != 1) {
configuration[i] = NULL; configuration[i] = NULL;
break; break;
} }
/* Ignore comments - everything between '#' and '\n' */
if (configuration[i][0] == '#') { if (configuration[i][0] == '#') {
if (sscanf(line, "%*[^\n]") != 0) {
pr_err("Error while reading configuration file %s\n", filepath);
fclose(configfile);
exit(1);
}
configuration[i] = NULL; configuration[i] = NULL;
break; break;
} }
if ((configuration[i][0] == '\"') && (strchr(line + offset + 1, '"'))) { if ((configuration[i][0] == '\"') && (strchr(line + offset + 1, '"'))) {
/* /* Handle empty strings which strtok ignores */
* Handle empty strings which strtok ignores
*/
if (!strcmp(configuration[i], "\"\"")) { if (!strcmp(configuration[i], "\"\"")) {
configuration[i] = ""; configuration[i] = "";
offset += strlen("\"\""); offset += strlen("\"\"");
} else if ((configuration[i] = strtok_r(line + offset, "\"", &quotedptr))) { } else if ((configuration[i] = strtok_r(line + offset, "\"", &quotedptr))) {
/* /* Handle escaping of quotes in quoted string */
* Handle escaping of quotes in quoted string
*/
while (configuration[i][strlen(configuration[i]) - 1] == '\\') { while (configuration[i][strlen(configuration[i]) - 1] == '\\') {
offset++; offset++;
len = strlen(configuration[i]); len = strlen(configuration[i]);
...@@ -114,10 +81,9 @@ static char ** parse_config(char *filepath) ...@@ -114,10 +81,9 @@ static char ** parse_config(char *filepath)
} }
quoted = strtok_r(NULL, "\"", &quotedptr); quoted = strtok_r(NULL, "\"", &quotedptr);
tmp_string = xmalloc(len + strlen(quoted) + 1); tmp_string = xmalloc(len + strlen(quoted) + 1);
if (tmp_string == NULL) { if (tmp_string == NULL)
fclose(configfile); return -1;
exit(1);
}
memmove(tmp_string, configuration[i], len); memmove(tmp_string, configuration[i], len);
memmove(tmp_string + len, quoted, strlen(quoted) + 1); memmove(tmp_string + len, quoted, strlen(quoted) + 1);
configuration[i] = tmp_string; configuration[i] = tmp_string;
...@@ -125,24 +91,72 @@ static char ** parse_config(char *filepath) ...@@ -125,24 +91,72 @@ static char ** parse_config(char *filepath)
offset += 2; offset += 2;
} }
} }
offset += strlen(configuration[i]); offset += strlen(configuration[i]);
if (was_newline) { if (was_newline) {
was_newline = false; was_newline = false;
len = strlen(configuration[i]); len = strlen(configuration[i]);
tmp_string = xrealloc(configuration[i], len + strlen("--") + 1); tmp_string = xrealloc(configuration[i], len + strlen("--") + 1);
if (tmp_string == NULL) { if (tmp_string == NULL)
fclose(configfile); return -1;
exit(1);
}
memmove(tmp_string + strlen("--"), tmp_string, len + 1); memmove(tmp_string + strlen("--"), tmp_string, len + 1);
memmove(tmp_string, "--", strlen("--")); memmove(tmp_string, "--", strlen("--"));
configuration[i] = tmp_string; configuration[i] = tmp_string;
} }
i++; i++;
} }
return i;
}
/* Parse a configuration file */
static char ** parse_config(char *filepath)
{
#define DEFAULT_CONFIG_SIZE 10
FILE* configfile = fopen(filepath, "r");
int config_size = DEFAULT_CONFIG_SIZE;
int i = 1;
size_t line_size = 0;
char *line = NULL;
char **configuration;
if (!configfile)
return NULL;
configuration = xmalloc(config_size * sizeof(char *));
if (configuration == NULL) {
fclose(configfile);
exit(1);
}
/*
* Initialize first element, getopt ignores it.
*/
configuration[0] = "criu";
while (getline(&line, &line_size, configfile) != -1) {
/* Extend configuration buffer if necessary */
if (i >= config_size - 1) {
config_size *= 2;
configuration = xrealloc(configuration, config_size * sizeof(char *));
if (configuration == NULL) {
fclose(configfile);
exit(1);
}
}
i = parse_statement(i, line, configuration);
if (i < 0) {
fclose(configfile);
exit(1);
}
free(line); free(line);
line = NULL; line = NULL;
} }
/* Initialize the last element */
configuration[i] = NULL;
free(line); free(line);
fclose(configfile); fclose(configfile);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment