aboutsummaryrefslogtreecommitdiffstats
path: root/nihil.posix/open.ccm
blob: a2fc9f430c702196a43df8c716c3f2e8370bf13b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// This source code is released into the public domain.
module;

#include <fcntl.h>
#include <unistd.h>

export module nihil.posix:open;

import nihil.std;
import nihil.util;
import :fd;

namespace nihil {

// Flags which can be passed to open().
struct open_flags_tag
{
};
export using open_flags = nihil::flagset<int, open_flags_tag>;

export inline constexpr auto open_none = open_flags();

// Basic flags, exactly one of these is required.
export inline constexpr auto open_read = open_flags::mask<O_RDONLY>();
export inline constexpr auto open_write = open_flags::mask<O_WRONLY>();
export inline constexpr auto open_readwrite = open_flags::mask<O_RDWR>();
export inline constexpr auto open_search = open_flags::mask<O_SEARCH>();
export inline constexpr auto open_exec = open_flags::mask<O_EXEC>();

// Modifiers
export inline constexpr auto open_nonblock = open_flags::mask<O_NONBLOCK>();
export inline constexpr auto open_append = open_flags::mask<O_APPEND>();
export inline constexpr auto open_create = open_flags::mask<O_CREAT>();
export inline constexpr auto open_truncate = open_flags::mask<O_TRUNC>();
export inline constexpr auto open_exclusive = open_flags::mask<O_EXCL>();
export inline constexpr auto open_shared_lock = open_flags::mask<O_SHLOCK>();
export inline constexpr auto open_exclusive_lock = open_flags::mask<O_EXLOCK>();
export inline constexpr auto open_directory = open_flags::mask<O_DIRECTORY>();
export inline constexpr auto open_nofollow = open_flags::mask<O_NOFOLLOW>();
export inline constexpr auto open_close_on_exec = open_flags::mask<O_CLOEXEC>();
export inline constexpr auto open_resolve_beneath = open_flags::mask<O_RESOLVE_BENEATH>();

// FreeBSD
#ifdef O_DIRECT
export inline constexpr auto open_direct = open_flags::mask<O_DIRECT>();
#endif

#ifdef O_VERIFY
export inline constexpr auto open_verify = open_flags::mask<O_VERIFY>();
#endif

#ifdef O_PATH
export inline constexpr auto open_path = open_flags::mask<O_PATH>();
#endif

#ifdef O_EMPTY_PATH
export inline constexpr auto open_empty_path = open_flags::mask<O_EMPTY_PATH>();
#endif

// macOS
#ifdef O_NOFOLLOW_ANY
export inline constexpr auto open_nofollow_any = open_flags::mask<O_NOFOLLOW_ANY>();
#endif

#ifdef O_SYMLINK
export inline constexpr auto open_symlink = open_flags::mask<O_SYMLINK>();
#endif

#ifdef O_EVTONLY
export inline constexpr auto open_eventonly = open_flags::mask<O_EVTONLY>();
#endif

// Open the given file and return an fd for it.
export [[nodiscard]] auto open(std::filesystem::path const &filename, open_flags flags,
                               int mode = 0777) -> std::expected<fd, error>
{
	auto fdno = ::open(filename.c_str(), flags.value(), mode);
	if (fdno != -1)
		return fd(fdno);

	return error(sys_error());
}

// Like open(), but resolve relative to an open file descriptor, which must refer to a directory.
export [[nodiscard]] auto openat(fd &where, std::filesystem::path const &filename, open_flags flags,
                                 int mode = 0777) -> std::expected<fd, error>
{
	auto fdno = ::openat(where.get(), filename.c_str(), flags.value(), mode);
	if (fdno != -1)
		return fd(fdno);

	return error(sys_error());
}

} // namespace nihil