From 268ae488167617b919b8bb219f555e1f9133e234 Mon Sep 17 00:00:00 2001 From: Colin Walters <walters@verbum.org> Date: Wed, 19 Jul 2017 09:40:23 -0400 Subject: [PATCH] fdio: Introduce glnx_openat_read() This is kind of long overdue. Reasons are the same as the other wrappers. I debated adding `O_NOFOLLOW` support but the use cases for that are pretty obscure, callers who want that can just use the syscall directly for now. --- glnx-fdio.c | 43 +++++++++++++++++++++++++++++-------- glnx-fdio.h | 7 ++++++ tests/test-libglnx-xattrs.c | 26 +++++++--------------- 3 files changed, 49 insertions(+), 27 deletions(-) diff --git a/glnx-fdio.c b/glnx-fdio.c index 797d939c2..756248d69 100644 --- a/glnx-fdio.c +++ b/glnx-fdio.c @@ -387,6 +387,35 @@ glnx_link_tmpfile_at (GLnxTmpfile *tmpf, return TRUE; } +/** + * glnx_openat_rdonly: + * @dfd: File descriptor for origin directory + * @path: Pathname, relative to @dfd + * @follow: Whether or not to follow symbolic links in the final component + * @out_fd: (out): File descriptor + * @error: Error + * + * Use openat() to open a file, with flags `O_RDONLY | O_CLOEXEC | O_NOCTTY`. + * Like the other libglnx wrappers, will use `TEMP_FAILURE_RETRY` and + * also includes @path in @error in case of failure. + */ +gboolean +glnx_openat_rdonly (int dfd, + const char *path, + gboolean follow, + int *out_fd, + GError **error) +{ + int flags = O_RDONLY | O_CLOEXEC | O_NOCTTY; + if (!follow) + flags |= O_NOFOLLOW; + int fd = TEMP_FAILURE_RETRY (openat (dfd, path, flags)); + if (fd == -1) + return glnx_throw_errno_prefix (error, "openat(%s)", path); + *out_fd = fd; + return TRUE; +} + static guint8* glnx_fd_readall_malloc (int fd, gsize *out_len, @@ -524,9 +553,9 @@ glnx_file_get_contents_utf8_at (int dfd, { dfd = glnx_dirfd_canonicalize (dfd); - glnx_fd_close int fd = TEMP_FAILURE_RETRY (openat (dfd, subpath, O_RDONLY | O_NOCTTY | O_CLOEXEC)); - if (G_UNLIKELY (fd == -1)) - return glnx_null_throw_errno_prefix (error, "open(%s)", subpath); + glnx_fd_close int fd = -1; + if (!glnx_openat_rdonly (dfd, subpath, TRUE, &fd, error)) + return NULL; gsize len; g_autofree char *buf = glnx_fd_readall_utf8 (fd, &len, cancellable, error); @@ -822,12 +851,8 @@ glnx_file_copy_at (int src_dfd, goto out; } - src_fd = TEMP_FAILURE_RETRY (openat (src_dfd, src_subpath, O_RDONLY | O_CLOEXEC | O_NOCTTY | O_NOFOLLOW)); - if (src_fd == -1) - { - glnx_set_error_from_errno (error); - goto out; - } + if (!glnx_openat_rdonly (src_dfd, src_subpath, FALSE, &src_fd, error)) + goto out; dest_open_flags = O_WRONLY | O_CREAT | O_CLOEXEC | O_NOCTTY; if (!(copyflags & GLNX_FILE_COPY_OVERWRITE)) diff --git a/glnx-fdio.h b/glnx-fdio.h index 902f8d2c7..6b873e94c 100644 --- a/glnx-fdio.h +++ b/glnx-fdio.h @@ -102,6 +102,13 @@ glnx_link_tmpfile_at (GLnxTmpfile *tmpf, const char *target, GError **error); +gboolean +glnx_openat_rdonly (int dfd, + const char *path, + gboolean follow, + int *out_fd, + GError **error); + GBytes * glnx_fd_readall_bytes (int fd, GCancellable *cancellable, diff --git a/tests/test-libglnx-xattrs.c b/tests/test-libglnx-xattrs.c index b6f0ac69c..37c982d7b 100644 --- a/tests/test-libglnx-xattrs.c +++ b/tests/test-libglnx-xattrs.c @@ -107,22 +107,17 @@ do_write_run (GLnxDirFdIterator *dfd_iter, GError **error) { while (TRUE) { - g_autoptr(GVariant) current_xattrs = NULL; - glnx_fd_close int fd = -1; - struct dirent *dent; if (!glnx_dirfd_iterator_next_dent (dfd_iter, &dent, NULL, error)) return FALSE; if (!dent) break; - fd = openat (dfd_iter->fd, dent->d_name, O_RDONLY | O_CLOEXEC); - if (fd < 0) - { - glnx_set_error_from_errno (error); - return FALSE; - } + glnx_fd_close int fd = -1; + if (!glnx_openat_rdonly (dfd_iter->fd, dent->d_name, FALSE, &fd, error)) + return FALSE; + g_autoptr(GVariant) current_xattrs = NULL; if (!glnx_fd_get_all_xattrs (fd, ¤t_xattrs, NULL, error)) return FALSE; @@ -156,22 +151,17 @@ do_read_run (GLnxDirFdIterator *dfd_iter, guint nattrs = 0; while (TRUE) { - g_autoptr(GVariant) current_xattrs = NULL; - glnx_fd_close int fd = -1; - struct dirent *dent; if (!glnx_dirfd_iterator_next_dent (dfd_iter, &dent, NULL, error)) return FALSE; if (!dent) break; - fd = openat (dfd_iter->fd, dent->d_name, O_RDONLY | O_CLOEXEC); - if (fd < 0) - { - glnx_set_error_from_errno (error); - return FALSE; - } + glnx_fd_close int fd = -1; + if (!glnx_openat_rdonly (dfd_iter->fd, dent->d_name, FALSE, &fd, error)) + return FALSE; + g_autoptr(GVariant) current_xattrs = NULL; if (!glnx_fd_get_all_xattrs (fd, ¤t_xattrs, NULL, error)) return FALSE; -- GitLab