diff options
author | Mike Yuan <me@yhndnzj.com> | 2023-11-09 19:54:21 +0100 |
---|---|---|
committer | Yu Watanabe <watanabe.yu+github@gmail.com> | 2023-11-12 21:11:26 +0100 |
commit | 9ac2f3c4d2cc02eda32034980461c21232bb746c (patch) | |
tree | 2171a0c616c38229b41a46099c865cc9ae58cac4 /src | |
parent | Merge pull request #29976 from YHNdnzj/session-by-leader-pidref (diff) | |
download | systemd-9ac2f3c4d2cc02eda32034980461c21232bb746c.tar.xz systemd-9ac2f3c4d2cc02eda32034980461c21232bb746c.zip |
conf-parser: pin seen config files
Follow-up for 93f1da45566d064f4f053b37bbac2813631f58b1
Addresses https://github.com/systemd/systemd/commit/93f1da45566d064f4f053b37bbac2813631f58b1#r132152321
Diffstat (limited to 'src')
-rw-r--r-- | src/shared/conf-parser.c | 79 |
1 files changed, 58 insertions, 21 deletions
diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index 667480dc4f..f552e9aed2 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -18,6 +18,7 @@ #include "fd-util.h" #include "fileio.h" #include "fs-util.h" +#include "hash-funcs.h" #include "hostname-util.h" #include "id128-util.h" #include "in-addr-util.h" @@ -42,6 +43,10 @@ #include "time-util.h" #include "utf8.h" +DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(config_file_hash_ops_fclose, + char, path_hash_func, path_compare, + FILE, safe_fclose); + int config_item_table_lookup( const void *table, const char *section, @@ -485,6 +490,7 @@ static int config_parse_many_files( Hashmap **ret_stats_by_path) { _cleanup_hashmap_free_ Hashmap *stats_by_path = NULL; + _cleanup_ordered_hashmap_free_ OrderedHashmap *dropins = NULL; _cleanup_set_free_ Set *inodes = NULL; struct stat st; int r; @@ -495,18 +501,38 @@ static int config_parse_many_files( return -ENOMEM; } - /* Get inodes for all drop-ins. Later we'll verify if main config is a symlink to one of them. If so, - * we skip reading main config file directly. */ STRV_FOREACH(fn, files) { _cleanup_free_ struct stat *st_dropin = NULL; + _cleanup_fclose_ FILE *f = NULL; + int fd; + + f = fopen(*fn, "re"); + if (!f) { + if (errno == ENOENT) + continue; + + return -errno; + } + + fd = fileno(f); + + r = ordered_hashmap_ensure_put(&dropins, &config_file_hash_ops_fclose, *fn, f); + if (r < 0) { + assert(r != -EEXIST); + return r; + } + assert(r > 0); + TAKE_PTR(f); + + /* 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); if (!st_dropin) return -ENOMEM; - r = RET_NERRNO(stat(*fn, st_dropin)); - if (r < 0 && r != -ENOENT) - return r; + if (fstat(fd, st_dropin) < 0) + return -errno; r = set_ensure_consume(&inodes, &inode_hash_ops, TAKE_PTR(st_dropin)); if (r < 0) @@ -515,42 +541,53 @@ static int config_parse_many_files( /* First read the first found main config file. */ STRV_FOREACH(fn, conf_files) { + _cleanup_fclose_ FILE *f = NULL; + + f = fopen(*fn, "re"); + if (!f) { + if (errno == ENOENT) + continue; + + return -errno; + } + if (inodes) { - r = RET_NERRNO(stat(*fn, &st)); - if (r < 0 && r != -ENOENT) - return r; + if (fstat(fileno(f), &st) < 0) + return -errno; if (set_contains(inodes, &st)) { - log_debug("%s: symlink to drop-in, will be read later.", *fn); + log_debug("%s: symlink to/symlinked as drop-in, will be read later.", *fn); continue; } } - r = config_parse(NULL, *fn, NULL, sections, lookup, table, flags, userdata, &st); + r = config_parse(NULL, *fn, f, sections, lookup, table, flags, userdata, &st); if (r < 0) return r; - if (r == 0) - continue; + if (r > 0) { + if (ret_stats_by_path) { + r = hashmap_put_stats_by_path(&stats_by_path, *fn, &st); + if (r < 0) + return r; + } - if (ret_stats_by_path) { - r = hashmap_put_stats_by_path(&stats_by_path, *fn, &st); - if (r < 0) - return r; + break; } - - break; } /* Then read all the drop-ins. */ - STRV_FOREACH(fn, files) { - r = config_parse(NULL, *fn, NULL, sections, lookup, table, flags, userdata, &st); + + 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); if (r < 0) return r; if (r == 0) continue; if (ret_stats_by_path) { - r = hashmap_put_stats_by_path(&stats_by_path, *fn, &st); + r = hashmap_put_stats_by_path(&stats_by_path, path_dropin, &st); if (r < 0) return r; } |