diff options
author | Lennart Poettering <lennart@poettering.net> | 2021-05-03 18:18:09 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2021-05-07 16:43:26 +0200 |
commit | 2708160ccda8727de80442cbf634489a360ca001 (patch) | |
tree | 2c9e2d90210a41fdcf77c3ca4b01173af306768c /src | |
parent | ac2c088939de5aba5a06bee00dbc6c89a2809534 (diff) | |
download | systemd-2708160ccda8727de80442cbf634489a360ca001.tar.gz |
fileio: optionally, return discovered path of file in search_and_fopen()
Diffstat (limited to 'src')
-rw-r--r-- | src/basic/fileio.c | 88 | ||||
-rw-r--r-- | src/basic/fileio.h | 4 | ||||
-rw-r--r-- | src/binfmt/binfmt.c | 7 | ||||
-rw-r--r-- | src/home/homed-manager.c | 2 | ||||
-rw-r--r-- | src/modules-load/modules-load.c | 7 | ||||
-rw-r--r-- | src/sysctl/sysctl.c | 11 | ||||
-rw-r--r-- | src/sysusers/sysusers.c | 4 | ||||
-rw-r--r-- | src/test/test-fileio.c | 87 | ||||
-rw-r--r-- | src/tmpfiles/tmpfiles.c | 7 |
9 files changed, 146 insertions, 71 deletions
diff --git a/src/basic/fileio.c b/src/basic/fileio.c index 414fd15d56..16cd2408f0 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -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( diff --git a/src/basic/fileio.h b/src/basic/fileio.h index 752995c2a3..d772b0a50d 100644 --- a/src/basic/fileio.h +++ b/src/basic/fileio.h @@ -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, diff --git a/src/binfmt/binfmt.c b/src/binfmt/binfmt.c index f6b72e0bae..29530bb691 100644 --- a/src/binfmt/binfmt.c +++ b/src/binfmt/binfmt.c @@ -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; diff --git a/src/home/homed-manager.c b/src/home/homed-manager.c index bd104f6811..f8dfa272b9 100644 --- a/src/home/homed-manager.c +++ b/src/home/homed-manager.c @@ -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) diff --git a/src/modules-load/modules-load.c b/src/modules-load/modules-load.c index 9cfd292011..b57d806fab 100644 --- a/src/modules-load/modules-load.c +++ b/src/modules-load/modules-load.c @@ -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; diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c index 15b68b7d2e..458a91be29 100644 --- a/src/sysctl/sysctl.c +++ b/src/sysctl/sysctl.c @@ -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)); } diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c index 35ae3ae4af..848e5e867c 100644 --- a/src/sysusers/sysusers.c +++ b/src/sysusers/sysusers.c @@ -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 (;;) { diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c index c5c8116e96..4d2895c847 100644 --- a/src/test/test-fileio.c +++ b/src/test/test-fileio.c @@ -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) { diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 98f14bbbe7..9529b09b3f 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -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; } |