chase-symlinks: Add more chase_symlinks_at() helpers
Copies of the corresponding chase_symlinks() helpers.
This commit is contained in:
@@ -829,3 +829,180 @@ int chase_symlinks_at_and_open(
|
||||
return r;
|
||||
}
|
||||
|
||||
int chase_symlinks_at_and_opendir(
|
||||
int dir_fd,
|
||||
const char *path,
|
||||
ChaseSymlinksFlags chase_flags,
|
||||
char **ret_path,
|
||||
DIR **ret_dir) {
|
||||
|
||||
_cleanup_close_ int path_fd = -EBADF;
|
||||
_cleanup_free_ char *p = NULL;
|
||||
DIR *d;
|
||||
int r;
|
||||
|
||||
assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP)));
|
||||
assert(ret_dir);
|
||||
|
||||
if (dir_fd == AT_FDCWD && !ret_path &&
|
||||
(chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_PROHIBIT_SYMLINKS|CHASE_PARENT|CHASE_MKDIR_0755)) == 0) {
|
||||
/* Shortcut this call if none of the special features of this call are requested */
|
||||
d = opendir(path);
|
||||
if (!d)
|
||||
return -errno;
|
||||
|
||||
*ret_dir = d;
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = chase_symlinks_at(dir_fd, path, chase_flags, ret_path ? &p : NULL, &path_fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
assert(path_fd >= 0);
|
||||
|
||||
d = xopendirat(path_fd, ".", O_NOFOLLOW);
|
||||
if (!d)
|
||||
return -errno;
|
||||
|
||||
if (ret_path)
|
||||
*ret_path = TAKE_PTR(p);
|
||||
|
||||
*ret_dir = d;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int chase_symlinks_at_and_stat(
|
||||
int dir_fd,
|
||||
const char *path,
|
||||
ChaseSymlinksFlags chase_flags,
|
||||
char **ret_path,
|
||||
struct stat *ret_stat) {
|
||||
|
||||
_cleanup_close_ int path_fd = -EBADF;
|
||||
_cleanup_free_ char *p = NULL;
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP)));
|
||||
assert(ret_stat);
|
||||
|
||||
if (dir_fd == AT_FDCWD && !ret_path &&
|
||||
(chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_PROHIBIT_SYMLINKS|CHASE_PARENT|CHASE_MKDIR_0755)) == 0)
|
||||
/* Shortcut this call if none of the special features of this call are requested */
|
||||
return RET_NERRNO(fstatat(AT_FDCWD, path, ret_stat,
|
||||
FLAGS_SET(chase_flags, CHASE_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0));
|
||||
|
||||
r = chase_symlinks_at(dir_fd, path, chase_flags, ret_path ? &p : NULL, &path_fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
assert(path_fd >= 0);
|
||||
|
||||
if (fstat(path_fd, ret_stat) < 0)
|
||||
return -errno;
|
||||
|
||||
if (ret_path)
|
||||
*ret_path = TAKE_PTR(p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int chase_symlinks_at_and_access(
|
||||
int dir_fd,
|
||||
const char *path,
|
||||
ChaseSymlinksFlags chase_flags,
|
||||
int access_mode,
|
||||
char **ret_path) {
|
||||
|
||||
_cleanup_close_ int path_fd = -EBADF;
|
||||
_cleanup_free_ char *p = NULL;
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP)));
|
||||
|
||||
if (dir_fd == AT_FDCWD && !ret_path &&
|
||||
(chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_PROHIBIT_SYMLINKS|CHASE_PARENT|CHASE_MKDIR_0755)) == 0)
|
||||
/* Shortcut this call if none of the special features of this call are requested */
|
||||
return RET_NERRNO(faccessat(AT_FDCWD, path, access_mode,
|
||||
FLAGS_SET(chase_flags, CHASE_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0));
|
||||
|
||||
r = chase_symlinks_at(dir_fd, path, chase_flags, ret_path ? &p : NULL, &path_fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
assert(path_fd >= 0);
|
||||
|
||||
r = access_fd(path_fd, access_mode);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ret_path)
|
||||
*ret_path = TAKE_PTR(p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int chase_symlinks_at_and_fopen_unlocked(
|
||||
int dir_fd,
|
||||
const char *path,
|
||||
ChaseSymlinksFlags chase_flags,
|
||||
const char *open_flags,
|
||||
char **ret_path,
|
||||
FILE **ret_file) {
|
||||
|
||||
_cleanup_free_ char *final_path = NULL;
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
int mode_flags, r;
|
||||
|
||||
assert(path);
|
||||
assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP|CHASE_PARENT)));
|
||||
assert(open_flags);
|
||||
assert(ret_file);
|
||||
|
||||
mode_flags = fopen_mode_to_flags(open_flags);
|
||||
if (mode_flags < 0)
|
||||
return mode_flags;
|
||||
|
||||
fd = chase_symlinks_at_and_open(dir_fd, path, 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 chase_symlinks_at_and_unlink(
|
||||
int dir_fd,
|
||||
const char *path,
|
||||
ChaseSymlinksFlags chase_flags,
|
||||
int unlink_flags,
|
||||
char **ret_path) {
|
||||
|
||||
_cleanup_free_ char *p = NULL, *fname = NULL;
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP|CHASE_PARENT)));
|
||||
|
||||
fd = chase_symlinks_at_and_open(dir_fd, path, chase_flags|CHASE_PARENT|CHASE_NOFOLLOW, O_PATH|O_DIRECTORY|O_CLOEXEC, &p);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
r = path_extract_filename(p, &fname);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (unlinkat(fd, fname, unlink_flags) < 0)
|
||||
return -errno;
|
||||
|
||||
if (ret_path)
|
||||
*ret_path = TAKE_PTR(p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -42,4 +42,10 @@ int chase_symlinks_and_fopen_unlocked(const char *path, const char *root, ChaseS
|
||||
int chase_symlinks_and_unlink(const char *path, const char *root, ChaseSymlinksFlags chase_flags, int unlink_flags, char **ret_path);
|
||||
|
||||
int chase_symlinks_at(int dir_fd, const char *path, ChaseSymlinksFlags flags, char **ret_path, int *ret_fd);
|
||||
|
||||
int chase_symlinks_at_and_open(int dir_fd, const char *path, ChaseSymlinksFlags chase_flags, int open_flags, char **ret_path);
|
||||
int chase_symlinks_at_and_opendir(int dir_fd, const char *path, ChaseSymlinksFlags chase_flags, char **ret_path, DIR **ret_dir);
|
||||
int chase_symlinks_at_and_stat(int dir_fd, const char *path, ChaseSymlinksFlags chase_flags, char **ret_path, struct stat *ret_stat);
|
||||
int chase_symlinks_at_and_access(int dir_fd, const char *path, ChaseSymlinksFlags chase_flags, int access_mode, char **ret_path);
|
||||
int chase_symlinks_at_and_fopen_unlocked(int dir_fd, const char *path, ChaseSymlinksFlags chase_flags, const char *open_flags, char **ret_path, FILE **ret_file);
|
||||
int chase_symlinks_at_and_unlink(int dir_fd, const char *path, ChaseSymlinksFlags chase_flags, int unlink_flags, char **ret_path);
|
||||
|
||||
Reference in New Issue
Block a user