preparations for installer PR (#40446)

As suggested by @keszybz the generic preparatory work split out of
#38764
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2026-01-27 15:04:47 +01:00
committed by GitHub
23 changed files with 307 additions and 149 deletions
+69 -52
View File
@@ -24,7 +24,7 @@ ConfFile* conf_file_free(ConfFile *c) {
if (!c)
return NULL;
free(c->name);
free(c->filename);
free(c->result);
free(c->original_path);
free(c->resolved_path);
@@ -44,13 +44,20 @@ static int conf_files_log_level(ConfFilesFlags flags) {
return FLAGS_SET(flags, CONF_FILES_WARN) ? LOG_WARNING : LOG_DEBUG;
}
static int prepare_dirs(const char *root, ConfFilesFlags flags, char * const *dirs, int *ret_rfd, char **ret_root, char ***ret_dirs) {
static int prepare_dirs(
const char *root,
ConfFilesFlags flags,
char * const *dirs,
char **ret_root,
int *ret_rfd,
char ***ret_dirs) {
_cleanup_free_ char *root_abs = NULL;
_cleanup_strv_free_ char **dirs_abs = NULL;
int r;
assert(ret_rfd);
assert(ret_root);
assert(ret_rfd);
assert(ret_dirs || strv_isempty(dirs));
int log_level = conf_files_log_level(flags);
@@ -65,6 +72,7 @@ static int prepare_dirs(const char *root, ConfFilesFlags flags, char * const *di
return log_oom_full(log_level);
}
_cleanup_close_ int rfd = XAT_FDROOT;
if (root) {
/* When a non-trivial root is specified, we will prefix the result later. Hence, it is not
* necessary to modify each config directories here. but needs to normalize the root directory. */
@@ -73,6 +81,11 @@ static int prepare_dirs(const char *root, ConfFilesFlags flags, char * const *di
return log_full_errno(log_level, r, "Failed to make '%s' absolute: %m", root);
path_simplify(root_abs);
rfd = open(root, O_CLOEXEC|O_DIRECTORY|O_PATH);
if (rfd < 0)
return log_full_errno(log_level, errno, "Failed to open '%s': %m", root_abs);
} else if (ret_dirs) {
/* When an empty root or "/" is specified, we will open "/" below, hence we need to make
* each config directory absolute if relative. */
@@ -81,12 +94,8 @@ static int prepare_dirs(const char *root, ConfFilesFlags flags, char * const *di
return log_full_errno(log_level, r, "Failed to make directories absolute: %m");
}
_cleanup_close_ int rfd = open(empty_to_root(root_abs), O_CLOEXEC|O_DIRECTORY|O_PATH);
if (rfd < 0)
return log_full_errno(log_level, errno, "Failed to open '%s': %m", empty_to_root(root_abs));
*ret_rfd = TAKE_FD(rfd);
*ret_root = TAKE_PTR(root_abs);
*ret_rfd = TAKE_FD(rfd);
if (ret_dirs)
*ret_dirs = TAKE_PTR(dirs_abs);
return 0;
@@ -135,8 +144,8 @@ static ChaseFlags conf_files_chase_flags(ConfFilesFlags flags) {
}
static int conf_file_chase_and_verify(
int rfd,
const char *root, /* for logging, can be NULL */
int rfd,
const char *original_path, /* for logging */
const char *path,
const char *name,
@@ -151,7 +160,7 @@ static int conf_file_chase_and_verify(
struct stat st = {};
int r;
assert(rfd >= 0 || rfd == AT_FDCWD);
assert(rfd >= 0 || IN_SET(rfd, AT_FDCWD, XAT_FDROOT));
assert(original_path);
assert(path);
assert(name);
@@ -261,18 +270,25 @@ static int conf_file_chase_and_verify(
return 0;
}
int conf_file_new_at(const char *path, int rfd, ConfFilesFlags flags, ConfFile **ret) {
int conf_file_new_at(
const char *path,
const char *root,
int rfd,
ConfFilesFlags flags,
ConfFile **ret) {
int r;
assert(path);
assert(rfd >= 0 || rfd == AT_FDCWD);
assert(rfd >= 0 || IN_SET(rfd, AT_FDCWD, XAT_FDROOT));
assert(ret);
int log_level = conf_files_log_level(flags);
_cleanup_free_ char *root = NULL;
if (rfd >= 0)
(void) fd_get_path(rfd, &root);
_cleanup_free_ char *_root = NULL;
if (DEBUG_LOGGING && !root) {
(void) fd_get_path(rfd, &_root);
root = _root;
}
_cleanup_(conf_file_freep) ConfFile *c = new(ConfFile, 1);
if (!c)
@@ -286,7 +302,7 @@ int conf_file_new_at(const char *path, int rfd, ConfFilesFlags flags, ConfFile *
if (!c->original_path)
return log_oom_full(log_level);
r = path_extract_filename(path, &c->name);
r = path_extract_filename(path, &c->filename);
if (r < 0)
return log_full_errno(log_level, r, "Failed to extract filename from '%s': %m", path);
@@ -302,16 +318,16 @@ int conf_file_new_at(const char *path, int rfd, ConfFilesFlags flags, ConfFile *
return log_full_errno(log_level, r, "Failed to chase '%s%s': %m", empty_to_root(root), skip_leading_slash(dirpath));
}
c->result = path_join(resolved_dirpath, c->name);
c->result = path_join(resolved_dirpath, c->filename);
if (!c->result)
return log_oom_full(log_level);
r = conf_file_chase_and_verify(
rfd,
root,
rfd,
c->original_path,
c->result,
c->name,
c->filename,
/* masked= */ NULL,
flags,
&c->resolved_path,
@@ -332,7 +348,7 @@ int conf_file_new(const char *path, const char *root, ConfFilesFlags flags, Conf
_cleanup_free_ char *root_abs = NULL;
_cleanup_close_ int rfd = -EBADF;
r = prepare_dirs(root, flags, /* dirs= */ NULL, &rfd, &root_abs, /* ret_dirs= */ NULL);
r = prepare_dirs(root, flags, /* dirs= */ NULL, &root_abs, &rfd, /* ret_dirs= */ NULL);
if (r < 0)
return r;
@@ -346,7 +362,7 @@ int conf_file_new(const char *path, const char *root, ConfFilesFlags flags, Conf
}
_cleanup_(conf_file_freep) ConfFile *c = NULL;
r = conf_file_new_at(path, rfd, flags, &c);
r = conf_file_new_at(path, root_abs, rfd, flags, &c);
if (r < 0)
return r;
@@ -367,8 +383,8 @@ static int files_add(
DIR *dir,
const char *original_dirpath,
const char *resolved_dirpath,
int rfd,
const char *root, /* for logging, can be NULL */
int rfd,
Hashmap **files,
Set **masked,
const char *suffix,
@@ -379,7 +395,7 @@ static int files_add(
assert(dir);
assert(original_dirpath);
assert(resolved_dirpath);
assert(rfd >= 0 || rfd == AT_FDCWD);
assert(rfd >= 0 || IN_SET(rfd, AT_FDCWD, XAT_FDROOT));
assert(files);
assert(masked);
@@ -420,8 +436,8 @@ static int files_add(
_cleanup_close_ int fd = -EBADF;
struct stat st;
r = conf_file_chase_and_verify(
rfd,
root,
rfd,
original_path,
p,
de->d_name,
@@ -440,7 +456,7 @@ static int files_add(
return log_oom_full(log_level);
*c = (ConfFile) {
.name = strdup(de->d_name),
.filename = strdup(de->d_name),
.result = TAKE_PTR(p),
.original_path = TAKE_PTR(original_path),
.resolved_path = TAKE_PTR(resolved_path),
@@ -448,10 +464,10 @@ static int files_add(
.st = st,
};
if (!c->name)
if (!c->filename)
return log_oom_full(log_level);
r = hashmap_ensure_put(files, &conf_file_hash_ops, c->name, c);
r = hashmap_ensure_put(files, &conf_file_hash_ops, c->filename, c);
if (r < 0) {
assert(r == -ENOMEM);
return log_oom_full(log_level);
@@ -481,7 +497,7 @@ static int dump_files(Hashmap *fh, const char *root, ConfFilesFlags flags, ConfF
/* Hence, we need to remove them from the hashmap. */
FOREACH_ARRAY(i, files, n_files)
assert_se(hashmap_remove(fh, (*i)->name) == *i);
assert_se(hashmap_remove(fh, (*i)->filename) == *i);
if (root)
FOREACH_ARRAY(i, files, n_files) {
@@ -522,8 +538,8 @@ static int copy_and_sort_files_from_hashmap(
const char *add = NULL;
if (FLAGS_SET(flags, CONF_FILES_BASENAME))
add = c->name;
else if (root) {
add = c->filename;
else if (root && !FLAGS_SET(flags, CONF_FILES_DONT_PREFIX_ROOT)) {
_cleanup_free_ char *p = NULL;
r = chaseat_prefix_root(c->result, root, &p);
@@ -574,22 +590,22 @@ static int insert_replacement(Hashmap **fh, ConfFile *replacement, ConfFilesFlag
/* This consumes the input ConfFile. */
ConfFile *existing = hashmap_get(*fh, c->name);
ConfFile *existing = hashmap_get(*fh, c->filename);
if (existing) {
log_debug("An entry with higher priority '%s' -> '%s' already exists, ignoring the replacement: %s",
existing->name, existing->result, c->original_path);
existing->filename, existing->result, c->original_path);
*ret = NULL;
return 0;
}
r = hashmap_ensure_put(fh, &conf_file_hash_ops, c->name, c);
r = hashmap_ensure_put(fh, &conf_file_hash_ops, c->filename, c);
if (r < 0) {
assert(r == -ENOMEM);
return log_oom_full(conf_files_log_level(flags));
}
assert(r > 0);
log_debug("Inserted replacement: '%s' -> '%s'", c->name, c->result);
log_debug("Inserted replacement: '%s' -> '%s'", c->filename, c->result);
*ret = TAKE_PTR(c);
return 0;
@@ -597,8 +613,8 @@ static int insert_replacement(Hashmap **fh, ConfFile *replacement, ConfFilesFlag
static int conf_files_list_impl(
const char *suffix,
int rfd,
const char *root, /* for logging, can be NULL */
int rfd,
ConfFilesFlags flags,
const char * const *dirs,
const char *replacement,
@@ -611,13 +627,13 @@ static int conf_files_list_impl(
const ConfFile *inserted = NULL;
int r;
assert(rfd >= 0 || rfd == AT_FDCWD);
assert(rfd >= 0 || IN_SET(rfd, AT_FDCWD, XAT_FDROOT));
assert(ret);
root = empty_to_root(root);
if (replacement) {
r = conf_file_new_at(replacement, rfd, flags & CONF_FILES_WARN, &c);
r = conf_file_new_at(replacement, root, rfd, flags & CONF_FILES_WARN, &c);
if (r < 0)
return r;
}
@@ -635,13 +651,13 @@ static int conf_files_list_impl(
continue;
}
if (c && streq_ptr(path_startswith(c->result, path), c->name)) {
if (c && streq_ptr(path_startswith(c->result, path), c->filename)) {
r = insert_replacement(&fh, TAKE_PTR(c), flags, &inserted);
if (r < 0)
return r;
}
r = files_add(dir, *p, path, rfd, root, &fh, &masked, suffix, flags);
r = files_add(dir, *p, path, root, rfd, &fh, &masked, suffix, flags);
if (r == -ENOMEM)
return r;
}
@@ -673,11 +689,11 @@ int conf_files_list_strv(
assert(ret);
r = prepare_dirs(root, flags, (char**) dirs, &rfd, &root_abs, &dirs_abs);
r = prepare_dirs(root, flags, (char**) dirs, &root_abs, &rfd, &dirs_abs);
if (r < 0)
return r;
r = conf_files_list_impl(suffix, rfd, root_abs, flags, (const char * const *) dirs_abs,
r = conf_files_list_impl(suffix, root_abs, rfd, flags, (const char * const *) dirs_abs,
/* replacement= */ NULL, &fh, /* ret_inserted= */ NULL);
if (r < 0)
return r;
@@ -702,11 +718,11 @@ int conf_files_list_strv_full(
assert(ret_files);
assert(ret_n_files);
r = prepare_dirs(root, flags, (char**) dirs, &rfd, &root_abs, &dirs_abs);
r = prepare_dirs(root, flags, (char**) dirs, &root_abs, &rfd, &dirs_abs);
if (r < 0)
return r;
r = conf_files_list_impl(suffix, rfd, root_abs, flags, (const char * const *) dirs_abs,
r = conf_files_list_impl(suffix, root_abs, rfd, flags, (const char * const *) dirs_abs,
/* replacement= */ NULL, &fh, /* ret_inserted= */ NULL);
if (r < 0)
return r;
@@ -725,13 +741,13 @@ int conf_files_list_strv_at(
_cleanup_free_ char *root = NULL;
int r;
assert(rfd >= 0 || rfd == AT_FDCWD);
assert(rfd >= 0 || IN_SET(rfd, AT_FDCWD, XAT_FDROOT));
assert(ret);
if (rfd >= 0)
if (DEBUG_LOGGING)
(void) fd_get_path(rfd, &root); /* for logging */
r = conf_files_list_impl(suffix, rfd, root, flags, dirs, /* replacement= */ NULL, &fh, /* ret_inserted= */ NULL);
r = conf_files_list_impl(suffix, root, rfd, flags, dirs, /* replacement= */ NULL, &fh, /* ret_inserted= */ NULL);
if (r < 0)
return r;
@@ -750,14 +766,14 @@ int conf_files_list_strv_at_full(
_cleanup_free_ char *root = NULL;
int r;
assert(rfd >= 0 || rfd == AT_FDCWD);
assert(rfd >= 0 || IN_SET(rfd, AT_FDCWD, XAT_FDROOT));
assert(ret_files);
assert(ret_n_files);
if (rfd >= 0)
if (DEBUG_LOGGING)
(void) fd_get_path(rfd, &root); /* for logging */
r = conf_files_list_impl(suffix, rfd, root, flags, dirs, /* replacement= */ NULL, &fh, /* ret_inserted= */ NULL);
r = conf_files_list_impl(suffix, root, rfd, flags, dirs, /* replacement= */ NULL, &fh, /* ret_inserted= */ NULL);
if (r < 0)
return r;
@@ -848,11 +864,11 @@ int conf_files_list_with_replacement(
assert(ret_files);
r = prepare_dirs(root, flags, config_dirs, &rfd, &root_abs, &dirs_abs);
r = prepare_dirs(root, flags, config_dirs, &root_abs, &rfd, &dirs_abs);
if (r < 0)
return r;
r = conf_files_list_impl(".conf", rfd, root_abs, flags, (const char * const *) dirs_abs,
r = conf_files_list_impl(".conf", root_abs, rfd, flags, (const char * const *) dirs_abs,
replacement, &fh, ret_inserted ? &c : NULL);
if (r < 0)
return r;
@@ -878,6 +894,7 @@ int conf_files_list_dropins(
char ***ret,
const char *dropin_dirname,
const char *root,
int root_fd,
ConfFilesFlags flags,
const char * const *dirs) {
@@ -894,7 +911,7 @@ int conf_files_list_dropins(
if (r < 0)
return log_oom_full(conf_files_log_level(flags));
return conf_files_list_strv(ret, ".conf", root, flags, (const char* const*) dropin_dirs);
return conf_files_list_strv_at(ret, ".conf", root_fd, flags, (const char* const*) dropin_dirs);
}
/**
+8 -6
View File
@@ -15,14 +15,15 @@ typedef enum ConfFilesFlags {
CONF_FILES_FILTER_MASKED = CONF_FILES_FILTER_MASKED_BY_SYMLINK | CONF_FILES_FILTER_MASKED_BY_EMPTY,
CONF_FILES_TRUNCATE_SUFFIX = 1 << 6, /* truncate specified suffix from return filename or path */
CONF_FILES_WARN = 1 << 7, /* warn on some errors */
CONF_FILES_DONT_PREFIX_ROOT = 1 << 8, /* don't prefix the specified root path to the resulting paths */
} ConfFilesFlags;
typedef struct ConfFile {
char *name; /* name of a file found in config directories */
char *result; /* resolved config directory with the original file name found in the directory */
char *original_path; /* original config directory with the original file name found in the directory */
char *resolved_path; /* fully resolved path, where the filename part of the path may be different from the original name */
int fd; /* O_PATH fd to resolved_path, -EBADF if the resolved_path does not exist */
char *filename; /* filename of the discovered file (i.e. without any directory prefix) */
char *result; /* full path to the file (with the directory prefix fully resolved, but the filename part left as is) */
char *original_path; /* full path to the file (original – non-resolved – directory prefix + filename part left as is) */
char *resolved_path; /* fully resolved path to the file with both directory prefix and filename fully resolved */
int fd; /* O_PATH fd to resolved_path, -EBADF if resolved_path does not exist */
struct stat st; /* stat of the file. */
} ConfFile;
@@ -30,7 +31,7 @@ ConfFile* conf_file_free(ConfFile *c);
DEFINE_TRIVIAL_CLEANUP_FUNC(ConfFile*, conf_file_free);
void conf_file_free_many(ConfFile **array, size_t n);
int conf_file_new_at(const char *path, int rfd, ConfFilesFlags flags, ConfFile **ret);
int conf_file_new_at(const char *path, const char *root, int rfd, ConfFilesFlags flags, ConfFile **ret);
int conf_file_new(const char *path, const char *root, ConfFilesFlags flags, ConfFile **ret);
int conf_files_list(char ***ret, const char *suffix, const char *root, ConfFilesFlags flags, const char *dir);
@@ -57,6 +58,7 @@ int conf_files_list_dropins(
char ***ret,
const char *dropin_dirname,
const char *root,
int root_fd,
ConfFilesFlags flags,
const char * const *dirs);
+23 -16
View File
@@ -168,7 +168,7 @@ int open_os_release_at(int rfd, char **ret_path, int *ret_fd) {
const char *e;
int r;
assert(rfd >= 0 || rfd == AT_FDCWD);
assert(rfd >= 0 || IN_SET(rfd, AT_FDCWD, XAT_FDROOT));
e = secure_getenv("SYSTEMD_OS_RELEASE");
if (e)
@@ -184,13 +184,15 @@ int open_os_release_at(int rfd, char **ret_path, int *ret_fd) {
}
int open_os_release(const char *root, char **ret_path, int *ret_fd) {
_cleanup_close_ int rfd = -EBADF, fd = -EBADF;
_cleanup_close_ int rfd = XAT_FDROOT, fd = -EBADF;
_cleanup_free_ char *p = NULL;
int r;
rfd = open(empty_to_root(root), O_CLOEXEC | O_DIRECTORY | O_PATH);
if (rfd < 0)
return -errno;
if (!empty_or_root(root)) {
rfd = open(root, O_CLOEXEC | O_DIRECTORY | O_PATH);
if (rfd < 0)
return -errno;
}
r = open_os_release_at(rfd, ret_path ? &p : NULL, ret_fd ? &fd : NULL);
if (r < 0)
@@ -223,7 +225,7 @@ int open_extension_release_at(
const char *p;
int r;
assert(rfd >= 0 || rfd == AT_FDCWD);
assert(rfd >= 0 || IN_SET(rfd, AT_FDCWD, XAT_FDROOT));
assert(!extension || (image_class >= 0 && image_class < _IMAGE_CLASS_MAX));
if (!extension)
@@ -330,13 +332,15 @@ int open_extension_release(
char **ret_path,
int *ret_fd) {
_cleanup_close_ int rfd = -EBADF, fd = -EBADF;
_cleanup_close_ int rfd = XAT_FDROOT, fd = -EBADF;
_cleanup_free_ char *p = NULL;
int r;
rfd = open(empty_to_root(root), O_CLOEXEC | O_DIRECTORY | O_PATH);
if (rfd < 0)
return -errno;
if (!empty_or_root(root)) {
rfd = open(root, O_CLOEXEC | O_DIRECTORY | O_PATH);
if (rfd < 0)
return -errno;
}
r = open_extension_release_at(rfd, image_class, extension, relax_extension_release_check,
ret_path ? &p : NULL, ret_fd ? &fd : NULL);
@@ -366,7 +370,7 @@ static int parse_extension_release_atv(
_cleanup_free_ char *p = NULL;
int r;
assert(rfd >= 0 || rfd == AT_FDCWD);
assert(rfd >= 0 || IN_SET(rfd, AT_FDCWD, XAT_FDROOT));
r = open_extension_release_at(rfd, image_class, extension, relax_extension_release_check, &p, &fd);
if (r < 0)
@@ -385,7 +389,7 @@ int parse_extension_release_at_sentinel(
va_list ap;
int r;
assert(rfd >= 0 || rfd == AT_FDCWD);
assert(rfd >= 0 || IN_SET(rfd, AT_FDCWD, XAT_FDROOT));
va_start(ap, extension);
r = parse_extension_release_atv(rfd, image_class, extension, relax_extension_release_check, ap);
@@ -400,17 +404,20 @@ int parse_extension_release_sentinel(
const char *extension,
...) {
_cleanup_close_ int rfd = -EBADF;
_cleanup_close_ int rfd = XAT_FDROOT;
va_list ap;
int r;
rfd = open(empty_to_root(root), O_CLOEXEC | O_DIRECTORY | O_PATH);
if (rfd < 0)
return -errno;
if (!empty_or_root(root)) {
rfd = open(root, O_CLOEXEC | O_DIRECTORY | O_PATH);
if (rfd < 0)
return -errno;
}
va_start(ap, extension);
r = parse_extension_release_atv(rfd, image_class, extension, relax_extension_release_check, ap);
va_end(ap);
return r;
}
+1 -2
View File
@@ -842,11 +842,10 @@ static int parse_config_file(void) {
(const char* const*) files,
(const char* const*) dirs,
"user.conf.d",
/* root= */ NULL,
"Manager\0",
config_item_table_lookup, items,
CONFIG_PARSE_WARN,
NULL, NULL, NULL);
/* userdata= */ NULL);
}
/* Traditionally "0" was used to turn off the default unit timeouts. Fix this up so that we use
+9 -7
View File
@@ -460,13 +460,15 @@ static int context_load_install_conf(Context *c) {
assert(c);
r = load_kernel_install_conf(arg_root,
c->conf_root,
&machine_id,
&boot_root,
&layout,
&initrd_generator,
&uki_generator);
r = load_kernel_install_conf_at(
c->conf_root ? NULL : arg_root,
c->conf_root ? XAT_FDROOT : c->rfd,
c->conf_root,
&machine_id,
&boot_root,
&layout,
&initrd_generator,
&uki_generator);
if (r <= 0)
return r;
+1 -1
View File
@@ -138,7 +138,7 @@ _public_ int sd_id128_get_machine(sd_id128_t *ret) {
int id128_get_machine_at(int rfd, sd_id128_t *ret) {
int r;
assert(rfd >= 0 || rfd == AT_FDCWD);
assert(rfd >= 0 || IN_SET(rfd, AT_FDCWD, XAT_FDROOT));
r = dir_fd_is_root_or_cwd(rfd);
if (r < 0)
+14 -8
View File
@@ -1031,13 +1031,14 @@ int netdev_load_one(Manager *manager, const char *filename, NetDev **ret) {
dropin_dirname = strjoina(file_basename, ".d");
r = config_parse_many(
STRV_MAKE_CONST(filename), NETWORK_DIRS, dropin_dirname, /* root= */ NULL,
STRV_MAKE_CONST(filename),
NETWORK_DIRS,
dropin_dirname,
NETDEV_COMMON_SECTIONS NETDEV_OTHER_SECTIONS,
config_item_perf_lookup, network_netdev_gperf_lookup,
config_item_perf_lookup,
network_netdev_gperf_lookup,
CONFIG_PARSE_WARN,
netdev_raw,
NULL,
NULL);
netdev_raw);
if (r < 0)
return r; /* config_parse_many() logs internally. */
@@ -1064,10 +1065,15 @@ int netdev_load_one(Manager *manager, const char *filename, NetDev **ret) {
if (NETDEV_VTABLE(netdev)->init)
NETDEV_VTABLE(netdev)->init(netdev);
r = config_parse_many(
STRV_MAKE_CONST(filename), NETWORK_DIRS, dropin_dirname, /* root= */ NULL,
r = config_parse_many_full(
STRV_MAKE_CONST(filename),
NETWORK_DIRS,
dropin_dirname,
/* root= */ NULL,
/* root_fd= */ -EBADF,
NETDEV_VTABLE(netdev)->sections,
config_item_perf_lookup, network_netdev_gperf_lookup,
config_item_perf_lookup,
network_netdev_gperf_lookup,
CONFIG_PARSE_WARN,
netdev,
&netdev->stats_by_path,
+8 -1
View File
@@ -17,6 +17,7 @@
#include "edit-util.h"
#include "errno-util.h"
#include "extract-word.h"
#include "fd-util.h"
#include "log.h"
#include "mkdir-label.h"
#include "netlink-util.h"
@@ -106,7 +107,13 @@ static int get_config_files_by_name(
if (!dropin_dirname)
return -ENOMEM;
r = conf_files_list_dropins(ret_dropins, dropin_dirname, /* root= */ NULL, CONF_FILES_WARN, NETWORK_DIRS);
r = conf_files_list_dropins(
ret_dropins,
dropin_dirname,
/* root= */ NULL,
/* root_fd= */ XAT_FDROOT,
CONF_FILES_WARN,
NETWORK_DIRS);
if (r < 0)
return r;
}
+8 -3
View File
@@ -514,8 +514,12 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
.ipoib_umcast = -1,
};
r = config_parse_many(
STRV_MAKE_CONST(filename), NETWORK_DIRS, dropin_dirname, /* root= */ NULL,
r = config_parse_many_full(
STRV_MAKE_CONST(filename),
NETWORK_DIRS,
dropin_dirname,
/* root= */ NULL,
/* root_fd= */ -EBADF,
"Match\0"
"Link\0"
"SR-IOV\0"
@@ -574,7 +578,8 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
"StochasticFairnessQueueing\0"
"TokenBucketFilter\0"
"TrivialLinkEqualizer\0",
config_item_perf_lookup, network_network_gperf_lookup,
config_item_perf_lookup,
network_network_gperf_lookup,
CONFIG_PARSE_WARN,
network,
&network->stats_by_path,
+4 -3
View File
@@ -2871,16 +2871,17 @@ static int partition_read_definition(
dropin_dirname = strjoina(filename, ".d");
r = config_parse_many(
r = config_parse_many_full(
STRV_MAKE_CONST(path),
conf_file_dirs,
dropin_dirname,
c->definitions ? NULL : arg_root,
/* root_fd= */ -EBADF,
"Partition\0",
config_item_table_lookup, table,
CONFIG_PARSE_WARN,
p,
NULL,
/* ret_stats_by_path= */ NULL,
&p->drop_in_files);
if (r < 0)
return r;
@@ -3396,7 +3397,7 @@ static int context_read_definitions(Context *context) {
&files,
".conf",
context->definitions ? NULL : arg_root,
CONF_FILES_REGULAR|CONF_FILES_FILTER_MASKED|CONF_FILES_WARN,
CONF_FILES_REGULAR|CONF_FILES_FILTER_MASKED|CONF_FILES_WARN|CONF_FILES_DONT_PREFIX_ROOT,
dirs);
if (r < 0)
return log_error_errno(r, "Failed to enumerate *.conf files: %m");
+1 -4
View File
@@ -188,14 +188,11 @@ static int dns_delegate_load(Manager *m, const char *path) {
STRV_MAKE_CONST(path),
DNS_DELEGATE_SEARCH_DIRS,
dropin_dirname,
/* root= */ NULL,
"Delegate\0",
config_item_perf_lookup,
resolved_dns_delegate_gperf_lookup,
/* flags= */ 0,
d,
/* ret_stats_by_path= */ NULL,
/* ret_drop_in_files= */ NULL);
d);
if (r < 0)
return r;
+4 -4
View File
@@ -125,13 +125,13 @@ static int dnssd_registered_service_load(Manager *manager, const char *path) {
return log_oom();
r = config_parse_many(
STRV_MAKE_CONST(path), DNSSD_SERVICE_DIRS, dropin_dirname, /* root= */ NULL,
STRV_MAKE_CONST(path),
DNSSD_SERVICE_DIRS,
dropin_dirname,
"Service\0",
config_item_perf_lookup, resolved_dnssd_gperf_lookup,
CONFIG_PARSE_WARN,
service,
NULL,
NULL);
service);
if (r < 0)
return r;
+10 -9
View File
@@ -22,7 +22,7 @@ static int entry_token_load_one(int rfd, const char *dir, BootEntryTokenType *ty
_cleanup_fclose_ FILE *f = NULL;
int r;
assert(rfd >= 0 || rfd == AT_FDCWD);
assert(rfd >= 0 || IN_SET(rfd, AT_FDCWD, XAT_FDROOT));
assert(dir);
assert(type);
assert(*type == BOOT_ENTRY_TOKEN_AUTO);
@@ -58,7 +58,7 @@ static int entry_token_load_one(int rfd, const char *dir, BootEntryTokenType *ty
static int entry_token_load(int rfd, const char *conf_root, BootEntryTokenType *type, char **token) {
int r;
assert(rfd >= 0 || rfd == AT_FDCWD);
assert(rfd >= 0 || IN_SET(rfd, AT_FDCWD, XAT_FDROOT));
assert(type);
assert(*type == BOOT_ENTRY_TOKEN_AUTO);
assert(token);
@@ -98,7 +98,7 @@ static int entry_token_from_os_release(int rfd, BootEntryTokenType *type, char *
_cleanup_free_ char *id = NULL, *image_id = NULL;
int r;
assert(rfd >= 0 || rfd == AT_FDCWD);
assert(rfd >= 0 || IN_SET(rfd, AT_FDCWD, XAT_FDROOT));
assert(type);
assert(IN_SET(*type, BOOT_ENTRY_TOKEN_AUTO, BOOT_ENTRY_TOKEN_OS_IMAGE_ID, BOOT_ENTRY_TOKEN_OS_ID));
assert(token);
@@ -151,7 +151,7 @@ int boot_entry_token_ensure_at(
int r;
assert(rfd >= 0 || rfd == AT_FDCWD);
assert(rfd >= 0 || IN_SET(rfd, AT_FDCWD, XAT_FDROOT));
assert(type);
assert(token);
@@ -229,11 +229,12 @@ int boot_entry_token_ensure(
if (*token)
return 0; /* Already set. */
_cleanup_close_ int rfd = -EBADF;
rfd = open(empty_to_root(root), O_CLOEXEC | O_DIRECTORY | O_PATH);
if (rfd < 0)
return -errno;
_cleanup_close_ int rfd = XAT_FDROOT;
if (!empty_or_root(root)) {
rfd = open(root, O_CLOEXEC | O_DIRECTORY | O_PATH);
if (rfd < 0)
return -errno;
}
return boot_entry_token_ensure_at(rfd, conf_root, machine_id, machine_id_is_random, type, token);
}
+75 -19
View File
@@ -481,6 +481,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,
int root_fd,
const char* const* conf_files,
char **files,
const char *sections,
@@ -502,17 +503,17 @@ static int config_parse_many_files(
return log_oom_full(level);
}
/* Pin and stat() all dropins */
STRV_FOREACH(fn, files) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *fname = NULL;
r = chase_and_fopen_unlocked(*fn, root, CHASE_AT_RESOLVE_IN_ROOT, "re", &fname, &f);
r = chase_and_fopenat_unlocked(root_fd, *fn, CHASE_AT_RESOLVE_IN_ROOT|CHASE_MUST_BE_REGULAR, "re", /* ret_path= */ NULL, &f);
if (r == -ENOENT)
continue;
if (r < 0)
return log_full_errno(level, r, "Failed to open %s: %m", *fn);
int fd = fileno(f);
assert(fd >= 0);
r = ordered_hashmap_ensure_put(&dropins, &config_file_hash_ops_fclose, *fn, f);
if (r < 0) {
@@ -537,11 +538,10 @@ static int config_parse_many_files(
return log_oom_full(level);
}
/* First read the first found main config file. */
/* First process the first found main config file. */
STRV_FOREACH(fn, conf_files) {
_cleanup_fclose_ FILE *f = NULL;
r = chase_and_fopen_unlocked(*fn, root, CHASE_AT_RESOLVE_IN_ROOT, "re", NULL, &f);
r = chase_and_fopenat_unlocked(root_fd, *fn, CHASE_AT_RESOLVE_IN_ROOT|CHASE_MUST_BE_REGULAR, "re", /* ret_path= */ NULL, &f);
if (r == -ENOENT)
continue;
if (r < 0)
@@ -572,7 +572,6 @@ static int config_parse_many_files(
}
/* Then read all the drop-ins. */
const char *path_dropin;
FILE *f_dropin;
ORDERED_HASHMAP_FOREACH_KEY(f_dropin, path_dropin, dropins) {
@@ -594,12 +593,39 @@ static int config_parse_many_files(
return 0;
}
static int normalize_root_fd(const char *root, int *root_fd, int *ret_opened_fd) {
assert(root_fd);
assert(ret_opened_fd);
/* Normalizes a root dir specification: if root_fd is already valid, keep it. Otherwise, we open the
* specified dir */
if (*root_fd >= 0 || IN_SET(*root_fd, AT_FDCWD, XAT_FDROOT)) {
*ret_opened_fd = -EBADF;
return 0;
}
if (empty_or_root(root)) {
*root_fd = XAT_FDROOT;
*ret_opened_fd = -EBADF;
return 0;
}
int fd = open(root, O_CLOEXEC|O_PATH|O_DIRECTORY);
if (fd < 0)
return log_error_errno(errno, "Failed to open root directory '%s': %m", root);
*ret_opened_fd = *root_fd = fd;
return 0;
}
/* Parse each config file in the directories specified as strv. */
int config_parse_many(
int config_parse_many_full(
const char* const* conf_files,
const char* const* conf_file_dirs,
const char *dropin_dirname,
const char *root,
int root_fd,
const char *sections,
ConfigItemLookup lookup,
const void *table,
@@ -615,14 +641,33 @@ int config_parse_many(
assert(dropin_dirname);
assert(table);
r = conf_files_list_dropins(&files, dropin_dirname, root,
FLAGS_SET(flags, CONFIG_PARSE_WARN) ? CONF_FILES_WARN : 0,
conf_file_dirs);
_cleanup_close_ int opened_root_fd = -EBADF;
r = normalize_root_fd(root, &root_fd, &opened_root_fd);
if (r < 0)
return r;
r = conf_files_list_dropins(
&files,
dropin_dirname,
root,
root_fd,
FLAGS_SET(flags, CONFIG_PARSE_WARN) ? CONF_FILES_WARN : 0,
conf_file_dirs);
if (r < 0)
return log_full_errno(FLAGS_SET(flags, CONFIG_PARSE_WARN) ? LOG_WARNING : LOG_DEBUG, r,
"Failed to list drop-ins in %s: %m", dropin_dirname);
r = config_parse_many_files(root, conf_files, files, sections, lookup, table, flags, userdata, ret_stats_by_path);
r = config_parse_many_files(
root,
root_fd,
conf_files,
files,
sections,
lookup,
table,
flags,
userdata,
ret_stats_by_path);
if (r < 0)
return r; /* config_parse_many_files() logs internally. */
@@ -634,6 +679,7 @@ int config_parse_many(
int config_parse_standard_file_with_dropins_full(
const char *root,
int root_fd,
const char *main_file, /* A path like "systemd/frobnicator.conf" */
const char *sections,
ConfigItemLookup lookup,
@@ -643,12 +689,15 @@ int config_parse_standard_file_with_dropins_full(
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;
const char* const *conf_file_dirs = (const char* const*) CONF_PATHS_STRV("");
_cleanup_strv_free_ char **conf_files = NULL;
int r, level = FLAGS_SET(flags, CONFIG_PARSE_WARN) ? LOG_WARNING : LOG_DEBUG;
/* Build the list of main config files */
r = strv_extend_strv_biconcat(&configs, root, conf_paths, main_file);
r = strv_extend_strv_concat(
&conf_files,
conf_file_dirs,
main_file);
if (r < 0)
return log_oom_full(level);
@@ -656,11 +705,12 @@ int config_parse_standard_file_with_dropins_full(
if (!dropin_dirname)
return log_oom_full(level);
return config_parse_many(
(const char* const*) configs,
conf_paths,
return config_parse_many_full(
(const char* const*) conf_files,
conf_file_dirs,
dropin_dirname,
root,
root_fd,
sections,
lookup,
table,
@@ -692,7 +742,13 @@ static int dropins_get_stats_by_path(
if (!strextend(&dropin_dirname, ".d"))
return -ENOMEM;
r = conf_files_list_dropins(&files, dropin_dirname, /* root= */ NULL, /* flags= */ 0, conf_file_dirs);
r = conf_files_list_dropins(
&files,
dropin_dirname,
/* root= */ NULL,
/* root_fd= */ XAT_FDROOT,
/* flags= */ 0,
conf_file_dirs);
if (r < 0)
return r;
+30 -2
View File
@@ -5,7 +5,7 @@
#include "alloc-util.h"
#include "conf-parser-forward.h"
#include "shared-forward.h"
#include "fd-util.h"
#include "log.h"
/* An abstract parser for simple, line based, shallow configuration files consisting of variable assignments only. */
@@ -66,11 +66,12 @@ int config_parse(
void *userdata,
struct stat *ret_stat); /* possibly NULL */
int config_parse_many(
int config_parse_many_full(
const char* const* conf_files, /* possibly empty */
const char* const* conf_file_dirs,
const char *dropin_dirname,
const char *root,
int root_fd,
const char *sections, /* nulstr */
ConfigItemLookup lookup,
const void *table,
@@ -79,8 +80,34 @@ int config_parse_many(
Hashmap **ret_stats_by_path, /* possibly NULL */
char ***ret_dropin_files); /* possibly NULL */
static inline int config_parse_many(
const char* const* conf_files, /* possibly empty */
const char* const* conf_file_dirs,
const char *dropin_dirname,
const char *sections, /* nulstr */
ConfigItemLookup lookup,
const void *table,
ConfigParseFlags flags,
void *userdata) {
return config_parse_many_full(
conf_files,
conf_file_dirs,
dropin_dirname,
/* root= */ NULL,
/* root_fd= */ XAT_FDROOT,
sections,
lookup,
table,
flags,
userdata,
/* ret_stats_by_path= */ NULL,
/* ret_drop_in_files= */ NULL);
}
int config_parse_standard_file_with_dropins_full(
const char *root,
int root_fd,
const char *main_file, /* A path like "systemd/frobnicator.conf" */
const char *sections,
ConfigItemLookup lookup,
@@ -99,6 +126,7 @@ static inline int config_parse_standard_file_with_dropins(
void *userdata) {
return config_parse_standard_file_with_dropins_full(
/* root= */ NULL,
/* root_fd= */ XAT_FDROOT,
main_file,
sections,
lookup,
+9 -3
View File
@@ -2,11 +2,13 @@
#include "alloc-util.h"
#include "conf-parser.h"
#include "fd-util.h"
#include "kernel-config.h"
#include "path-util.h"
int load_kernel_install_conf(
int load_kernel_install_conf_at(
const char *root,
int root_fd,
const char *conf_root,
char **ret_machine_id,
char **ret_boot_root,
@@ -26,16 +28,19 @@ int load_kernel_install_conf(
};
int r;
assert(root_fd >= 0 || IN_SET(root_fd, AT_FDCWD, XAT_FDROOT));
if (conf_root) {
_cleanup_free_ char *conf = path_join(conf_root, "install.conf");
if (!conf)
return log_oom();
r = config_parse_many(
r = config_parse_many_full(
STRV_MAKE_CONST(conf),
STRV_MAKE_CONST(conf_root),
"install.conf.d",
/* root= */ NULL, /* $KERNEL_INSTALL_CONF_ROOT and --root are independent */
root,
root_fd,
/* sections= */ NULL,
config_item_table_lookup, items,
CONFIG_PARSE_WARN,
@@ -45,6 +50,7 @@ int load_kernel_install_conf(
} else
r = config_parse_standard_file_with_dropins_full(
root,
root_fd,
"kernel/install.conf",
/* sections= */ NULL,
config_item_table_lookup, items,
+15 -1
View File
@@ -1,13 +1,27 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "fd-util.h"
#include "shared-forward.h"
int load_kernel_install_conf(
int load_kernel_install_conf_at(
const char *root,
int root_fd,
const char *conf_root,
char **ret_machine_id,
char **ret_boot_root,
char **ret_layout,
char **ret_initrd_generator,
char **ret_uki_generator);
static inline int load_kernel_install_conf(
const char *root,
const char *conf_root,
char **ret_machine_id,
char **ret_boot_root,
char **ret_layout,
char **ret_initrd_generator,
char **ret_uki_generator) {
return load_kernel_install_conf_at(root, XAT_FDROOT, conf_root, ret_machine_id, ret_boot_root, ret_layout, ret_initrd_generator, ret_uki_generator);
}
+1
View File
@@ -191,6 +191,7 @@ static int parse_config_file(ImageClass image_class) {
r = config_parse_standard_file_with_dropins_full(
arg_root,
/* root_fd= */ -EBADF,
config_file,
sections,
config_item_table_lookup, items,
+2 -1
View File
@@ -101,11 +101,12 @@ int feature_read_definition(Feature *f, const char *path, const char *const *dir
if (r < 0)
return log_error_errno(r, "Failed to extract filename from path '%s': %m", path);
r = config_parse_many(
r = config_parse_many_full(
STRV_MAKE_CONST(path),
dirs,
strjoina(filename, ".d"),
arg_root,
/* root_fd= */ -EBADF,
"Feature\0",
config_item_table_lookup, table,
CONFIG_PARSE_WARN,
+2 -1
View File
@@ -543,11 +543,12 @@ int transfer_read_definition(Transfer *t, const char *path, const char **dirs, H
if (r < 0)
return log_error_errno(r, "Failed to extract filename from path '%s': %m", path);
r = config_parse_many(
r = config_parse_many_full(
STRV_MAKE_CONST(path),
dirs,
strjoina(filename, ".d"),
arg_root,
/* root_fd= */ -EBADF,
"Transfer\0"
"Source\0"
"Target\0",
+2 -2
View File
@@ -1568,12 +1568,12 @@ static int verb_components(int argc, char **argv, void *userdata) {
FOREACH_ARRAY(i, directories, n_directories) {
ConfFile *e = *i;
if (streq(e->name, "sysupdate.d")) {
if (streq(e->filename, "sysupdate.d")) {
has_default_component = true;
continue;
}
const char *s = startswith(e->name, "sysupdate.");
const char *s = startswith(e->filename, "sysupdate.");
if (!s)
continue;
+6 -2
View File
@@ -444,7 +444,9 @@ TEST(config_parse_standard_file_with_dropins_full) {
};
r = config_parse_standard_file_with_dropins_full(
root, "kernel/install.conf",
root,
/* root_fd= */ -EBADF,
"kernel/install.conf",
/* sections= */ NULL,
config_item_table_lookup, items,
CONFIG_PARSE_WARN,
@@ -483,7 +485,9 @@ TEST(config_parse_standard_file_with_dropins_full) {
assert_se(symlinkat("/etc/kernel/install.conf.d/drop4.conf", rfd, "etc/kernel/install2.conf.d/drop4.conf") == 0);
r = config_parse_standard_file_with_dropins_full(
root, "kernel/install2.conf",
root,
/* root_fd= */ -EBADF,
"kernel/install2.conf",
/* sections= */ NULL,
config_item_table_lookup, items,
CONFIG_PARSE_WARN,
+5 -2
View File
@@ -280,17 +280,20 @@ int link_load_one(LinkConfigContext *ctx, const char *filename) {
return log_error_errno(r, "Failed to extract file name of '%s': %m", filename);
dropin_dirname = strjoina(file_basename, ".d");
r = config_parse_many(
r = config_parse_many_full(
STRV_MAKE_CONST(filename),
NETWORK_DIRS,
dropin_dirname,
/* root= */ NULL,
/* root_fd= */ -EBADF,
"Match\0"
"Link\0"
"SR-IOV\0"
"EnergyEfficientEthernet\0",
config_item_perf_lookup, link_config_gperf_lookup,
CONFIG_PARSE_WARN, config, &stats_by_path,
CONFIG_PARSE_WARN,
config,
&stats_by_path,
&config->dropins);
if (r < 0)
return r; /* config_parse_many() logs internally. */