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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user