The main posixpp library and associated tests.
Revision | d30c74a036b553087ea39b939f8ef9fe5a336aec (tree) |
---|---|
Time | 2021-04-30 01:31:19 |
Author | Eric Hopper <hopper@omni...> |
Commiter | Eric Hopper |
Implement dup3 as well, and add TODO for test case.
@@ -4,6 +4,7 @@ | ||
4 | 4 | #include <posixpp/fdflags.h> |
5 | 5 | #include <posixpp/modeflags.h> |
6 | 6 | #include <syscalls/linux/simple_io.h> |
7 | +#include <optional> | |
7 | 8 | |
8 | 9 | namespace posixpp { |
9 | 10 |
@@ -56,10 +57,25 @@ | ||
56 | 57 | return error_cascade(dup(fd_), int_to_fd); |
57 | 58 | } |
58 | 59 | |
59 | - //! See man page dup2(2) | |
60 | - [[nodiscard]] expected<void> dup2(fd &newfd) const noexcept { | |
60 | + //! See man page dup2(2) or dup3(2) (if the cloexec flag has a value). | |
61 | + [[nodiscard]] expected<void> dup2( | |
62 | + fd &newfd, | |
63 | + ::std::optional<bool> cloexec=::std::optional<bool>{} | |
64 | + ) const noexcept | |
65 | + { | |
61 | 66 | using ::syscalls::linux::dup2; |
62 | - return error_cascade_void(dup2(fd_, newfd.as_fd())); | |
67 | + using ::syscalls::linux::dup3; | |
68 | + if (!cloexec.has_value()) { | |
69 | + return error_cascade_void(dup2(fd_, newfd.fd_)); | |
70 | + } else { | |
71 | + auto const flagval = cloexec.value() ? fdflags::cloexec : fdflags{}; | |
72 | + // TODO: Write a test case for this, which is hard because it | |
73 | + // requires the 'exec' system call, and that the exec'ed program | |
74 | + // run part of the test. | |
75 | + return error_cascade_void( | |
76 | + dup3(fd_, newfd.fd_, flagval.getbits()) | |
77 | + ); | |
78 | + } | |
63 | 79 | } |
64 | 80 | |
65 | 81 | expected<::std::size_t> |
@@ -41,5 +41,10 @@ | ||
41 | 41 | return syscall_expected(call_id::dup2, oldfd, newfd); |
42 | 42 | } |
43 | 43 | |
44 | +inline expected_t dup3(int oldfd, int newfd, int flags) noexcept | |
45 | +{ | |
46 | + return syscall_expected(call_id::dup3, oldfd, newfd, flags); | |
47 | +} | |
48 | + | |
44 | 49 | } |
45 | 50 | } |
@@ -19,6 +19,8 @@ | ||
19 | 19 | |
20 | 20 | public: |
21 | 21 | friend class openflags; |
22 | + //! Default empty set | |
23 | + constexpr fdflags() : base_t{0} {} | |
22 | 24 | |
23 | 25 | static const fdflags accmode; |
24 | 26 | static const fdflags tmpfile; |
@@ -63,6 +65,9 @@ | ||
63 | 65 | friend base_t; |
64 | 66 | |
65 | 67 | public: |
68 | + //! Default empty set. | |
69 | + constexpr openflags() : base_t{0} {} | |
70 | + //! All fdflags are also openflags, but not all openflags are fdflags. | |
66 | 71 | explicit constexpr openflags(fdflags const &val) : base_t(val.getbits()) {} |
67 | 72 | |
68 | 73 | static const openflags creat; //!< O_CREAT |
@@ -342,6 +342,7 @@ | ||
342 | 342 | unshare, |
343 | 343 | epoll_pwait = 281, |
344 | 344 | epoll_create1 = 291, |
345 | + dup3 = 292, | |
345 | 346 | syncfs = 306, |
346 | 347 | setns = 308 |
347 | 348 | }; |