From: Christian Brauner Date: Mon, 1 Feb 2021 10:11:15 +0000 (+0100) Subject: file_utils: add fdopenat() X-Git-Tag: lxc-5.0.0~309^2~10 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a60d8c4ea7e77897e79fe91421490a55bb850ea1;p=thirdparty%2Flxc.git file_utils: add fdopenat() Signed-off-by: Christian Brauner --- diff --git a/src/lxc/file_utils.c b/src/lxc/file_utils.c index 02856153a..5e88cf893 100644 --- a/src/lxc/file_utils.c +++ b/src/lxc/file_utils.c @@ -517,6 +517,64 @@ FILE *fdopen_cached(int fd, const char *mode, void **caller_freed_buffer) return f; } +int fd_cloexec(int fd, bool cloexec) +{ + int oflags, nflags; + + oflags = fcntl(fd, F_GETFD, 0); + if (oflags < 0) + return -errno; + + if (cloexec) + nflags = oflags | FD_CLOEXEC; + else + nflags = oflags & ~FD_CLOEXEC; + + if (nflags == oflags) + return 0; + + if (fcntl(fd, F_SETFD, nflags) < 0) + return -errno; + + return 0; +} + +static inline int dup_cloexec(int fd) +{ + __do_close int fd_dup = -EBADF; + + fd_dup = dup(fd); + if (fd_dup < 0) + return -errno; + + if (fd_cloexec(fd_dup, true)) + return -errno; + + return move_fd(fd_dup); +} + +FILE *fdopenat(int dfd, const char *path, const char *mode) +{ + __do_close int fd = -EBADF; + __do_fclose FILE *f = NULL; + + if (is_empty_string(path)) + fd = dup_cloexec(dfd); + else + fd = openat(dfd, path, O_CLOEXEC | O_NOCTTY | O_NOFOLLOW); + if (fd < 0) + return NULL; + + f = fdopen(fd, "re"); + if (!f) + return NULL; + + /* Transfer ownership of fd. */ + move_fd(fd); + + return move_ptr(f); +} + int timens_offset_write(clockid_t clk_id, int64_t s_offset, int64_t ns_offset) { __do_close int fd = -EBADF; diff --git a/src/lxc/file_utils.h b/src/lxc/file_utils.h index 7652b09ff..2091f7e49 100644 --- a/src/lxc/file_utils.h +++ b/src/lxc/file_utils.h @@ -73,8 +73,10 @@ static inline int fd_to_fd(int from, int to) { return __fd_to_fd(from, to) >= 0; } +__hidden extern int fd_cloexec(int fd, bool cloexec); __hidden extern int lxc_open_dirfd(const char *dir); __hidden extern FILE *fdopen_cached(int fd, const char *mode, void **caller_freed_buffer); +__hidden extern FILE *fdopenat(int dfd, const char *path, const char *mode); __hidden extern FILE *fopen_cached(const char *path, const char *mode, void **caller_freed_buffer); __hidden extern int timens_offset_write(clockid_t clk_id, int64_t s_offset, int64_t ns_offset); __hidden extern bool exists_dir_at(int dir_fd, const char *path); diff --git a/src/lxc/utils.c b/src/lxc/utils.c index bb7074cca..ad2d6eea0 100644 --- a/src/lxc/utils.c +++ b/src/lxc/utils.c @@ -1779,28 +1779,6 @@ int lxc_set_death_signal(int signal, pid_t parent, int parent_status_fd) return 0; } -int fd_cloexec(int fd, bool cloexec) -{ - int oflags, nflags; - - oflags = fcntl(fd, F_GETFD, 0); - if (oflags < 0) - return -errno; - - if (cloexec) - nflags = oflags | FD_CLOEXEC; - else - nflags = oflags & ~FD_CLOEXEC; - - if (nflags == oflags) - return 0; - - if (fcntl(fd, F_SETFD, nflags) < 0) - return -errno; - - return 0; -} - int lxc_rm_rf(const char *dirname) { __do_closedir DIR *dir = NULL; diff --git a/src/lxc/utils.h b/src/lxc/utils.h index 4825599c4..c3dc5cfb9 100644 --- a/src/lxc/utils.h +++ b/src/lxc/utils.h @@ -223,7 +223,6 @@ __hidden extern uint64_t lxc_find_next_power2(uint64_t n); /* Set a signal the child process will receive after the parent has died. */ __hidden extern int lxc_set_death_signal(int signal, pid_t parent, int parent_status_fd); -__hidden extern int fd_cloexec(int fd, bool cloexec); __hidden extern int lxc_rm_rf(const char *dirname); __hidden extern bool lxc_can_use_pidfd(int pidfd);