diff options
Diffstat (limited to '')
-rw-r--r-- | src/shared/conf-parser.c | 193 |
1 files changed, 114 insertions, 79 deletions
diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index e8ecd9b..fcc45c6 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -8,6 +8,7 @@ #include <sys/types.h> #include "alloc-util.h" +#include "chase.h" #include "conf-files.h" #include "conf-parser.h" #include "constants.h" @@ -159,7 +160,11 @@ static int next_assignment( /* Warn about unknown non-extension fields. */ if (!(flags & CONFIG_PARSE_RELAXED) && !startswith(lvalue, "X-")) log_syntax(unit, LOG_WARNING, filename, line, 0, - "Unknown key name '%s' in section '%s', ignoring.", lvalue, section); + "Unknown key '%s'%s%s%s, ignoring.", + lvalue, + section ? " in section [" : "", + strempty(section), + section ? "]" : ""); return 0; } @@ -480,6 +485,7 @@ int hashmap_put_stats_by_path(Hashmap **stats_by_path, const char *path, const s } static int config_parse_many_files( + const char *root, const char* const* conf_files, char **files, const char *sections, @@ -502,19 +508,16 @@ static int config_parse_many_files( } STRV_FOREACH(fn, files) { - _cleanup_free_ struct stat *st_dropin = NULL; _cleanup_fclose_ FILE *f = NULL; - int fd; + _cleanup_free_ char *fname = NULL; - f = fopen(*fn, "re"); - if (!f) { - if (errno == ENOENT) - continue; - - return -errno; - } + r = chase_and_fopen_unlocked(*fn, root, CHASE_AT_RESOLVE_IN_ROOT, "re", &fname, &f); + if (r == -ENOENT) + continue; + if (r < 0) + return r; - fd = fileno(f); + int fd = fileno(f); r = ordered_hashmap_ensure_put(&dropins, &config_file_hash_ops_fclose, *fn, f); if (r < 0) { @@ -527,7 +530,7 @@ static int config_parse_many_files( /* Get inodes for all drop-ins. Later we'll verify if main config is a symlink to or is * symlinked as one of them. If so, we skip reading main config file directly. */ - st_dropin = new(struct stat, 1); + _cleanup_free_ struct stat *st_dropin = new(struct stat, 1); if (!st_dropin) return -ENOMEM; @@ -543,13 +546,11 @@ static int config_parse_many_files( STRV_FOREACH(fn, conf_files) { _cleanup_fclose_ FILE *f = NULL; - f = fopen(*fn, "re"); - if (!f) { - if (errno == ENOENT) - continue; - - return -errno; - } + r = chase_and_fopen_unlocked(*fn, root, CHASE_AT_RESOLVE_IN_ROOT, "re", NULL, &f); + if (r == -ENOENT) + continue; + if (r < 0) + return r; if (inodes) { if (fstat(fileno(f), &st) < 0) @@ -561,7 +562,7 @@ static int config_parse_many_files( } } - r = config_parse(NULL, *fn, f, sections, lookup, table, flags, userdata, &st); + r = config_parse(/* unit= */ NULL, *fn, f, sections, lookup, table, flags, userdata, &st); if (r < 0) return r; assert(r > 0); @@ -580,7 +581,7 @@ static int config_parse_many_files( const char *path_dropin; FILE *f_dropin; ORDERED_HASHMAP_FOREACH_KEY(f_dropin, path_dropin, dropins) { - r = config_parse(NULL, path_dropin, f_dropin, sections, lookup, table, flags, userdata, &st); + r = config_parse(/* unit= */ NULL, path_dropin, f_dropin, sections, lookup, table, flags, userdata, &st); if (r < 0) return r; assert(r > 0); @@ -598,54 +599,6 @@ static int config_parse_many_files( return 0; } -/* Parse one main config file located in /etc/systemd and its drop-ins, which is what all systemd daemons - * do. */ -int config_parse_config_file( - const char *conf_file, - const char *sections, - ConfigItemLookup lookup, - const void *table, - ConfigParseFlags flags, - void *userdata) { - - _cleanup_strv_free_ char **dropins = NULL, **dropin_dirs = NULL; - char **conf_paths = CONF_PATHS_STRV(""); - int r; - - assert(conf_file); - - /* build the dropin dir list */ - dropin_dirs = new0(char*, strv_length(conf_paths) + 1); - if (!dropin_dirs) { - if (flags & CONFIG_PARSE_WARN) - return log_oom(); - return -ENOMEM; - } - - size_t i = 0; - STRV_FOREACH(p, conf_paths) { - char *d; - - d = strjoin(*p, "systemd/", conf_file, ".d"); - if (!d) { - if (flags & CONFIG_PARSE_WARN) - return log_oom(); - return -ENOMEM; - } - - dropin_dirs[i++] = d; - } - - r = conf_files_list_strv(&dropins, ".conf", NULL, 0, (const char**) dropin_dirs); - if (r < 0) - return r; - - const char *sysconf_file = strjoina(PKGSYSCONFDIR, "/", conf_file); - - return config_parse_many_files(STRV_MAKE_CONST(sysconf_file), dropins, - sections, lookup, table, flags, userdata, NULL); -} - /* Parse each config file in the directories specified as strv. */ int config_parse_many( const char* const* conf_files, @@ -665,14 +618,13 @@ int config_parse_many( assert(conf_file_dirs); assert(dropin_dirname); - assert(sections); assert(table); r = conf_files_list_dropins(&files, dropin_dirname, root, conf_file_dirs); if (r < 0) return r; - r = config_parse_many_files(conf_files, files, sections, lookup, table, flags, userdata, ret_stats_by_path); + r = config_parse_many_files(root, conf_files, files, sections, lookup, table, flags, userdata, ret_stats_by_path); if (r < 0) return r; @@ -682,6 +634,50 @@ int config_parse_many( return 0; } +int config_parse_standard_file_with_dropins_full( + const char *root, + const char *main_file, /* A path like "systemd/frobnicator.conf" */ + const char *sections, + ConfigItemLookup lookup, + const void *table, + ConfigParseFlags flags, + void *userdata, + Hashmap **ret_stats_by_path, + char ***ret_dropin_files) { + + const char* const *conf_paths = (const char* const*) CONF_PATHS_STRV(""); + _cleanup_strv_free_ char **configs = NULL; + int r; + + /* Build the list of main config files */ + r = strv_extend_strv_biconcat(&configs, root, conf_paths, main_file); + if (r < 0) { + if (flags & CONFIG_PARSE_WARN) + log_oom(); + return r; + } + + _cleanup_free_ char *dropin_dirname = strjoin(main_file, ".d"); + if (!dropin_dirname) { + if (flags & CONFIG_PARSE_WARN) + log_oom(); + return -ENOMEM; + } + + return config_parse_many( + (const char* const*) configs, + conf_paths, + dropin_dirname, + root, + sections, + lookup, + table, + flags, + userdata, + ret_stats_by_path, + ret_dropin_files); +} + static int dropins_get_stats_by_path( const char* conf_file, const char* const* conf_file_dirs, @@ -795,12 +791,12 @@ bool stats_by_path_equal(Hashmap *a, Hashmap *b) { return true; } -static void config_section_hash_func(const ConfigSection *c, struct siphash *state) { +void config_section_hash_func(const ConfigSection *c, struct siphash *state) { siphash24_compress_string(c->filename, state); - siphash24_compress(&c->line, sizeof(c->line), state); + siphash24_compress_typesafe(c->line, state); } -static int config_section_compare_func(const ConfigSection *x, const ConfigSection *y) { +int config_section_compare_func(const ConfigSection *x, const ConfigSection *y) { int r; r = strcmp(x->filename, y->filename); @@ -1062,7 +1058,7 @@ int config_parse_tristate( if (isempty(rvalue)) { *t = -1; - return 0; + return 1; } r = parse_tristate(rvalue, t); @@ -1072,7 +1068,7 @@ int config_parse_tristate( return 0; } - return 0; + return 1; } int config_parse_string( @@ -1088,6 +1084,7 @@ int config_parse_string( void *userdata) { char **s = ASSERT_PTR(data); + int r; assert(filename); assert(lvalue); @@ -1095,7 +1092,7 @@ int config_parse_string( if (isempty(rvalue)) { *s = mfree(*s); - return 0; + return 1; } if (FLAGS_SET(ltype, CONFIG_PARSE_STRING_SAFE) && !string_is_safe(rvalue)) { @@ -1116,7 +1113,11 @@ int config_parse_string( return 0; } - return free_and_strdup_warn(s, empty_to_null(rvalue)); + r = free_and_strdup_warn(s, empty_to_null(rvalue)); + if (r < 0) + return r; + + return 1; } int config_parse_dns_name( @@ -1592,7 +1593,7 @@ int config_parse_mtu( return 0; } - return 0; + return 1; } int config_parse_rlimit( @@ -1982,3 +1983,37 @@ int config_parse_unsigned_bounded( DEFINE_CONFIG_PARSE(config_parse_percent, parse_percent, "Failed to parse percent value"); DEFINE_CONFIG_PARSE(config_parse_permyriad, parse_permyriad, "Failed to parse permyriad value"); DEFINE_CONFIG_PARSE_PTR(config_parse_sec_fix_0, parse_sec_fix_0, usec_t, "Failed to parse time value"); + +int config_parse_timezone( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + char **tz = ASSERT_PTR(data); + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + if (isempty(rvalue)) { + *tz = mfree(*tz); + return 0; + } + + r = verify_timezone(rvalue, LOG_WARNING); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Timezone is not valid, ignoring assignment: %s", rvalue); + return 0; + } + + return free_and_strdup_warn(tz, rvalue); +} |