Skip to content

Commit dda85e0

Browse files
committed
io/Open: add TryOpen(struct open_how), Open(struct open_how)
1 parent 5b39305 commit dda85e0

4 files changed

Lines changed: 77 additions & 1 deletion

File tree

src/io/FileAt.hxx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// SPDX-License-Identifier: BSD-2-Clause
2+
// Copyright CM4all GmbH
3+
// author: Max Kellermann <mk@cm4all.com>
4+
5+
#pragma once
6+
7+
#include "FileDescriptor.hxx"
8+
9+
/**
10+
* Reference to a file by an anchor directory (which can be an
11+
* `O_PATH` descriptor) and a path name relative to it.
12+
*/
13+
struct FileAt {
14+
FileDescriptor directory;
15+
const char *name;
16+
};

src/io/Open.cxx

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
#include "UniqueFileDescriptor.hxx"
66
#include "lib/fmt/SystemError.hxx"
77

8+
#ifdef __linux__
9+
#include "FileAt.hxx"
10+
#include "system/linux/openat2.h"
11+
#endif
12+
813
#include <fcntl.h>
914

1015
UniqueFileDescriptor
@@ -93,4 +98,21 @@ OpenDirectory(FileDescriptor directory, const char *name, int flags)
9398
return fd;
9499
}
95100

96-
#endif
101+
UniqueFileDescriptor
102+
TryOpen(FileAt file, const struct open_how &how) noexcept
103+
{
104+
int fd = openat2(file.directory.Get(), file.name, &how, sizeof(how));
105+
return UniqueFileDescriptor{AdoptTag{}, fd};
106+
}
107+
108+
UniqueFileDescriptor
109+
Open(FileAt file, const struct open_how &how)
110+
{
111+
auto fd = TryOpen(file, how);
112+
if (!fd.IsDefined())
113+
throw FmtErrno("Failed to open {:?}", file.name);
114+
115+
return fd;
116+
}
117+
118+
#endif // __linux__

src/io/Open.hxx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,25 @@ OpenWriteOnly(FileDescriptor directory, const char *name, int flags=0);
3636
UniqueFileDescriptor
3737
OpenDirectory(FileDescriptor directory, const char *name, int flags=0);
3838

39+
struct opwn_how;
40+
struct FileAt;
41+
42+
/**
43+
* Wrapper for openat2() which converts the returned file descriptor
44+
* to a #UniqueFileDescriptor.
45+
*
46+
* Returns an "undefined" instance on error and sets errno.
47+
*/
48+
UniqueFileDescriptor
49+
TryOpen(FileAt file, const struct open_how &how) noexcept;
50+
51+
/**
52+
* Wrapper for openat2() which converts the returned file descriptor
53+
* to a #UniqueFileDescriptor.
54+
*
55+
* Throws on error.
56+
*/
57+
UniqueFileDescriptor
58+
Open(FileAt file, const struct open_how &how);
59+
3960
#endif

src/system/linux/openat2.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// SPDX-License-Identifier: BSD-2-Clause
2+
// Copyright CM4all GmbH
3+
// author: Max Kellermann <mk@cm4all.com>
4+
5+
#pragma once
6+
7+
#include <fcntl.h> // for O_*
8+
#include <linux/openat2.h> // for RESOLVE_*
9+
#include <sys/syscall.h>
10+
#include <unistd.h>
11+
12+
static inline int
13+
openat2(int dirfd, const char *pathname,
14+
const struct open_how *how, size_t size)
15+
{
16+
return syscall(__NR_openat2, dirfd, pathname, how, size);
17+
}

0 commit comments

Comments
 (0)