/proc/self/cwd/envoy/filesystem/filesystem.h
Line | Count | Source (jump to first uncovered line) |
1 | | #pragma once |
2 | | |
3 | | #include <bitset> |
4 | | #include <cstdint> |
5 | | #include <memory> |
6 | | #include <string> |
7 | | |
8 | | #include "envoy/api/io_error.h" |
9 | | #include "envoy/common/platform.h" |
10 | | #include "envoy/common/pure.h" |
11 | | #include "envoy/common/time.h" |
12 | | |
13 | | #include "absl/status/statusor.h" |
14 | | #include "absl/strings/string_view.h" |
15 | | #include "absl/types/optional.h" |
16 | | |
17 | | namespace Envoy { |
18 | | namespace Filesystem { |
19 | | |
20 | | using FlagSet = std::bitset<5>; |
21 | | |
22 | | enum class DestinationType { File, Stderr, Stdout, TmpFile }; |
23 | | |
24 | | enum class FileType { Regular, Directory, Other }; |
25 | | |
26 | | struct FileInfo { |
27 | | const std::string name_; |
28 | | // the size of the file in bytes, or `nullopt` if the size could not be determined |
29 | | // (e.g. for directories, or windows symlinks.) |
30 | | const absl::optional<uint64_t> size_; |
31 | | // Note that if the file represented by name_ is a symlink, type_ will be the file type of the |
32 | | // target. For example, if name_ is a symlink to a directory, its file type will be Directory. |
33 | | // A broken symlink on posix will have `FileType::Regular`. |
34 | | const FileType file_type_; |
35 | | const absl::optional<SystemTime> time_created_; |
36 | | const absl::optional<SystemTime> time_last_accessed_; |
37 | | const absl::optional<SystemTime> time_last_modified_; |
38 | | }; |
39 | | |
40 | | /** |
41 | | * Abstraction for a basic file on disk. |
42 | | */ |
43 | | class File { |
44 | | public: |
45 | 17.4k | virtual ~File() = default; |
46 | | |
47 | | enum Operation { |
48 | | // Open a file for reading. |
49 | | Read, |
50 | | // Open a file for writing. The file will be truncated if neither Append nor |
51 | | // KeepExisting is set. |
52 | | Write, |
53 | | // Create the file if it does not already exist |
54 | | Create, |
55 | | // If writing, append to the file rather than writing to the beginning and |
56 | | // truncating after write. |
57 | | Append, |
58 | | // To open for write, without appending, and without truncating, add the |
59 | | // KeepExistingData flag. It is especially important to set this flag if |
60 | | // using pwrite, as the Windows implementation of truncation will interact |
61 | | // poorly with pwrite. |
62 | | KeepExistingData, |
63 | | }; |
64 | | |
65 | | /** |
66 | | * Open the file with Flag |
67 | | * The file will be closed when this object is destructed |
68 | | * |
69 | | * @return bool whether the open succeeded |
70 | | */ |
71 | | virtual Api::IoCallBoolResult open(FlagSet flags) PURE; |
72 | | |
73 | | /** |
74 | | * Write the buffer to the file. The file must be explicitly opened before writing. |
75 | | * |
76 | | * @return ssize_t number of bytes written, or -1 for failure |
77 | | */ |
78 | | virtual Api::IoCallSizeResult write(absl::string_view buffer) PURE; |
79 | | |
80 | | /** |
81 | | * Get additional details about the file. May or may not require a file system operation. |
82 | | * |
83 | | * @return FileInfo the file info. |
84 | | */ |
85 | | virtual Api::IoCallResult<FileInfo> info() PURE; |
86 | | |
87 | | /** |
88 | | * Close the file. |
89 | | * |
90 | | * @return bool whether the close succeeded |
91 | | */ |
92 | | virtual Api::IoCallBoolResult close() PURE; |
93 | | |
94 | | /** |
95 | | * Read a chunk of data from the file to a buffer. The file must be explicitly opened |
96 | | * before reading. |
97 | | * @param buf The buffer to copy the data into. |
98 | | * @param count The maximum number of bytes to read. |
99 | | * @param offset The offset in the file at which to start reading. |
100 | | * @return ssize_t number of bytes read, or -1 for failure. |
101 | | */ |
102 | | virtual Api::IoCallSizeResult pread(void* buf, uint64_t count, uint64_t offset) PURE; |
103 | | |
104 | | /** |
105 | | * Write a chunk of data from a buffer to the file. The file must be explicitly opened |
106 | | * before writing. |
107 | | * @param buf The buffer to read the data from. |
108 | | * @param count The maximum number of bytes to write. |
109 | | * @param offset The offset in the file at which to start writing. |
110 | | * @return ssize_t number of bytes written, or -1 for failure. |
111 | | */ |
112 | | virtual Api::IoCallSizeResult pwrite(const void* buf, uint64_t count, uint64_t offset) PURE; |
113 | | |
114 | | /** |
115 | | * @return bool is the file open |
116 | | */ |
117 | | virtual bool isOpen() const PURE; |
118 | | |
119 | | /** |
120 | | * @return string the file path |
121 | | */ |
122 | | virtual std::string path() const PURE; |
123 | | |
124 | | /** |
125 | | * @return the type of the destination |
126 | | */ |
127 | | virtual DestinationType destinationType() const PURE; |
128 | | }; |
129 | | |
130 | | using FilePtr = std::unique_ptr<File>; |
131 | | |
132 | | /** |
133 | | * Contains the result of splitting the file name and its parent directory from |
134 | | * a given file path. |
135 | | */ |
136 | | struct PathSplitResult { |
137 | | absl::string_view directory_; |
138 | | absl::string_view file_; |
139 | | }; |
140 | | |
141 | | /** |
142 | | * Contains the file type and the path. |
143 | | */ |
144 | | struct FilePathAndType { |
145 | 0 | bool operator==(const FilePathAndType& rhs) const { |
146 | 0 | return file_type_ == rhs.file_type_ && path_ == rhs.path_; |
147 | 0 | } |
148 | | FilePathAndType() = default; |
149 | | FilePathAndType(DestinationType file_type, absl::string_view path) |
150 | 18.2k | : file_type_(file_type), path_(path) {} |
151 | | DestinationType file_type_; |
152 | | std::string path_; |
153 | | }; |
154 | | |
155 | | /** |
156 | | * Abstraction for some basic filesystem operations |
157 | | */ |
158 | | class Instance { |
159 | | public: |
160 | 27.3k | virtual ~Instance() = default; |
161 | | |
162 | | /** |
163 | | * @param file_info The path and the type of the File |
164 | | * @return a FilePtr. The file is not opened. |
165 | | */ |
166 | | virtual FilePtr createFile(const FilePathAndType& file_info) PURE; |
167 | | |
168 | | /** |
169 | | * @return bool whether a file exists on disk and can be opened for read. |
170 | | */ |
171 | | virtual bool fileExists(const std::string& path) PURE; |
172 | | |
173 | | /** |
174 | | * @return FileInfo containing information about the file, or an error status. |
175 | | */ |
176 | | virtual Api::IoCallResult<FileInfo> stat(absl::string_view path) PURE; |
177 | | |
178 | | /** |
179 | | * Attempts to create the given path, recursively if necessary. |
180 | | * @return bool true if one or more directories was created and the path exists, |
181 | | * false if the path already existed, an error status if the path does |
182 | | * not exist after the call. |
183 | | */ |
184 | | virtual Api::IoCallBoolResult createPath(absl::string_view path) PURE; |
185 | | |
186 | | /** |
187 | | * @return bool whether a directory exists on disk and can be opened for read. |
188 | | */ |
189 | | virtual bool directoryExists(const std::string& path) PURE; |
190 | | |
191 | | /** |
192 | | * @return ssize_t the size in bytes of the specified file, or -1 if the file size |
193 | | * cannot be determined for any reason, including without limitation |
194 | | * the non-existence of the file. |
195 | | */ |
196 | | virtual ssize_t fileSize(const std::string& path) PURE; |
197 | | |
198 | | /** |
199 | | * @return full file content as a string or an error if the file can not be read. |
200 | | * Be aware, this is not most highly performing file reading method. |
201 | | */ |
202 | | virtual absl::StatusOr<std::string> fileReadToEnd(const std::string& path) PURE; |
203 | | |
204 | | /** |
205 | | * @path file path to split |
206 | | * @return PathSplitResult containing the parent directory of the input path and the file name or |
207 | | * an error status. |
208 | | */ |
209 | | virtual absl::StatusOr<PathSplitResult> splitPathFromFilename(absl::string_view path) PURE; |
210 | | |
211 | | /** |
212 | | * Determine if the path is on a list of paths Envoy will refuse to access. This |
213 | | * is a basic sanity check for users, denying some clearly bad paths. Paths |
214 | | * may still be problematic (e.g. indirectly leading to /dev/mem) even if this |
215 | | * returns false, it is up to the user to validate that supplied paths are |
216 | | * valid. |
217 | | * @param path some filesystem path. |
218 | | * @return is the path on the deny list? |
219 | | */ |
220 | | virtual bool illegalPath(const std::string& path) PURE; |
221 | | }; |
222 | | |
223 | | using InstancePtr = std::unique_ptr<Instance>; |
224 | | |
225 | | struct DirectoryEntry { |
226 | | // name_ is the name of the file in the directory, not including the directory path itself |
227 | | // For example, if we have directory a/b containing file c, name_ will be c |
228 | | std::string name_; |
229 | | |
230 | | // Note that if the file represented by name_ is a symlink, type_ will be the file type of the |
231 | | // target. For example, if name_ is a symlink to a directory, its file type will be Directory. |
232 | | FileType type_; |
233 | | |
234 | | // The file size in bytes for regular files. nullopt for FileType::Directory and FileType::Other, |
235 | | // and, on Windows, also nullopt for symlinks, and on Linux nullopt for broken symlinks. |
236 | | absl::optional<uint64_t> size_bytes_; |
237 | | |
238 | 15.7k | bool operator==(const DirectoryEntry& rhs) const { |
239 | 15.7k | return name_ == rhs.name_ && type_ == rhs.type_ && size_bytes_ == rhs.size_bytes_; |
240 | 15.7k | } |
241 | | }; |
242 | | |
243 | | class DirectoryIteratorImpl; |
244 | | class DirectoryIterator { |
245 | | public: |
246 | 13.5k | DirectoryIterator() : entry_({"", FileType::Other, absl::nullopt}) {} |
247 | 13.5k | virtual ~DirectoryIterator() = default; |
248 | | |
249 | 28.5k | const DirectoryEntry& operator*() const { return entry_; } |
250 | | |
251 | 15.7k | bool operator!=(const DirectoryIterator& rhs) const { return !(entry_ == *rhs); } |
252 | | |
253 | | virtual DirectoryIteratorImpl& operator++() PURE; |
254 | | |
255 | | protected: |
256 | | DirectoryEntry entry_; |
257 | | }; |
258 | | |
259 | | } // namespace Filesystem |
260 | | } // namespace Envoy |