Arene Base
Fundamental Utilities For Safety Critical C++
Loading...
Searching...
No Matches
directory_handle.hpp
Go to the documentation of this file.
1// Copyright 2024, Toyota Motor Corporation
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4
5#ifndef INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_FILESYSTEM_DIRECTORY_HANDLE_HPP_
6#define INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_FILESYSTEM_DIRECTORY_HANDLE_HPP_
7
8#include <dirent.h>
9#include <sys/stat.h> // IWYU pragma: keep
10
11#include <cstdint>
12#include <utility>
13
14// parasoft-begin-suppress AUTOSAR-A16_2_2-a-2 "Arene Base aggregate headers permitted by A16-2-2 Permit #1"
15#include "arene/base/filesystem/error_code.hpp"
16#include "arene/base/filesystem/file_handle.hpp"
17#include "arene/base/filesystem/open_flags.hpp"
18#include "arene/base/result.hpp"
19#include "arene/base/string_view.hpp"
20// parasoft-end-suppress AUTOSAR-A16_2_2-a-2
21
22// parasoft-begin-suppress AUTOSAR-A7_1_5-a-2 "Trailing return syntax permitted by A7-1-5 Permit #1 v1.0.0"
23
24namespace arene {
25namespace base {
26
27namespace filesystem {
28
29/// @brief Flags to specify what to do when attempting to create a file that already exists
30enum class create_flags : std::uint8_t {
31 /// @brief If the file already exists fail the creation
32 create_or_fail,
33 /// @brief If the file already exists, truncate it and open it
34 create_or_truncate,
35 /// @brief If the file already exists, open the existing file without altering it
36 create_or_open
37};
38
39// parasoft-begin-suppress AUTOSAR-A12_1_5-a-2 "Delegating constructors would not reduce duplication"
40/// @brief Class to wrap a directory handle.
41class directory_handle {
42 // parasoft-begin-suppress AUTOSAR-A3_9_1-b-2 "Using an int for compatibility with OS functions"
43 /// @brief The OS directory handle type
44 using os_directory_handle = int;
45 // parasoft-end-suppress AUTOSAR-A3_9_1-b-2
46 public:
47 /// @brief Construct a directory handle that doesn't refer to a directory
48 directory_handle() noexcept
49 : raw_handle_{file_handle::invalid_handle_value},
50 handle_{nullptr} {}
51
52 /// @brief Obtain a directory handle from a file handle to the directory.
53 /// @param source_handle The file handle for the directory
54 /// @throws std::system_error if an error occurs
55 explicit directory_handle(file_handle source_handle);
56
57 /// @brief Close the directory handle
58 ~directory_handle();
59
60 /// @brief Transfer ownership of a directory handle from @c source to @c *this.
61 /// @param source The handle to transfer ownership from
62 directory_handle(directory_handle&& source) noexcept
63 : raw_handle_(std::exchange(source.raw_handle_, file_handle::invalid_handle_value)),
64 // parasoft-begin-suppress CERT_CPP-EXP57-b-3 "False positive: This is not a pointer cast"
65 handle_(std::exchange(source.handle_, nullptr)) {}
66 // parasoft-end-suppress CERT_CPP-EXP57-b-3
67
68 /// @brief Transfer ownership of a directory handle from @c source to @c *this.
69 /// Closes any previous directory handle owned by @c *this
70 /// @param source The handle to transfer ownership from
71 auto operator=(directory_handle&& source) noexcept -> directory_handle&;
72 /// @brief Check if the handle has a valid value
73 /// @return @c true if the handle is valid, @c false otherwise
74 auto valid() const noexcept -> bool { return raw_handle_ != file_handle::invalid_handle_value; }
75
76 // parasoft-begin-suppress CERT_C-EXP37-a-3 "False positive: The rule does not mention naming all parameters"
77 /// @brief Not copyable
78 directory_handle(directory_handle const&) = delete;
79 /// @brief Not copyable
80 auto operator=(directory_handle const&) -> directory_handle& = delete;
81 // parasoft-end-suppress CERT_C-EXP37-a-3
82
83 /// @brief Rewind the directory handle to the start of the directory.
84 /// @return A @c result holding a value on success, otherwise a @c result
85 /// holding an error indicating the cause of failure.
86 auto rewind() noexcept -> result<void, error_code>;
87
88 /// @brief Advance to the next directory entry and return it. Ignores "." and ".."
89 /// entries. Returns an @c ERANGE error if there are no more entries.
90 /// @return A @c result holding the name of the next entry on success,
91 /// otherwise a @c result holding an error indicating the cause of failure. An
92 /// error of @c ERANGE indicates that the end of the directory has been
93 /// reached.
94 auto next_entry() noexcept -> result<null_terminated_string_view, error_code>;
95
96 /// @brief Create a directory as a subdirectory of the directory referenced by @c
97 /// *this, with the given name.
98 /// @param dir_name The name of the new directory to create
99 /// @return A @c result with a value if the directory was created, otherwise
100 /// a @c result holding an @c error_code identifying the cause for the
101 /// failure.
102 // NOLINTNEXTLINE(readability-avoid-const-params-in-decls)
103 auto create_subdirectory(null_terminated_string_view const dir_name) const noexcept -> result<void, error_code>;
104
105 /// @brief Open a handle to the directory with the specified absolute path or path
106 /// relative to the current working directory.
107 /// @param path The path of the directory to retrieve the handle for
108 /// @return A @c directory_handle for the directory, or @c nullopt if the
109 /// directory doesn't exist
110 /// @return A @c result holding a handle to the directory if the directory
111 /// could be opened, otherwise a @c result holding an @c error_code
112 /// identifying the cause for the failure.
113 // NOLINTNEXTLINE(readability-avoid-const-params-in-decls)
114 static auto open(null_terminated_string_view const path) noexcept -> result<directory_handle, error_code>;
115
116 /// @brief Open a handle to the directory with the specified name relative to the
117 /// directory referenced by @c *this.
118 /// @param relative_name The name of the directory to retrieve the handle for
119 /// @return A @c result holding a handle to the subdirectory if the directory
120 /// could be opened, otherwise a @c result holding an @c error_code
121 /// identifying the cause for the failure.
122 // NOLINTNEXTLINE(readability-avoid-const-params-in-decls)
123 auto open_subdirectory(null_terminated_string_view const relative_name) const noexcept
124 -> result<directory_handle, error_code>;
125
126 /// @brief Get the file stats for the directory entry with the specified name
127 /// relative to the directory referenced by @c *this.
128 /// @param relative_name The name of the directory entry to check
129 /// @return The file stats for the directory entry, or @c nullopt if the
130 /// directory entry doesn't exist
131 /// @return A @c result holding the file stats for the directory entry if
132 /// they could be retrieved, otherwise a @c result holding an @c error_code
133 /// identifying the cause for the failure.
134 // NOLINTNEXTLINE(readability-avoid-const-params-in-decls)
135 auto get_file_stats(null_terminated_string_view const relative_name) const noexcept
136 -> result<struct stat, error_code>;
137
138 /// @brief Flag type to indicate what is being unlinked
139 enum class unlink_type : std::uint8_t {
140 /// @brief A directory is being unlinked
141 directory,
142 /// @brief Something that is not a directory is being unlinked
143 other
144 };
145
146 /// @brief Remove a directory entry with the specified name relative to the directory
147 /// referenced by @c *this.
148 /// @param relative_name The name of the directory entry to check
149 /// @param type A flag indicating if the directory entry is thought to
150 /// be a directory (@c unlink_type::directory), or not (@c unlink_type::other)
151 /// @return A @c result with a value if the directory entry was removed,
152 /// otherwise a @c result holding an @c error_code identifying the cause for
153 /// the failure.
154 // parasoft-begin-suppress AUTOSAR-A7_1_3-a-2 "False Positive: const is on rhs"
155 // NOLINTNEXTLINE(readability-avoid-const-params-in-decls)
156 auto unlink_entry(null_terminated_string_view const relative_name, unlink_type const type) const noexcept
157 -> result<void, error_code>;
158 // parasoft-end-suppress AUTOSAR-A7_1_3-a-2
159
160 /// @brief Open a read-only handle to the file with the specified name relative to
161 /// the directory referenced by @c *this.
162 /// @param relative_name The name of the file to open
163 /// @return A @c result holding a handle to the file if the file could be
164 /// opened, otherwise a @c result holding an @c error_code identifying the
165 /// cause for the failure.
166 // NOLINTNEXTLINE(readability-avoid-const-params-in-decls)
167 auto open_file(null_terminated_string_view const relative_name) const noexcept -> result<file_handle, error_code>;
168
169 /// @brief Open a handle to the file with the specified name relative to the
170 /// directory referenced by @c *this, with permissions specified by the @c
171 /// flags
172 /// @param relative_name The name of the file to open
173 /// @param flags The flags to use for opening the file
174 /// @return A @c result holding a handle to the file if the file could be
175 /// opened, otherwise a @c result holding an @c error_code identifying the
176 /// cause for the failure.
177 // NOLINTNEXTLINE(readability-avoid-const-params-in-decls)
178 auto open_file(null_terminated_string_view const relative_name, open_flags const flags) const noexcept
179 -> result<file_handle, error_code>;
180
181 /// @brief Create a file with the specified name relative to the directory referenced
182 /// by @c *this and return a read-write handle to the new file. Fails if a
183 /// file with the specified name already exists.
184 /// @param relative_name The name of the file to create
185 /// @return A @c result holding a handle to the file if the file could be
186 /// created, otherwise a @c result holding an @c error_code identifying the
187 /// cause for the failure.
188 // NOLINTNEXTLINE(readability-avoid-const-params-in-decls)
189 auto create_file(null_terminated_string_view const relative_name) const noexcept -> result<file_handle, error_code>;
190
191 /// @brief Create a file or open an existing file with the specified name relative to
192 /// the directory referenced by @c *this and return a read-write handle to the
193 /// new file. The behaviour when there is already a file with the specified
194 /// name is specified by the @c flags parameter.
195 /// @param relative_name The name of the file to create
196 /// @param flags The creation flags
197 /// @return A @c result holding a handle to the file if the file could be
198 /// created, otherwise a @c result holding an @c error_code identifying the
199 /// cause for the failure.
200 auto create_file(null_terminated_string_view relative_name, create_flags flags) const noexcept
201 -> result<file_handle, error_code>;
202
203 /// @brief Create a temporary file with no name (or a transient random name) in the
204 /// directory referenced by @c *this and return a read-write handle to the new
205 /// file. Fails if a temporary file could not be created.
206 /// @return A @c result holding a handle to the file if the file could be
207 /// created, otherwise a @c result holding an @c error_code identifying the
208 /// cause for the failure.
209 auto create_temporary_file() const noexcept -> result<file_handle, error_code>;
210
211 /// @brief Rename a file or directory from its existing name relative to the
212 /// directory referenced by @c *this to the specified new name relative to the
213 /// directory referenced by @c *this.
214 /// @param old_name The existing name of the file or directory
215 /// @param new_name The desired name of the file or directory
216 /// @return A @c result holding a value if the file or directory could be
217 /// renamed, otherwise a @c result holding an @c error_code identifying the
218 /// cause for the failure.
219 // NOLINTNEXTLINE(readability-avoid-const-params-in-decls)
220 auto rename(null_terminated_string_view const old_name, null_terminated_string_view const new_name) const noexcept
221 -> result<void, error_code>;
222
223 private:
224 /// @brief Internal function to create a temporary file with no name in the
225 /// directory referenced by @c *this and return a read-write handle to the new
226 /// file. Fails if a temporary file could not be created or the OS does not provide the necessary facilities.
227 /// @return A @c result holding a handle to the file if the file could be
228 /// created, otherwise a @c result holding an @c error_code identifying the
229 /// cause for the failure. The error code is @c ENOTSUP if the OS does not provide the necessary facilities.
230 auto create_temporary_file_directly() const noexcept -> result<file_handle, error_code>;
231
232 /// @brief The raw file handle for the directory
233 os_directory_handle raw_handle_;
234 /// @brief The directory handle itself
235 DIR* handle_;
236};
237// parasoft-end-suppress AUTOSAR-A12_1_5-a-2
238
239} // namespace filesystem
240} // namespace base
241} // namespace arene
242
243#endif // INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_FILESYSTEM_DIRECTORY_HANDLE_HPP_
Definition directory_handle.cpp:39
Definition array_exceptions_disabled.cpp:11
Copyright 2026, Toyota Motor Corporation.
Definition array_exceptions_disabled.cpp:10