summaryrefslogtreecommitdiffstats
path: root/src/shared/conf-parser.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/shared/conf-parser.c193
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);
+}