[CRIU] [PATCH] config: Refactor configuration file parsing
Andrei Vagin
avagin at gmail.com
Fri Feb 1 20:51:30 MSK 2019
Accepted, thanks!
On Fri, Jan 25, 2019 at 09:27:27PM +0000, Radostin Stoyanov wrote:
> 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: Radostin Stoyanov <rstoyanov1 at gmail.com>
> ---
> criu/config.c | 164 +++++++++++++++++++++++++++-----------------------
> 1 file changed, 89 insertions(+), 75 deletions(-)
>
> diff --git a/criu/config.c b/criu/config.c
> index b6ecbfb64..1a41b4533 100644
> --- a/criu/config.c
> +++ b/criu/config.c
> @@ -40,20 +40,91 @@ static int count_elements(char **to_count)
> return count;
> }
>
> +/* Parse one statement in configuration file */
> +int parse_statement(int i, char *line, char **configuration)
> +{
> + int offset = 0, len = 0;
> + bool was_newline = true;
> + char *tmp_string, *quoted, *quotedptr;
> +
> + while (1) {
> + /* Ignore white-space */
> + 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) {
> + configuration[i] = NULL;
> + break;
> + }
> +
> + /* Ignore comments - everything between '#' and '\n' */
> + if (configuration[i][0] == '#') {
> + configuration[i] = NULL;
> + break;
> + }
> +
> + if ((configuration[i][0] == '\"') && (strchr(line + offset + 1, '"'))) {
> + /* Handle empty strings which strtok ignores */
> + if (!strcmp(configuration[i], "\"\"")) {
> + configuration[i] = "";
> + offset += strlen("\"\"");
> + } else if ((configuration[i] = strtok_r(line + offset, "\"", "edptr))) {
> + /* Handle escaping of quotes in quoted string */
> + while (configuration[i][strlen(configuration[i]) - 1] == '\\') {
> + offset++;
> + len = strlen(configuration[i]);
> + configuration[i][len - 1] = '"';
> + if (*quotedptr == '"') {
> + quotedptr++;
> + break;
> + }
> + quoted = strtok_r(NULL, "\"", "edptr);
> + tmp_string = xmalloc(len + strlen(quoted) + 1);
> + if (tmp_string == NULL)
> + return -1;
> +
> + memmove(tmp_string, configuration[i], len);
> + memmove(tmp_string + len, quoted, strlen(quoted) + 1);
> + configuration[i] = tmp_string;
> + }
> + offset += 2;
> + }
> + }
> +
> + offset += strlen(configuration[i]);
> +
> + if (was_newline) {
> + was_newline = false;
> + len = strlen(configuration[i]);
> + tmp_string = xrealloc(configuration[i], len + strlen("--") + 1);
> + if (tmp_string == NULL)
> + return -1;
> +
> + memmove(tmp_string + strlen("--"), tmp_string, len + 1);
> + memmove(tmp_string, "--", strlen("--"));
> + configuration[i] = tmp_string;
> + }
> + 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, len = 0, offset;
> - size_t limit = 0;
> - bool was_newline;
> - char *tmp_string, *line = NULL, *quoted, *quotedptr;
> - char **configuration, **tmp_conf;
> + int i = 1;
> + size_t line_size = 0;
> + char *line = NULL;
> + char **configuration;
>
> - if (!configfile) {
> + if (!configfile)
> return NULL;
> - }
> +
> configuration = xmalloc(config_size * sizeof(char *));
> if (configuration == NULL) {
> fclose(configfile);
> @@ -64,85 +135,28 @@ static char ** parse_config(char *filepath)
> */
> configuration[0] = "criu";
>
> - while ((len = getline(&line, &limit, configfile)) != -1) {
> - offset = 0;
> - was_newline = true;
> + while (getline(&line, &line_size, configfile) != -1) {
> + /* Extend configuration buffer if necessary */
> if (i >= config_size - 1) {
> config_size *= 2;
> - tmp_conf = xrealloc(configuration, config_size * sizeof(char *));
> - if (tmp_conf == NULL) {
> + configuration = xrealloc(configuration, config_size * sizeof(char *));
> + if (configuration == NULL) {
> fclose(configfile);
> exit(1);
> }
> - configuration = tmp_conf;
> }
> - while (1) {
> - while ((isspace(*(line + offset)) && (*(line + offset) != '\n'))) offset++;
> -
> - if (sscanf(line + offset, "%m[^ \t\n]s", &configuration[i]) != 1) {
> - configuration[i] = NULL;
> - break;
> - }
>
> - 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;
> - break;
> - }
> - if ((configuration[i][0] == '\"') && (strchr(line + offset + 1, '"'))) {
> - /*
> - * Handle empty strings which strtok ignores
> - */
> - if (!strcmp(configuration[i], "\"\"")) {
> - configuration[i] = "";
> - offset += strlen("\"\"");
> - } else if ((configuration[i] = strtok_r(line + offset, "\"", "edptr))) {
> - /*
> - * Handle escaping of quotes in quoted string
> - */
> - while (configuration[i][strlen(configuration[i]) - 1] == '\\') {
> - offset++;
> - len = strlen(configuration[i]);
> - configuration[i][len - 1] = '"';
> - if (*quotedptr == '"') {
> - quotedptr++;
> - break;
> - }
> - quoted = strtok_r(NULL, "\"", "edptr);
> - tmp_string = xmalloc(len + strlen(quoted) + 1);
> - if (tmp_string == NULL) {
> - fclose(configfile);
> - exit(1);
> - }
> - memmove(tmp_string, configuration[i], len);
> - memmove(tmp_string + len, quoted, strlen(quoted) + 1);
> - configuration[i] = tmp_string;
> - }
> - offset += 2;
> - }
> - }
> - offset += strlen(configuration[i]);
> - if (was_newline) {
> - was_newline = false;
> - len = strlen(configuration[i]);
> - tmp_string = xrealloc(configuration[i], len + strlen("--") + 1);
> - if (tmp_string == NULL) {
> - fclose(configfile);
> - exit(1);
> - }
> - memmove(tmp_string + strlen("--"), tmp_string, len + 1);
> - memmove(tmp_string, "--", strlen("--"));
> - configuration[i] = tmp_string;
> - }
> - i++;
> + i = parse_statement(i, line, configuration);
> + if (i < 0) {
> + fclose(configfile);
> + exit(1);
> }
> +
> free(line);
> line = NULL;
> }
> + /* Initialize the last element */
> + configuration[i] = NULL;
>
> free(line);
> fclose(configfile);
> --
> 2.20.1
>
> _______________________________________________
> CRIU mailing list
> CRIU at openvz.org
> https://lists.openvz.org/mailman/listinfo/criu
More information about the CRIU
mailing list