conf-files: introduce struct ConfFile to store information of found conf file
It is currently unused, will be used later. Preparation for later changes.
This commit is contained in:
+181
-43
@@ -20,6 +20,187 @@
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
ConfFile* conf_file_free(ConfFile *c) {
|
||||
if (!c)
|
||||
return NULL;
|
||||
|
||||
free(c->name);
|
||||
free(c->result);
|
||||
free(c->original_path);
|
||||
free(c->resolved_path);
|
||||
safe_close(c->fd);
|
||||
|
||||
return mfree(c);
|
||||
}
|
||||
|
||||
void conf_file_free_many(ConfFile **array, size_t n) {
|
||||
FOREACH_ARRAY(i, array, n)
|
||||
conf_file_free(*i);
|
||||
|
||||
free(array);
|
||||
}
|
||||
|
||||
static int prepare_dirs(const char *root, char * const *dirs, int *ret_rfd, char **ret_root, 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_dirs || strv_isempty(dirs));
|
||||
|
||||
r = empty_or_root_harder_to_null(&root);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to determine if '%s' points to the root directory: %m", strempty(root));
|
||||
|
||||
if (ret_dirs) {
|
||||
dirs_abs = strv_copy(dirs);
|
||||
if (!dirs_abs)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
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. */
|
||||
r = path_make_absolute_cwd(root, &root_abs);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to make '%s' absolute: %m", root);
|
||||
|
||||
path_simplify(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. */
|
||||
r = path_strv_make_absolute_cwd(dirs_abs);
|
||||
if (r < 0)
|
||||
return log_debug_errno(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_debug_errno(errno, "Failed to open '%s': %m", empty_to_root(root_abs));
|
||||
|
||||
*ret_rfd = TAKE_FD(rfd);
|
||||
*ret_root = TAKE_PTR(root_abs);
|
||||
if (ret_dirs)
|
||||
*ret_dirs = TAKE_PTR(dirs_abs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int conf_file_prefix_root(ConfFile *c, const char *root) {
|
||||
char *p;
|
||||
int r;
|
||||
|
||||
assert(c);
|
||||
|
||||
r = chaseat_prefix_root(c->result, root, &p);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to prefix '%s' with root '%s': %m", c->result, root);
|
||||
free_and_replace(c->result, p);
|
||||
|
||||
r = chaseat_prefix_root(c->resolved_path, root, &p);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to prefix '%s' with root '%s': %m", c->resolved_path, root);
|
||||
free_and_replace(c->resolved_path, p);
|
||||
|
||||
/* Do not use chaseat_prefix_root(), as it is for the result of chaseat(), but the path is not chased. */
|
||||
p = path_join(empty_to_root(root), skip_leading_slash(c->original_path));
|
||||
if (!p)
|
||||
return log_oom_debug();
|
||||
path_simplify(p);
|
||||
free_and_replace(c->original_path, p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int conf_file_new_at(const char *path, int rfd, ChaseFlags chase_flags, ConfFile **ret) {
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
assert(rfd >= 0 || rfd == AT_FDCWD);
|
||||
assert(ret);
|
||||
|
||||
_cleanup_free_ char *root = NULL;
|
||||
if (rfd >= 0 && DEBUG_LOGGING)
|
||||
(void) fd_get_path(rfd, &root);
|
||||
|
||||
_cleanup_(conf_file_freep) ConfFile *c = new(ConfFile, 1);
|
||||
if (!c)
|
||||
return log_oom_debug();
|
||||
|
||||
*c = (ConfFile) {
|
||||
.original_path = strdup(path),
|
||||
.fd = -EBADF,
|
||||
};
|
||||
|
||||
if (!c->original_path)
|
||||
return log_oom_debug();
|
||||
|
||||
r = path_extract_filename(path, &c->name);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to extract filename from '%s': %m", path);
|
||||
|
||||
_cleanup_free_ char *dirpath = NULL, *resolved_dirpath = NULL;
|
||||
r = path_extract_directory(path, &dirpath);
|
||||
if (r < 0 && r != -EDESTADDRREQ)
|
||||
return log_debug_errno(r, "Failed to extract directory from '%s': %m", path);
|
||||
if (r >= 0) {
|
||||
r = chaseat(rfd, dirpath,
|
||||
CHASE_AT_RESOLVE_IN_ROOT | (FLAGS_SET(chase_flags, CHASE_NONEXISTENT) ? CHASE_NONEXISTENT : CHASE_MUST_BE_DIRECTORY),
|
||||
&resolved_dirpath, /* ret_fd = */ NULL);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to chase '%s%s': %m", empty_to_root(root), skip_leading_slash(dirpath));
|
||||
}
|
||||
|
||||
c->result = path_join(resolved_dirpath, c->name);
|
||||
if (!c->result)
|
||||
return log_oom_debug();
|
||||
|
||||
r = chaseat(rfd, c->result, CHASE_AT_RESOLVE_IN_ROOT | chase_flags, &c->resolved_path, &c->fd);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to chase '%s%s': %m", empty_to_root(root), skip_leading_slash(c->original_path));
|
||||
|
||||
if (c->fd >= 0 && fstat(c->fd, &c->st) < 0)
|
||||
return log_debug_errno(r, "Failed to stat '%s%s': %m", empty_to_root(root), skip_leading_slash(c->resolved_path));
|
||||
|
||||
*ret = TAKE_PTR(c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int conf_file_new(const char *path, const char *root, ChaseFlags chase_flags, ConfFile **ret) {
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
assert((chase_flags & (CHASE_PREFIX_ROOT | CHASE_STEP)) == 0);
|
||||
assert(ret);
|
||||
|
||||
_cleanup_free_ char *root_abs = NULL;
|
||||
_cleanup_close_ int rfd = -EBADF;
|
||||
r = prepare_dirs(root, /* dirs = */ NULL, &rfd, &root_abs, /* ret_dirs = */ NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_free_ char *path_abs = NULL;
|
||||
if (!root_abs) {
|
||||
r = path_make_absolute_cwd(path, &path_abs);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to make '%s' absolute: %m", path);
|
||||
|
||||
path = path_abs;
|
||||
}
|
||||
|
||||
_cleanup_(conf_file_freep) ConfFile *c = NULL;
|
||||
r = conf_file_new_at(path, rfd, chase_flags, &c);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = conf_file_prefix_root(c, root_abs);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = TAKE_PTR(c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int files_add(
|
||||
DIR *dir,
|
||||
const char *dirpath,
|
||||
@@ -332,49 +513,6 @@ static int conf_files_list_impl(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int prepare_dirs(const char *root, char * const *dirs, int *ret_rfd, char **ret_root, 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_dirs);
|
||||
|
||||
r = empty_or_root_harder_to_null(&root);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to determine if '%s' points to the root directory: %m", strempty(root));
|
||||
|
||||
dirs_abs = strv_copy(dirs);
|
||||
if (!dirs_abs)
|
||||
return log_oom();
|
||||
|
||||
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. */
|
||||
r = path_make_absolute_cwd(root, &root_abs);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to make '%s' absolute: %m", root);
|
||||
|
||||
path_simplify(root_abs);
|
||||
} else {
|
||||
/* When an empty root or "/" is specified, we will open "/" below, hence we need to make
|
||||
* each config directory absolute if relative. */
|
||||
r = path_strv_make_absolute_cwd(dirs_abs);
|
||||
if (r < 0)
|
||||
return log_debug_errno(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_debug_errno(errno, "Failed to open '%s': %m", empty_to_root(root_abs));
|
||||
|
||||
*ret_rfd = TAKE_FD(rfd);
|
||||
*ret_root = TAKE_PTR(root_abs);
|
||||
*ret_dirs = TAKE_PTR(dirs_abs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int conf_files_list_strv(
|
||||
char ***ret,
|
||||
const char *suffix,
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "forward.h"
|
||||
|
||||
typedef enum ConfFilesFlags {
|
||||
@@ -13,6 +15,22 @@ typedef enum ConfFilesFlags {
|
||||
CONF_FILES_FILTER_MASKED = CONF_FILES_FILTER_MASKED_BY_SYMLINK | CONF_FILES_FILTER_MASKED_BY_EMPTY,
|
||||
} 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 */
|
||||
struct stat st; /* stat of the file. */
|
||||
} ConfFile;
|
||||
|
||||
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, ChaseFlags chase_flags, ConfFile **ret);
|
||||
int conf_file_new(const char *path, const char *root, ChaseFlags chase_flags, ConfFile **ret);
|
||||
|
||||
int conf_files_list(char ***ret, const char *suffix, const char *root, ConfFilesFlags flags, const char *dir);
|
||||
int conf_files_list_at(char ***ret, const char *suffix, int rfd, ConfFilesFlags flags, const char *dir);
|
||||
int conf_files_list_strv(char ***ret, const char *suffix, const char *root, ConfFilesFlags flags, const char* const* dirs);
|
||||
|
||||
@@ -104,6 +104,7 @@ typedef struct Set Set;
|
||||
|
||||
typedef struct dual_timestamp dual_timestamp;
|
||||
typedef struct triple_timestamp triple_timestamp;
|
||||
typedef struct ConfFile ConfFile;
|
||||
typedef struct LockFile LockFile;
|
||||
typedef struct PidRef PidRef;
|
||||
typedef struct Prioq Prioq;
|
||||
|
||||
Reference in New Issue
Block a user