io/Open: add TryOpen(struct open_how), Open(struct open_how)

This commit is contained in:
Max Kellermann 2025-02-03 21:35:40 +01:00 committed by Max Kellermann
parent 5b393052ee
commit dda85e02bf
4 changed files with 77 additions and 1 deletions

16
src/io/FileAt.hxx Normal file

@ -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;
};

@ -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__

@ -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

@ -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);
}