[CRIU] [PATCH 1/2] criu: split configuration parsing into separate file
Mike Rapoport
rppt at linux.vnet.ibm.com
Thu Apr 26 18:52:17 MSK 2018
Signed-off-by: Mike Rapoport <rppt at linux.vnet.ibm.com>
---
criu/Makefile.crtools | 1 +
criu/config.c | 204 +++++++++++++++++++++++++++++++++++++++++++++++++
criu/crtools.c | 182 +------------------------------------------
criu/include/crtools.h | 2 +
4 files changed, 209 insertions(+), 180 deletions(-)
create mode 100644 criu/config.c
diff --git a/criu/Makefile.crtools b/criu/Makefile.crtools
index d93545a..c573695 100644
--- a/criu/Makefile.crtools
+++ b/criu/Makefile.crtools
@@ -86,6 +86,7 @@ obj-y += path.o
obj-y += autofs.o
obj-y += fdstore.o
obj-y += uffd.o
+obj-y += config.o
ifeq ($(VDSO),y)
obj-y += pie-util-vdso.o
diff --git a/criu/config.c b/criu/config.c
new file mode 100644
index 0000000..10630c6
--- /dev/null
+++ b/criu/config.c
@@ -0,0 +1,204 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <limits.h>
+
+#include "log.h"
+#include "crtools.h"
+
+#include "common/xmalloc.h"
+
+extern char **global_conf;
+extern char **user_conf;
+
+#define HELP_PASSED 1
+#define DEFAULT_CONFIGS_FORBIDDEN 2
+
+static int passed_help_or_defaults_forbidden(int argc, char *argv[])
+{
+ /*
+ * Check for --help / -h on commandline before parsing, otherwise
+ * the help message won't be displayed if there is an error in
+ * configuration file syntax. Checks are kept in parser in case of
+ * option being put in the configuration file itself.
+ *
+ * Check also whether default configfiles are forbidden to lower
+ * number of argv iterations, but checks for help have higher priority.
+ */
+ int i, ret = 0;
+ for (i = 0; i < argc; i++) {
+ if ((!strcmp(argv[i], "--help")) || (!strcmp(argv[i], "-h")))
+ return HELP_PASSED;
+ if (!strcmp(argv[i], "--no-default-config"))
+ ret = DEFAULT_CONFIGS_FORBIDDEN;
+ }
+ return ret;
+}
+
+static char * specific_config_passed(char *args[], int argc)
+{
+ int i;
+ for (i = 0; i < argc; i++) {
+ if (!strcmp(args[i], "--config")) {
+ /* getopt takes next string as required argument automatically */
+ return args[i + 1];
+ } else if (strstr(args[i], "--config=") != NULL) {
+ return args[i] + strlen("--config=");
+ }
+ }
+ return NULL;
+}
+
+static int count_elements(char **to_count)
+{
+ int count = 0;
+ if (to_count != NULL)
+ while (to_count[count] != NULL)
+ count++;
+ return count;
+}
+
+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;
+
+ 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 (sscanf(line + offset, "%m[^ \t\n]s", &configuration[i]) == 1) {
+ 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++;
+ while ((isspace(*(line + offset)) && (*(line + offset) != '\n'))) offset++;
+ }
+ line = NULL;
+ }
+
+ fclose(configfile);
+ return configuration;
+}
+
+static void init_configuration(int argc, char *argv[], int defaults_forbidden)
+{
+ char *specific_conf = specific_config_passed(argv, argc);
+ char local_filepath[PATH_MAX + 1];
+ char *home_dir = getenv("HOME");
+
+ if ((specific_conf == NULL) && (!defaults_forbidden)) {
+ global_conf = parse_config(GLOBAL_CONFIG_DIR DEFAULT_CONFIG_FILENAME);
+ if (!home_dir) {
+ pr_info("Unable to get $HOME directory, local configuration file will not be used.");
+ } else {
+ snprintf(local_filepath, PATH_MAX, "%s/%s%s",
+ home_dir, USER_CONFIG_DIR, DEFAULT_CONFIG_FILENAME);
+ user_conf = parse_config(local_filepath);
+ }
+ } else if (specific_conf != NULL) {
+ global_conf = parse_config(specific_conf);
+ if (global_conf == NULL) {
+ pr_err("Can't access configuration file %s.\n", specific_conf);
+ exit(1);
+ }
+ }
+}
+
+void init_config(int argc, char **argv, int *first_count, int *second_count)
+{
+ int help_or_configs;
+ bool usage_error;
+
+ help_or_configs = passed_help_or_defaults_forbidden(argc, argv);
+ if (help_or_configs == 1) {
+ usage_error = false;
+ printf("goto usage: %d\n", usage_error);
+ return;
+ }
+
+ init_configuration(argc, argv, (help_or_configs == DEFAULT_CONFIGS_FORBIDDEN));
+ if (global_conf != NULL)
+ *first_count = count_elements(global_conf);
+ if (user_conf != NULL)
+ *second_count = count_elements(user_conf);
+}
diff --git a/criu/crtools.c b/criu/crtools.c
index 9ba5832..0f55edb 100644
--- a/criu/crtools.c
+++ b/criu/crtools.c
@@ -226,177 +226,6 @@ static void rlimit_unlimit_nofile_self(void)
pr_debug("rlimit: RLIMIT_NOFILE unlimited for self\n");
}
-#define HELP_PASSED 1
-#define DEFAULT_CONFIGS_FORBIDDEN 2
-int passed_help_or_defaults_forbidden(int argc, char *argv[])
-{
- /*
- * Check for --help / -h on commandline before parsing, otherwise
- * the help message won't be displayed if there is an error in
- * configuration file syntax. Checks are kept in parser in case of
- * option being put in the configuration file itself.
- *
- * Check also whether default configfiles are forbidden to lower
- * number of argv iterations, but checks for help have higher priority.
- */
- int i, ret = 0;
- for (i = 0; i < argc; i++) {
- if ((!strcmp(argv[i], "--help")) || (!strcmp(argv[i], "-h")))
- return HELP_PASSED;
- if (!strcmp(argv[i], "--no-default-config"))
- ret = DEFAULT_CONFIGS_FORBIDDEN;
- }
- return ret;
-}
-
-char * specific_config_passed(char *args[], int argc)
-{
- int i;
- for (i = 0; i < argc; i++) {
- if (!strcmp(args[i], "--config")) {
- /* getopt takes next string as required argument automatically */
- return args[i + 1];
- } else if (strstr(args[i], "--config=") != NULL) {
- return args[i] + strlen("--config=");
- }
- }
- return NULL;
-}
-
-static int count_elements(char **to_count)
-{
- int count = 0;
- if (to_count != NULL)
- while (to_count[count] != NULL)
- count++;
- return count;
-}
-
-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;
-
- 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 (sscanf(line + offset, "%m[^ \t\n]s", &configuration[i]) == 1) {
- 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++;
- while ((isspace(*(line + offset)) && (*(line + offset) != '\n'))) offset++;
- }
- line = NULL;
- }
-
- fclose(configfile);
- return configuration;
-}
-
-static void init_configuration(int argc, char *argv[], int defaults_forbidden)
-{
- char *specific_conf = specific_config_passed(argv, argc);
- char local_filepath[PATH_MAX + 1];
- char *home_dir = getenv("HOME");
-
- if ((specific_conf == NULL) && (!defaults_forbidden)) {
- global_conf = parse_config(GLOBAL_CONFIG_DIR DEFAULT_CONFIG_FILENAME);
- if (!home_dir) {
- pr_info("Unable to get $HOME directory, local configuration file will not be used.");
- } else {
- snprintf(local_filepath, PATH_MAX, "%s/%s%s",
- home_dir, USER_CONFIG_DIR, DEFAULT_CONFIG_FILENAME);
- user_conf = parse_config(local_filepath);
- }
- } else if (specific_conf != NULL) {
- global_conf = parse_config(specific_conf);
- if (global_conf == NULL) {
- pr_err("Can't access configuration file %s.\n", specific_conf);
- exit(1);
- }
- }
-}
-
int main(int argc, char *argv[], char *envp[])
{
#define PARSING_GLOBAL_CONF 1
@@ -408,7 +237,7 @@ int main(int argc, char *argv[], char *envp[])
bool usage_error = true;
bool has_exec_cmd = false;
bool has_sub_command;
- int opt = 0, idx, help_or_configs;
+ int opt = 0, idx;
int first_count = 1, second_count = 1;
int state = PARSING_GLOBAL_CONF;
int log_level = DEFAULT_LOGLEVEL;
@@ -553,14 +382,7 @@ int main(int argc, char *argv[], char *envp[])
return cr_service_work(atoi(argv[2]));
}
- help_or_configs = passed_help_or_defaults_forbidden(argc, argv);
- if (help_or_configs == 1) {
- usage_error = false;
- goto usage;
- }
- init_configuration(argc, argv, (help_or_configs == DEFAULT_CONFIGS_FORBIDDEN));
- if (global_conf != NULL) first_count = count_elements(global_conf);
- if (user_conf != NULL) second_count = count_elements(user_conf);
+ init_config(argc, argv, &first_count, &second_count);
while (1) {
idx = -1;
diff --git a/criu/include/crtools.h b/criu/include/crtools.h
index a78a577..badfd6d 100644
--- a/criu/include/crtools.h
+++ b/criu/include/crtools.h
@@ -30,6 +30,8 @@ extern int cr_lazy_pages(bool daemon);
extern int check_add_feature(char *arg);
extern void pr_check_features(const char *offset, const char *sep, int width);
+extern void init_config(int argc, char **argv, int *first_cnt, int *second_cnt);
+
#define PPREP_HEAD_INACTIVE ((struct pprep_head *)-1)
#define add_post_prepare_cb_once(phead) do { \
--
2.7.4
More information about the CRIU
mailing list