conf-files: add support for root_fd based operation
Let's make sure we can safely load configuration files based on a root fd, including XAT_FDROOT. (While we are at it, always pass path to root fs before fd to root fs, following our recently updated CODING_STYLE)
This commit is contained in:
+54
-37
@@ -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)
|
||||
@@ -307,8 +323,8 @@ int conf_file_new_at(const char *path, int rfd, ConfFilesFlags flags, ConfFile *
|
||||
return log_oom_full(log_level);
|
||||
|
||||
r = conf_file_chase_and_verify(
|
||||
rfd,
|
||||
root,
|
||||
rfd,
|
||||
c->original_path,
|
||||
c->result,
|
||||
c->name,
|
||||
@@ -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,
|
||||
@@ -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;
|
||||
}
|
||||
@@ -641,7 +657,7 @@ static int conf_files_list_impl(
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -30,7 +30,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 +57,7 @@ int conf_files_list_dropins(
|
||||
char ***ret,
|
||||
const char *dropin_dirname,
|
||||
const char *root,
|
||||
int root_fd,
|
||||
ConfFilesFlags flags,
|
||||
const char * const *dirs);
|
||||
|
||||
|
||||
+1
-2
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
+3
-2
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
+75
-19
@@ -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;
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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. */
|
||||
|
||||
Reference in New Issue
Block a user