fileio: revamp search_and_fopen()
Let's modernize and clean up search_and_fopen a bit: let's add support for regular open() (instead of fopen()), as well as access() (if caller just wants to check if a file exists without opening it. This unifies much of the code involved, which previously was duplicated in search_and_fopen() and search_and_fopen_nulstr()
This commit is contained in:
+112
-58
@@ -1076,117 +1076,171 @@ int fdopen_independent(int fd, const char *mode, FILE **ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int search_and_fopen_internal(
|
||||
static int search_and_open_internal(
|
||||
const char *path,
|
||||
const char *mode,
|
||||
int mode, /* if ret_fd is NULL this is an [FRWX]_OK mode for access(), otherwise an open mode for open() */
|
||||
const char *root,
|
||||
char **search,
|
||||
FILE **ret,
|
||||
int *ret_fd,
|
||||
char **ret_path) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(!ret_fd || !FLAGS_SET(mode, O_CREAT)); /* We don't support O_CREAT for this */
|
||||
assert(path);
|
||||
assert(mode);
|
||||
assert(ret);
|
||||
|
||||
if (path_is_absolute(path)) {
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
|
||||
if (ret_fd)
|
||||
/* We only specify 0777 here to appease static analyzers, it's never used since we
|
||||
* don't support O_CREAT here */
|
||||
r = fd = RET_NERRNO(open(path, mode, 0777));
|
||||
else
|
||||
r = RET_NERRNO(access(path, mode));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ret_path) {
|
||||
r = path_simplify_alloc(path, ret_path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (ret_fd)
|
||||
*ret_fd = TAKE_FD(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!path_strv_resolve_uniq(search, root))
|
||||
return -ENOMEM;
|
||||
|
||||
STRV_FOREACH(i, search) {
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
_cleanup_free_ char *p = NULL;
|
||||
FILE *f;
|
||||
|
||||
p = path_join(root, *i, path);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
f = fopen(p, mode);
|
||||
if (f) {
|
||||
if (ret_fd)
|
||||
/* as above, 0777 is static analyzer appeasement */
|
||||
r = fd = RET_NERRNO(open(p, mode, 0777));
|
||||
else
|
||||
r = RET_NERRNO(access(p, F_OK));
|
||||
if (r >= 0) {
|
||||
if (ret_path)
|
||||
*ret_path = path_simplify(TAKE_PTR(p));
|
||||
|
||||
*ret = f;
|
||||
if (ret_fd)
|
||||
*ret_fd = TAKE_FD(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (errno != ENOENT)
|
||||
return -errno;
|
||||
if (r != -ENOENT)
|
||||
return r;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
int search_and_fopen(
|
||||
const char *filename,
|
||||
const char *mode,
|
||||
int search_and_open(
|
||||
const char *path,
|
||||
int mode,
|
||||
const char *root,
|
||||
const char **search,
|
||||
FILE **ret,
|
||||
char **search,
|
||||
int *ret_fd,
|
||||
char **ret_path) {
|
||||
|
||||
_cleanup_strv_free_ char **copy = NULL;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(mode);
|
||||
assert(ret);
|
||||
|
||||
if (path_is_absolute(filename)) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
|
||||
f = fopen(filename, mode);
|
||||
if (!f)
|
||||
return -errno;
|
||||
|
||||
if (ret_path) {
|
||||
r = path_simplify_alloc(filename, ret_path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
*ret = TAKE_PTR(f);
|
||||
return 0;
|
||||
}
|
||||
assert(path);
|
||||
|
||||
copy = strv_copy((char**) search);
|
||||
if (!copy)
|
||||
return -ENOMEM;
|
||||
|
||||
return search_and_fopen_internal(filename, mode, root, copy, ret, ret_path);
|
||||
return search_and_open_internal(path, mode, root, copy, ret_fd, ret_path);
|
||||
}
|
||||
|
||||
int search_and_fopen_nulstr(
|
||||
const char *filename,
|
||||
static int search_and_fopen_internal(
|
||||
const char *path,
|
||||
const char *mode,
|
||||
const char *root,
|
||||
const char *search,
|
||||
FILE **ret,
|
||||
char **search,
|
||||
FILE **ret_file,
|
||||
char **ret_path) {
|
||||
|
||||
_cleanup_strv_free_ char **s = NULL;
|
||||
_cleanup_free_ char *found_path = NULL;
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
int r;
|
||||
|
||||
if (path_is_absolute(filename)) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
assert(path);
|
||||
assert(mode || !ret_file);
|
||||
|
||||
f = fopen(filename, mode);
|
||||
r = search_and_open(
|
||||
path,
|
||||
mode ? fopen_mode_to_flags(mode) : 0,
|
||||
root,
|
||||
search,
|
||||
ret_file ? &fd : NULL,
|
||||
ret_path ? &found_path : NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ret_file) {
|
||||
FILE *f = take_fdopen(&fd, mode);
|
||||
if (!f)
|
||||
return -errno;
|
||||
|
||||
if (ret_path) {
|
||||
r = path_simplify_alloc(filename, ret_path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
*ret = TAKE_PTR(f);
|
||||
return 0;
|
||||
*ret_file = f;
|
||||
}
|
||||
|
||||
s = strv_split_nulstr(search);
|
||||
if (!s)
|
||||
if (ret_path)
|
||||
*ret_path = TAKE_PTR(found_path);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int search_and_fopen(
|
||||
const char *path,
|
||||
const char *mode,
|
||||
const char *root,
|
||||
const char **search,
|
||||
FILE **ret_file,
|
||||
char **ret_path) {
|
||||
|
||||
_cleanup_strv_free_ char **copy = NULL;
|
||||
|
||||
assert(path);
|
||||
assert(mode || !ret_file);
|
||||
|
||||
copy = strv_copy((char**) search);
|
||||
if (!copy)
|
||||
return -ENOMEM;
|
||||
|
||||
return search_and_fopen_internal(filename, mode, root, s, ret, ret_path);
|
||||
return search_and_fopen_internal(path, mode, root, copy, ret_file, ret_path);
|
||||
}
|
||||
|
||||
int search_and_fopen_nulstr(
|
||||
const char *path,
|
||||
const char *mode,
|
||||
const char *root,
|
||||
const char *search,
|
||||
FILE **ret_file,
|
||||
char **ret_path) {
|
||||
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
|
||||
assert(path);
|
||||
assert(mode || !ret_file);
|
||||
|
||||
l = strv_split_nulstr(search);
|
||||
if (!l)
|
||||
return -ENOMEM;
|
||||
|
||||
return search_and_fopen_internal(path, mode, root, l, ret_file, ret_path);
|
||||
}
|
||||
|
||||
int fflush_and_check(FILE *f) {
|
||||
|
||||
+6
-2
@@ -129,8 +129,12 @@ static inline int fopen_unlocked(const char *path, const char *mode, FILE **ret)
|
||||
|
||||
int fdopen_independent(int fd, const char *mode, FILE **ret);
|
||||
|
||||
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 search_and_open(const char *path, int mode, const char *root, char **search, int *ret_fd, char **ret_path);
|
||||
static inline int search_and_access(const char *path, int mode, const char *root, char**search, char **ret_path) {
|
||||
return search_and_open(path, mode, root, search, NULL, ret_path);
|
||||
}
|
||||
int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **ret_file, char **ret_path);
|
||||
int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **ret_file, char **ret_path);
|
||||
|
||||
int fflush_and_check(FILE *f);
|
||||
int fflush_sync_and_check(FILE *f);
|
||||
|
||||
Reference in New Issue
Block a user