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);
+ assert(path);
- if (path_is_absolute(filename)) {
- _cleanup_fclose_ FILE *f = NULL;
+ copy = strv_copy((char**) search);
+ if (!copy)
+ return -ENOMEM;
- f = fopen(filename, mode);
+ return search_and_open_internal(path, mode, root, copy, ret_fd, ret_path);
+}
+
+static int search_and_fopen_internal(
+ const char *path,
+ const char *mode,
+ const char *root,
+ char **search,
+ FILE **ret_file,
+ char **ret_path) {
+
+ _cleanup_free_ char *found_path = NULL;
+ _cleanup_close_ int fd = -EBADF;
+ int r;
+
+ assert(path);
+ assert(mode || !ret_file);
+
+ 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;
}
+ 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, copy, ret, ret_path);
+ return search_and_fopen_internal(path, mode, root, copy, ret_file, ret_path);
}
int search_and_fopen_nulstr(
- const char *filename,
+ const char *path,
const char *mode,
const char *root,
const char *search,
- FILE **ret,
+ FILE **ret_file,
char **ret_path) {
- _cleanup_strv_free_ char **s = NULL;
- int r;
-
- if (path_is_absolute(filename)) {
- _cleanup_fclose_ FILE *f = NULL;
+ _cleanup_strv_free_ char **l = 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);
+ assert(mode || !ret_file);
- s = strv_split_nulstr(search);
- if (!s)
+ l = strv_split_nulstr(search);
+ if (!l)
return -ENOMEM;
- return search_and_fopen_internal(filename, mode, root, s, ret, ret_path);
+ return search_and_fopen_internal(path, mode, root, l, ret_file, ret_path);
}
int fflush_and_check(FILE *f) {
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);
f = safe_fclose(f);
p = mfree(p);
+ r = search_and_fopen(basename(name), NULL, NULL, (const char**) dirs, NULL, &p);
+ assert_se(r >= 0);
+ assert_se(e = path_startswith(p, "/tmp/"));
+ assert_se(streq(basename(name), e));
+ p = mfree(p);
+
r = search_and_fopen(name, "re", NULL, (const char**) dirs, &f, &p);
assert_se(r >= 0);
assert_se(path_equal(name, p));
f = safe_fclose(f);
p = mfree(p);
+ r = search_and_fopen(name, NULL, NULL, (const char**) dirs, NULL, &p);
+ assert_se(r >= 0);
+ assert_se(path_equal(name, p));
+ p = mfree(p);
+
r = search_and_fopen(basename(name), "re", "/", (const char**) dirs, &f, &p);
assert_se(r >= 0);
assert_se(e = path_startswith(p, "/tmp/"));
f = safe_fclose(f);
p = mfree(p);
+ r = search_and_fopen(basename(name), NULL, "/", (const char**) dirs, NULL, &p);
+ assert_se(r >= 0);
+ assert_se(e = path_startswith(p, "/tmp/"));
+ assert_se(streq(basename(name), e));
+ p = mfree(p);
+
r = search_and_fopen("/a/file/which/does/not/exist/i/guess", "re", NULL, (const char**) dirs, &f, &p);
assert_se(r == -ENOENT);
+ r = search_and_fopen("/a/file/which/does/not/exist/i/guess", NULL, NULL, (const char**) dirs, NULL, &p);
+ assert_se(r == -ENOENT);
r = search_and_fopen("afilewhichdoesnotexistiguess", "re", NULL, (const char**) dirs, &f, &p);
assert_se(r == -ENOENT);
+ r = search_and_fopen("afilewhichdoesnotexistiguess", NULL, NULL, (const char**) dirs, NULL, &p);
+ assert_se(r == -ENOENT);
r = unlink(name);
assert_se(r == 0);
r = search_and_fopen(basename(name), "re", NULL, (const char**) dirs, &f, &p);
assert_se(r == -ENOENT);
+ r = search_and_fopen(basename(name), NULL, NULL, (const char**) dirs, NULL, &p);
+ assert_se(r == -ENOENT);
}
TEST(search_and_fopen_nulstr) {