mirror of
https://github.com/systemd/systemd
synced 2024-10-06 16:21:34 +00:00
fileio: optionally, return discovered path of file in search_and_fopen()
This commit is contained in:
parent
ac2c088939
commit
2708160ccd
|
@ -914,12 +914,19 @@ int xfopenat(int dir_fd, const char *path, const char *mode, int flags, FILE **r
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int search_and_fopen_internal(const char *path, const char *mode, const char *root, char **search, FILE **_f) {
|
||||
static int search_and_fopen_internal(
|
||||
const char *path,
|
||||
const char *mode,
|
||||
const char *root,
|
||||
char **search,
|
||||
FILE **ret,
|
||||
char **ret_path) {
|
||||
|
||||
char **i;
|
||||
|
||||
assert(path);
|
||||
assert(mode);
|
||||
assert(_f);
|
||||
assert(ret);
|
||||
|
||||
if (!path_strv_resolve_uniq(search, root))
|
||||
return -ENOMEM;
|
||||
|
@ -934,7 +941,10 @@ static int search_and_fopen_internal(const char *path, const char *mode, const c
|
|||
|
||||
f = fopen(p, mode);
|
||||
if (f) {
|
||||
*_f = f;
|
||||
if (ret_path)
|
||||
*ret_path = path_simplify(TAKE_PTR(p), true);
|
||||
|
||||
*ret = f;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -945,52 +955,84 @@ static int search_and_fopen_internal(const char *path, const char *mode, const c
|
|||
return -ENOENT;
|
||||
}
|
||||
|
||||
int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f) {
|
||||
int search_and_fopen(
|
||||
const char *filename,
|
||||
const char *mode,
|
||||
const char *root,
|
||||
const char **search,
|
||||
FILE **ret,
|
||||
char **ret_path) {
|
||||
|
||||
_cleanup_strv_free_ char **copy = NULL;
|
||||
|
||||
assert(path);
|
||||
assert(filename);
|
||||
assert(mode);
|
||||
assert(_f);
|
||||
assert(ret);
|
||||
|
||||
if (path_is_absolute(path)) {
|
||||
FILE *f;
|
||||
if (path_is_absolute(filename)) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
|
||||
f = fopen(path, mode);
|
||||
if (f) {
|
||||
*_f = f;
|
||||
return 0;
|
||||
f = fopen(filename, mode);
|
||||
if (!f)
|
||||
return -errno;
|
||||
|
||||
if (ret_path) {
|
||||
char *p;
|
||||
|
||||
p = strdup(filename);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
*ret_path = path_simplify(p, true);
|
||||
}
|
||||
|
||||
return -errno;
|
||||
*ret = TAKE_PTR(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
copy = strv_copy((char**) search);
|
||||
if (!copy)
|
||||
return -ENOMEM;
|
||||
|
||||
return search_and_fopen_internal(path, mode, root, copy, _f);
|
||||
return search_and_fopen_internal(filename, mode, root, copy, ret, ret_path);
|
||||
}
|
||||
|
||||
int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f) {
|
||||
int search_and_fopen_nulstr(
|
||||
const char *filename,
|
||||
const char *mode,
|
||||
const char *root,
|
||||
const char *search,
|
||||
FILE **ret,
|
||||
char **ret_path) {
|
||||
|
||||
_cleanup_strv_free_ char **s = NULL;
|
||||
|
||||
if (path_is_absolute(path)) {
|
||||
FILE *f;
|
||||
if (path_is_absolute(filename)) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
|
||||
f = fopen(path, mode);
|
||||
if (f) {
|
||||
*_f = f;
|
||||
return 0;
|
||||
f = fopen(filename, mode);
|
||||
if (!f)
|
||||
return -errno;
|
||||
|
||||
if (ret_path) {
|
||||
char *p;
|
||||
|
||||
p = strdup(filename);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
*ret_path = path_simplify(p, true);
|
||||
}
|
||||
|
||||
return -errno;
|
||||
*ret = TAKE_PTR(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s = strv_split_nulstr(search);
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
return search_and_fopen_internal(path, mode, root, s, _f);
|
||||
return search_and_fopen_internal(filename, mode, root, s, ret, ret_path);
|
||||
}
|
||||
|
||||
int chase_symlinks_and_fopen_unlocked(
|
||||
|
|
|
@ -80,8 +80,8 @@ int get_proc_field(const char *filename, const char *pattern, const char *termin
|
|||
DIR *xopendirat(int dirfd, const char *name, int flags);
|
||||
int xfopenat(int dir_fd, const char *path, const char *mode, int flags, FILE **ret);
|
||||
|
||||
int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f);
|
||||
int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f);
|
||||
int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **ret, char **ret_path);
|
||||
int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **ret, char **ret_path);
|
||||
|
||||
int chase_symlinks_and_fopen_unlocked(
|
||||
const char *path,
|
||||
|
|
|
@ -65,11 +65,12 @@ static int apply_rule(const char *rule) {
|
|||
|
||||
static int apply_file(const char *path, bool ignore_enoent) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
_cleanup_free_ char *pp = NULL;
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
|
||||
r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("binfmt.d"), &f);
|
||||
r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("binfmt.d"), &f, &pp);
|
||||
if (r < 0) {
|
||||
if (ignore_enoent && r == -ENOENT)
|
||||
return 0;
|
||||
|
@ -77,7 +78,7 @@ static int apply_file(const char *path, bool ignore_enoent) {
|
|||
return log_error_errno(r, "Failed to open file '%s': %m", path);
|
||||
}
|
||||
|
||||
log_debug("apply: %s", path);
|
||||
log_debug("apply: %s", pp);
|
||||
for (;;) {
|
||||
_cleanup_free_ char *line = NULL;
|
||||
char *p;
|
||||
|
@ -85,7 +86,7 @@ static int apply_file(const char *path, bool ignore_enoent) {
|
|||
|
||||
k = read_line(f, LONG_LINE_MAX, &line);
|
||||
if (k < 0)
|
||||
return log_error_errno(k, "Failed to read file '%s': %m", path);
|
||||
return log_error_errno(k, "Failed to read file '%s': %m", pp);
|
||||
if (k == 0)
|
||||
break;
|
||||
|
||||
|
|
|
@ -1327,7 +1327,7 @@ static int manager_load_key_pair(Manager *m) {
|
|||
m->private_key = NULL;
|
||||
}
|
||||
|
||||
r = search_and_fopen_nulstr("local.private", "re", NULL, KEY_PATHS_NULSTR, &f);
|
||||
r = search_and_fopen_nulstr("local.private", "re", NULL, KEY_PATHS_NULSTR, &f, NULL);
|
||||
if (r == -ENOENT)
|
||||
return 0;
|
||||
if (r < 0)
|
||||
|
|
|
@ -62,12 +62,13 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
|||
|
||||
static int apply_file(struct kmod_ctx *ctx, const char *path, bool ignore_enoent) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
_cleanup_free_ char *pp = NULL;
|
||||
int r;
|
||||
|
||||
assert(ctx);
|
||||
assert(path);
|
||||
|
||||
r = search_and_fopen_nulstr(path, "re", NULL, conf_file_dirs, &f);
|
||||
r = search_and_fopen_nulstr(path, "re", NULL, conf_file_dirs, &f, &pp);
|
||||
if (r < 0) {
|
||||
if (ignore_enoent && r == -ENOENT)
|
||||
return 0;
|
||||
|
@ -75,7 +76,7 @@ static int apply_file(struct kmod_ctx *ctx, const char *path, bool ignore_enoent
|
|||
return log_error_errno(r, "Failed to open %s: %m", path);
|
||||
}
|
||||
|
||||
log_debug("apply: %s", path);
|
||||
log_debug("apply: %s", pp);
|
||||
for (;;) {
|
||||
_cleanup_free_ char *line = NULL;
|
||||
char *l;
|
||||
|
@ -83,7 +84,7 @@ static int apply_file(struct kmod_ctx *ctx, const char *path, bool ignore_enoent
|
|||
|
||||
k = read_line(f, LONG_LINE_MAX, &line);
|
||||
if (k < 0)
|
||||
return log_error_errno(k, "Failed to read file '%s': %m", path);
|
||||
return log_error_errno(k, "Failed to read file '%s': %m", pp);
|
||||
if (k == 0)
|
||||
break;
|
||||
|
||||
|
|
|
@ -182,12 +182,13 @@ static int apply_all(OrderedHashmap *sysctl_options) {
|
|||
|
||||
static int parse_file(OrderedHashmap **sysctl_options, const char *path, bool ignore_enoent) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
_cleanup_free_ char *pp = NULL;
|
||||
unsigned c = 0;
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
|
||||
r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("sysctl.d"), &f);
|
||||
r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("sysctl.d"), &f, &pp);
|
||||
if (r < 0) {
|
||||
if (ignore_enoent && r == -ENOENT)
|
||||
return 0;
|
||||
|
@ -195,7 +196,7 @@ static int parse_file(OrderedHashmap **sysctl_options, const char *path, bool ig
|
|||
return log_error_errno(r, "Failed to open file '%s', ignoring: %m", path);
|
||||
}
|
||||
|
||||
log_debug("Parsing %s", path);
|
||||
log_debug("Parsing %s", pp);
|
||||
for (;;) {
|
||||
_cleanup_(option_freep) Option *new_option = NULL;
|
||||
_cleanup_free_ char *l = NULL;
|
||||
|
@ -208,7 +209,7 @@ static int parse_file(OrderedHashmap **sysctl_options, const char *path, bool ig
|
|||
if (k == 0)
|
||||
break;
|
||||
if (k < 0)
|
||||
return log_error_errno(k, "Failed to read file '%s', ignoring: %m", path);
|
||||
return log_error_errno(k, "Failed to read file '%s', ignoring: %m", pp);
|
||||
|
||||
c++;
|
||||
|
||||
|
@ -235,7 +236,7 @@ static int parse_file(OrderedHashmap **sysctl_options, const char *path, bool ig
|
|||
/* We have a "negative match" option. Let's continue with value==NULL. */
|
||||
p++;
|
||||
else {
|
||||
log_syntax(NULL, LOG_WARNING, path, c, 0,
|
||||
log_syntax(NULL, LOG_WARNING, pp, c, 0,
|
||||
"Line is not an assignment, ignoring: %s", p);
|
||||
if (r == 0)
|
||||
r = -EINVAL;
|
||||
|
@ -261,7 +262,7 @@ static int parse_file(OrderedHashmap **sysctl_options, const char *path, bool ig
|
|||
continue;
|
||||
}
|
||||
|
||||
log_debug("Overwriting earlier assignment of %s at '%s:%u'.", p, path, c);
|
||||
log_debug("Overwriting earlier assignment of %s at '%s:%u'.", p, pp, c);
|
||||
option_free(ordered_hashmap_remove(*sysctl_options, p));
|
||||
}
|
||||
|
||||
|
|
|
@ -1728,6 +1728,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
|
|||
|
||||
static int read_config_file(const char *fn, bool ignore_enoent) {
|
||||
_cleanup_fclose_ FILE *rf = NULL;
|
||||
_cleanup_free_ char *pp = NULL;
|
||||
FILE *f = NULL;
|
||||
unsigned v = 0;
|
||||
int r = 0;
|
||||
|
@ -1737,7 +1738,7 @@ static int read_config_file(const char *fn, bool ignore_enoent) {
|
|||
if (streq(fn, "-"))
|
||||
f = stdin;
|
||||
else {
|
||||
r = search_and_fopen(fn, "re", arg_root, (const char**) CONF_PATHS_STRV("sysusers.d"), &rf);
|
||||
r = search_and_fopen(fn, "re", arg_root, (const char**) CONF_PATHS_STRV("sysusers.d"), &rf, &pp);
|
||||
if (r < 0) {
|
||||
if (ignore_enoent && r == -ENOENT)
|
||||
return 0;
|
||||
|
@ -1746,6 +1747,7 @@ static int read_config_file(const char *fn, bool ignore_enoent) {
|
|||
}
|
||||
|
||||
f = rf;
|
||||
fn = pp;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "fs-util.h"
|
||||
#include "io-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "process-util.h"
|
||||
#include "random-util.h"
|
||||
#include "rm-rf.h"
|
||||
|
@ -525,69 +526,93 @@ static void test_load_env_file_pairs(void) {
|
|||
}
|
||||
|
||||
static void test_search_and_fopen(void) {
|
||||
const char *dirs[] = {"/tmp/foo/bar", "/tmp", NULL};
|
||||
|
||||
static const char* const dirs[] = {
|
||||
"/tmp/foo/bar",
|
||||
"/tmp",
|
||||
NULL
|
||||
};
|
||||
char name[] = "/tmp/test-search_and_fopen.XXXXXX";
|
||||
int fd, r;
|
||||
FILE *f;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
_cleanup_free_ char *p = NULL;
|
||||
_cleanup_close_ int fd = -1;
|
||||
const char *e;
|
||||
int r;
|
||||
|
||||
fd = mkostemp_safe(name);
|
||||
assert_se(fd >= 0);
|
||||
close(fd);
|
||||
fd = safe_close(fd);
|
||||
|
||||
r = search_and_fopen(basename(name), "r", NULL, dirs, &f);
|
||||
r = search_and_fopen(basename(name), "re", NULL, (const char**) dirs, &f, &p);
|
||||
assert_se(r >= 0);
|
||||
fclose(f);
|
||||
assert_se(e = path_startswith(p, "/tmp/"));
|
||||
assert_se(streq(basename(name), e));
|
||||
f = safe_fclose(f);
|
||||
p = mfree(p);
|
||||
|
||||
r = search_and_fopen(name, "r", NULL, dirs, &f);
|
||||
r = search_and_fopen(name, "re", NULL, (const char**) dirs, &f, &p);
|
||||
assert_se(r >= 0);
|
||||
fclose(f);
|
||||
assert_se(path_equal(name, p));
|
||||
f = safe_fclose(f);
|
||||
p = mfree(p);
|
||||
|
||||
r = search_and_fopen(basename(name), "r", "/", dirs, &f);
|
||||
r = search_and_fopen(basename(name), "re", "/", (const char**) dirs, &f, &p);
|
||||
assert_se(r >= 0);
|
||||
fclose(f);
|
||||
assert_se(e = path_startswith(p, "/tmp/"));
|
||||
assert_se(streq(basename(name), e));
|
||||
f = safe_fclose(f);
|
||||
p = mfree(p);
|
||||
|
||||
r = search_and_fopen("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f);
|
||||
assert_se(r < 0);
|
||||
r = search_and_fopen("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f);
|
||||
assert_se(r < 0);
|
||||
r = search_and_fopen("/a/file/which/does/not/exist/i/guess", "r", NULL, (const char**) dirs, &f, &p);
|
||||
assert_se(r == -ENOENT);
|
||||
r = search_and_fopen("afilewhichdoesnotexistiguess", "r", NULL, (const char**) dirs, &f, &p);
|
||||
assert_se(r == -ENOENT);
|
||||
|
||||
r = unlink(name);
|
||||
assert_se(r == 0);
|
||||
|
||||
r = search_and_fopen(basename(name), "r", NULL, dirs, &f);
|
||||
assert_se(r < 0);
|
||||
r = search_and_fopen(basename(name), "r", NULL, (const char**) dirs, &f, &p);
|
||||
assert_se(r == -ENOENT);
|
||||
}
|
||||
|
||||
static void test_search_and_fopen_nulstr(void) {
|
||||
const char dirs[] = "/tmp/foo/bar\0/tmp\0";
|
||||
static const char dirs[] =
|
||||
"/tmp/foo/bar\0"
|
||||
"/tmp\0";
|
||||
|
||||
_cleanup_(unlink_tempfilep) char name[] = "/tmp/test-search_and_fopen.XXXXXX";
|
||||
int fd, r;
|
||||
FILE *f;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
_cleanup_free_ char *p = NULL;
|
||||
_cleanup_close_ int fd = -1;
|
||||
const char *e;
|
||||
int r;
|
||||
|
||||
fd = mkostemp_safe(name);
|
||||
assert_se(fd >= 0);
|
||||
close(fd);
|
||||
fd = safe_close(fd);
|
||||
|
||||
r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f);
|
||||
r = search_and_fopen_nulstr(basename(name), "re", NULL, dirs, &f, &p);
|
||||
assert_se(r >= 0);
|
||||
fclose(f);
|
||||
assert_se(e = path_startswith(p, "/tmp/"));
|
||||
assert_se(streq(basename(name), e));
|
||||
f = safe_fclose(f);
|
||||
p = mfree(p);
|
||||
|
||||
r = search_and_fopen_nulstr(name, "r", NULL, dirs, &f);
|
||||
r = search_and_fopen_nulstr(name, "re", NULL, dirs, &f, &p);
|
||||
assert_se(r >= 0);
|
||||
fclose(f);
|
||||
assert_se(path_equal(name, p));
|
||||
f = safe_fclose(f);
|
||||
p = mfree(p);
|
||||
|
||||
r = search_and_fopen_nulstr("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f);
|
||||
assert_se(r < 0);
|
||||
r = search_and_fopen_nulstr("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f);
|
||||
assert_se(r < 0);
|
||||
r = search_and_fopen_nulstr("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f, &p);
|
||||
assert_se(r == -ENOENT);
|
||||
r = search_and_fopen_nulstr("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f, &p);
|
||||
assert_se(r == -ENOENT);
|
||||
|
||||
r = unlink(name);
|
||||
assert_se(r == 0);
|
||||
|
||||
r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f);
|
||||
assert_se(r < 0);
|
||||
r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f, &p);
|
||||
assert_se(r == -ENOENT);
|
||||
}
|
||||
|
||||
static void test_writing_tmpfile(void) {
|
||||
|
|
|
@ -3185,6 +3185,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
static int read_config_file(char **config_dirs, const char *fn, bool ignore_enoent, bool *invalid_config) {
|
||||
_cleanup_(hashmap_freep) Hashmap *uid_cache = NULL, *gid_cache = NULL;
|
||||
_cleanup_fclose_ FILE *_f = NULL;
|
||||
_cleanup_free_ char *pp = NULL;
|
||||
unsigned v = 0;
|
||||
FILE *f;
|
||||
ItemArray *ia;
|
||||
|
@ -3197,7 +3198,7 @@ static int read_config_file(char **config_dirs, const char *fn, bool ignore_enoe
|
|||
fn = "<stdin>";
|
||||
f = stdin;
|
||||
} else {
|
||||
r = search_and_fopen(fn, "re", arg_root, (const char**) config_dirs, &_f);
|
||||
r = search_and_fopen(fn, "re", arg_root, (const char**) config_dirs, &_f, &pp);
|
||||
if (r < 0) {
|
||||
if (ignore_enoent && r == -ENOENT) {
|
||||
log_debug_errno(r, "Failed to open \"%s\", ignoring: %m", fn);
|
||||
|
@ -3206,7 +3207,9 @@ static int read_config_file(char **config_dirs, const char *fn, bool ignore_enoe
|
|||
|
||||
return log_error_errno(r, "Failed to open '%s': %m", fn);
|
||||
}
|
||||
log_debug("Reading config file \"%s\"…", fn);
|
||||
|
||||
log_debug("Reading config file \"%s\"…", pp);
|
||||
fn = pp;
|
||||
f = _f;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue