diff --git a/src/basic/chase-symlinks.c b/src/basic/chase-symlinks.c index dd3a217203b..344e7e1bb74 100644 --- a/src/basic/chase-symlinks.c +++ b/src/basic/chase-symlinks.c @@ -5,6 +5,7 @@ #include "alloc-util.h" #include "chase-symlinks.h" #include "fd-util.h" +#include "fileio.h" #include "fs-util.h" #include "glyph-util.h" #include "log.h" @@ -515,3 +516,37 @@ int chase_symlinks_and_stat( return 1; } + +int chase_symlinks_and_fopen_unlocked( + const char *path, + const char *root, + unsigned chase_flags, + const char *open_flags, + char **ret_path, + FILE **ret_file) { + + _cleanup_free_ char *final_path = NULL; + _cleanup_close_ int fd = -1; + int mode_flags, r; + + assert(path); + assert(open_flags); + assert(ret_file); + + mode_flags = fopen_mode_to_flags(open_flags); + if (mode_flags < 0) + return mode_flags; + + fd = chase_symlinks_and_open(path, root, chase_flags, mode_flags, ret_path ? &final_path : NULL); + if (fd < 0) + return fd; + + r = take_fdopen_unlocked(&fd, open_flags, ret_file); + if (r < 0) + return r; + + if (ret_path) + *ret_path = TAKE_PTR(final_path); + + return 0; +} diff --git a/src/basic/chase-symlinks.h b/src/basic/chase-symlinks.h index 7191a457687..e2b22fe0412 100644 --- a/src/basic/chase-symlinks.h +++ b/src/basic/chase-symlinks.h @@ -28,3 +28,5 @@ int chase_symlinks(const char *path_with_prefix, const char *root, unsigned flag int chase_symlinks_and_open(const char *path, const char *root, unsigned chase_flags, int open_flags, char **ret_path); int chase_symlinks_and_opendir(const char *path, const char *root, unsigned chase_flags, char **ret_path, DIR **ret_dir); int chase_symlinks_and_stat(const char *path, const char *root, unsigned chase_flags, char **ret_path, struct stat *ret_stat, int *ret_fd); + +int chase_symlinks_and_fopen_unlocked(const char *path, const char *root, unsigned chase_flags, const char *open_flags, char **ret_path, FILE **ret_file); diff --git a/src/basic/fileio.c b/src/basic/fileio.c index 4911ac7c6dc..cced1dd564b 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -941,10 +941,12 @@ DIR *xopendirat(int fd, const char *name, int flags) { return d; } -static int mode_to_flags(const char *mode) { +int fopen_mode_to_flags(const char *mode) { const char *p; int flags; + assert(mode); + if ((p = startswith(mode, "r+"))) flags = O_RDWR; else if ((p = startswith(mode, "r"))) @@ -997,7 +999,7 @@ int xfopenat(int dir_fd, const char *path, const char *mode, int flags, FILE **r } else { int fd, mode_flags; - mode_flags = mode_to_flags(mode); + mode_flags = fopen_mode_to_flags(mode); if (mode_flags < 0) return mode_flags; @@ -1137,39 +1139,6 @@ int search_and_fopen_nulstr( return search_and_fopen_internal(filename, mode, root, s, ret, ret_path); } -int chase_symlinks_and_fopen_unlocked( - const char *path, - const char *root, - unsigned chase_flags, - const char *open_flags, - FILE **ret_file, - char **ret_path) { - - _cleanup_close_ int fd = -1; - _cleanup_free_ char *final_path = NULL; - int mode_flags, r; - - assert(path); - assert(open_flags); - assert(ret_file); - - mode_flags = mode_to_flags(open_flags); - if (mode_flags < 0) - return mode_flags; - - fd = chase_symlinks_and_open(path, root, chase_flags, mode_flags, ret_path ? &final_path : NULL); - if (fd < 0) - return fd; - - r = take_fdopen_unlocked(&fd, open_flags, ret_file); - if (r < 0) - return r; - - if (ret_path) - *ret_path = TAKE_PTR(final_path); - return 0; -} - int fflush_and_check(FILE *f) { assert(f); diff --git a/src/basic/fileio.h b/src/basic/fileio.h index c25a6381046..899def946bd 100644 --- a/src/basic/fileio.h +++ b/src/basic/fileio.h @@ -91,14 +91,6 @@ int xfopenat(int dir_fd, const char *path, const char *mode, int flags, FILE **r 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, - const char *root, - unsigned chase_flags, - const char *open_flags, - FILE **ret_file, - char **ret_path); - int fflush_and_check(FILE *f); int fflush_sync_and_check(FILE *f); @@ -126,3 +118,5 @@ static inline int read_nul_string(FILE *f, size_t limit, char **ret) { int safe_fgetc(FILE *f, char *ret); int warn_file_is_world_accessible(const char *filename, struct stat *st, const char *unit, unsigned line); + +int fopen_mode_to_flags(const char *mode); diff --git a/src/nspawn/nspawn-bind-user.c b/src/nspawn/nspawn-bind-user.c index 0220d71c2b9..a5d866da959 100644 --- a/src/nspawn/nspawn-bind-user.c +++ b/src/nspawn/nspawn-bind-user.c @@ -24,7 +24,7 @@ static int check_etc_passwd_collisions( assert(directory); assert(name || uid_is_valid(uid)); - r = chase_symlinks_and_fopen_unlocked("/etc/passwd", directory, CHASE_PREFIX_ROOT, "re", &f, NULL); + r = chase_symlinks_and_fopen_unlocked("/etc/passwd", directory, CHASE_PREFIX_ROOT, "re", NULL, &f); if (r == -ENOENT) return 0; /* no user database? then no user, hence no collision */ if (r < 0) @@ -57,7 +57,7 @@ static int check_etc_group_collisions( assert(directory); assert(name || gid_is_valid(gid)); - r = chase_symlinks_and_fopen_unlocked("/etc/group", directory, CHASE_PREFIX_ROOT, "re", &f, NULL); + r = chase_symlinks_and_fopen_unlocked("/etc/group", directory, CHASE_PREFIX_ROOT, "re", NULL, &f); if (r == -ENOENT) return 0; /* no group database? then no group, hence no collision */ if (r < 0) diff --git a/src/shared/user-record.c b/src/shared/user-record.c index f34a48b6567..fd6b37b9083 100644 --- a/src/shared/user-record.c +++ b/src/shared/user-record.c @@ -55,7 +55,7 @@ int read_login_defs(UGIDAllocationRange *ret_defs, const char *path, const char if (!path) path = "/etc/login.defs"; - r = chase_symlinks_and_fopen_unlocked(path, root, CHASE_PREFIX_ROOT, "re", &f, NULL); + r = chase_symlinks_and_fopen_unlocked(path, root, CHASE_PREFIX_ROOT, "re", NULL, &f); if (r == -ENOENT) goto assign; if (r < 0)