From dda85e02bf46fa7445b21a3dde7c21b22c8e4223 Mon Sep 17 00:00:00 2001 From: Max Kellermann <max.kellermann@ionos.com> Date: Mon, 3 Feb 2025 21:35:40 +0100 Subject: [PATCH] io/Open: add TryOpen(struct open_how), Open(struct open_how) --- src/io/FileAt.hxx | 16 ++++++++++++++++ src/io/Open.cxx | 24 +++++++++++++++++++++++- src/io/Open.hxx | 21 +++++++++++++++++++++ src/system/linux/openat2.h | 17 +++++++++++++++++ 4 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 src/io/FileAt.hxx create mode 100644 src/system/linux/openat2.h diff --git a/src/io/FileAt.hxx b/src/io/FileAt.hxx new file mode 100644 index 000000000..53cd9686c --- /dev/null +++ b/src/io/FileAt.hxx @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BSD-2-Clause +// Copyright CM4all GmbH +// author: Max Kellermann <mk@cm4all.com> + +#pragma once + +#include "FileDescriptor.hxx" + +/** + * Reference to a file by an anchor directory (which can be an + * `O_PATH` descriptor) and a path name relative to it. + */ +struct FileAt { + FileDescriptor directory; + const char *name; +}; diff --git a/src/io/Open.cxx b/src/io/Open.cxx index 8514e95cb..f962c273d 100644 --- a/src/io/Open.cxx +++ b/src/io/Open.cxx @@ -5,6 +5,11 @@ #include "UniqueFileDescriptor.hxx" #include "lib/fmt/SystemError.hxx" +#ifdef __linux__ +#include "FileAt.hxx" +#include "system/linux/openat2.h" +#endif + #include <fcntl.h> UniqueFileDescriptor @@ -93,4 +98,21 @@ OpenDirectory(FileDescriptor directory, const char *name, int flags) return fd; } -#endif +UniqueFileDescriptor +TryOpen(FileAt file, const struct open_how &how) noexcept +{ + int fd = openat2(file.directory.Get(), file.name, &how, sizeof(how)); + return UniqueFileDescriptor{AdoptTag{}, fd}; +} + +UniqueFileDescriptor +Open(FileAt file, const struct open_how &how) +{ + auto fd = TryOpen(file, how); + if (!fd.IsDefined()) + throw FmtErrno("Failed to open {:?}", file.name); + + return fd; +} + +#endif // __linux__ diff --git a/src/io/Open.hxx b/src/io/Open.hxx index 2ff0501f8..08c9bbdc5 100644 --- a/src/io/Open.hxx +++ b/src/io/Open.hxx @@ -36,4 +36,25 @@ OpenWriteOnly(FileDescriptor directory, const char *name, int flags=0); UniqueFileDescriptor OpenDirectory(FileDescriptor directory, const char *name, int flags=0); +struct opwn_how; +struct FileAt; + +/** + * Wrapper for openat2() which converts the returned file descriptor + * to a #UniqueFileDescriptor. + * + * Returns an "undefined" instance on error and sets errno. + */ +UniqueFileDescriptor +TryOpen(FileAt file, const struct open_how &how) noexcept; + +/** + * Wrapper for openat2() which converts the returned file descriptor + * to a #UniqueFileDescriptor. + * + * Throws on error. + */ +UniqueFileDescriptor +Open(FileAt file, const struct open_how &how); + #endif diff --git a/src/system/linux/openat2.h b/src/system/linux/openat2.h new file mode 100644 index 000000000..362ffad2e --- /dev/null +++ b/src/system/linux/openat2.h @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: BSD-2-Clause +// Copyright CM4all GmbH +// author: Max Kellermann <mk@cm4all.com> + +#pragma once + +#include <fcntl.h> // for O_* +#include <linux/openat2.h> // for RESOLVE_* +#include <sys/syscall.h> +#include <unistd.h> + +static inline int +openat2(int dirfd, const char *pathname, + const struct open_how *how, size_t size) +{ + return syscall(__NR_openat2, dirfd, pathname, how, size); +}