GCC Code Coverage Report


Directory: ./
File: Os/FileSystem.hpp
Date: 2026-09-03 21:13:48
Exec Total Coverage
Lines: 2 2 100.0%
Functions: 2 2 100.0%
Branches: 0 0 -%

Line Branch Exec Source
1 // ======================================================================
2 // \title Os/FileSystem.hpp
3 // \brief Os::FileSystem interface definition
4 // ======================================================================
5
6 #ifndef _OS_FILESYSTEM_HPP_
7 #define _OS_FILESYSTEM_HPP_
8
9 #include <Fw/FPrimeBasicTypes.hpp>
10 #include <Os/Directory.hpp>
11 #include <Os/File.hpp>
12 #include <Os/Os.hpp>
13
14 namespace Os {
15
16 struct FileSystemHandle {};
17
18 class FileSystemInterface {
19 public:
20 // Size of file chunks to use for file system operations (e.g. copyFile)
21 static constexpr FwSizeType FILE_SYSTEM_FILE_CHUNK_SIZE = FW_FILE_CHUNK_SIZE; //!< Size of file system chunk
22
23 enum Status {
24 OP_OK, //!< Operation was successful
25 ALREADY_EXISTS, //!< File already exists
26 NO_SPACE, //!< No space left
27 NO_PERMISSION, //!< No permission to write
28 NOT_DIR, //!< Path is not a directory
29 IS_DIR, //!< Path is a directory
30 NOT_EMPTY, //!< directory is not empty
31 INVALID_PATH, //!< Path is too long, too many sym links, etc.
32 DOESNT_EXIST, //!< Path doesn't exist
33 FILE_LIMIT, //!< Too many files or links
34 BUSY, //!< Operand is in use by the system or by a process
35 NO_MORE_FILES, //!< Directory stream has no more files
36 BUFFER_TOO_SMALL, //!< Buffer size is too small to hold full path (for getWorkingDirectory)
37 EXDEV_ERROR, // Operation not supported across devices (e.g. rename)
38 OVERFLOW_ERROR, // Operation failed due to overflow in calculation of the result
39 NOT_SUPPORTED, //!< Operation is not supported by the current implementation
40 OTHER_ERROR, //!< other OS-specific error
41 };
42
43 enum PathType {
44 FILE, //!< Path is a file
45 DIRECTORY, //!< Path is a directory
46 OTHER, //!< Path is not a file or directory, e.g. a socket
47 NOT_EXIST, //!< Path does not exist
48 };
49
50 //! \brief default constructor
51 40 FileSystemInterface() = default;
52
53 //! \brief default virtual destructor
54 80 virtual ~FileSystemInterface() = default;
55
56 //! \brief copy constructor is forbidden
57 FileSystemInterface(const FileSystemInterface& other) = delete;
58
59 //! \brief assignment operator is forbidden
60 FileSystemInterface& operator=(const FileSystemInterface& other) = delete; // NO_CODESONAR (cpp:S3657)
61
62 //! \brief return the underlying FileSystem handle (implementation specific)
63 //! \return internal FileSystem handle representation
64 virtual FileSystemHandle* getHandle() = 0;
65
66 //! \brief provide a pointer to a FileSystem delegate object
67 static FileSystemInterface* getDelegate(FileSystemHandleStorage& aligned_new_memory);
68
69 // ------------------------------------------------------------------
70 // FileSystem operations to be implemented by an OSAL implementation
71 // ------------------------------------------------------------------
72 // These functions are to be overridden in each OS implementation
73 // See an example in in Os/Posix/FileSystem.hpp
74
75 //! \brief Remove a directory at the specified path
76 //! \param path The path of the directory to remove
77 //! \return Status of the operation
78 virtual Status _removeDirectory(const char* path) = 0;
79
80 //! \brief Remove a file at the specified path
81 //! \param path The path of the file to remove
82 //! \return Status of the operation
83 virtual Status _removeFile(const char* path) = 0;
84
85 //! \brief Rename (or move) a file from source to destination
86 //! \param sourcePath The path of the source file
87 //! \param destPath The path of the destination file
88 //! \return Status of the operation
89 virtual Status _rename(const char* sourcePath, const char* destPath) = 0;
90
91 //! \brief Get filesystem free and total space in bytes on the filesystem containing the specified path
92 //! \param path The path on the filesystem to query
93 //! \param totalBytes Reference to store the total bytes on the filesystem
94 //! \param freeBytes Reference to store the free bytes on the filesystem
95 //! \return Status of the operation
96 virtual Status _getFreeSpace(const char* path, FwSizeType& totalBytes, FwSizeType& freeBytes) = 0;
97
98 //! \brief Get the type of the path (file, directory, etc.)
99 //!
100 //! It is invalid to pass `nullptr` as the path.
101 //!
102 //! \param path The path to check
103 //! \param pathType Reference to store the path type
104 //! \return Status of the operation
105 virtual Status _getPathType(const char* path, PathType& pathType) = 0;
106
107 //! \brief Get the current working directory
108 //! \param path Buffer to store the current working directory path
109 //! \param bufferSize Size of the buffer
110 //! \return Status of the operation
111 virtual Status _getWorkingDirectory(char* path, FwSizeType bufferSize) = 0;
112
113 //! \brief Change the current working directory to the specified path
114 //! \param path The path of the new working directory
115 //! \return Status of the operation
116 virtual Status _changeWorkingDirectory(const char* path) = 0;
117 };
118
119 //! \brief FileSystem class
120 //!
121 //! This class provides a common interface for file system operations.
122 //! This class uses the singleton pattern and should be accessed through
123 //! its static functions, for example using `Os::FileSystem::removeFile(path)`.
124 class FileSystem final : public FileSystemInterface {
125 private:
126 FileSystem(); //!< Constructor (private because singleton pattern)
127 public:
128 ~FileSystem() final; //!< Destructor
129
130 //! \brief return the underlying FileSystem handle (implementation specific)
131 //! \return internal FileSystem handle representation
132 FileSystemHandle* getHandle() override;
133
134 // ------------------------------------------------------------
135 // Implementation-specific FileSystem member functions
136 // ------------------------------------------------------------
137
138 //! \brief Remove a directory at the specified path
139 //!
140 //! It is invalid to pass `nullptr` as the path.
141 //!
142 //! \param path The path of the directory to remove
143 //! \return Status of the operation
144 Status _removeDirectory(const char* path) override;
145
146 //! \brief Remove a file at the specified path
147 //!
148 //! It is invalid to pass `nullptr` as the path.
149 //!
150 //! \param path The path of the file to remove
151 //! \return Status of the operation
152 Status _removeFile(const char* path) override;
153
154 //! \brief Rename a file from source to destination
155 //!
156 //! If the rename fails due to a cross-device operation, this function should return EXDEV_ERROR
157 //! and moveFile can be used instead to force a copy-and-remove.
158 //!
159 //! It is invalid to pass `nullptr` as sourcePath or destPath.
160 //!
161 //! \param sourcePath The path of the source file
162 //! \param destPath The path of the destination file
163 //! \return Status of the operation
164 Status _rename(const char* sourcePath, const char* destPath) override;
165
166 //! \brief Get filesystem free and total space in bytes on the filesystem containing the specified path
167 //!
168 //! It is invalid to pass `nullptr` as the path.
169 //!
170 //! \param path The path on the filesystem to query
171 //! \param totalBytes Reference to store the total bytes on the filesystem
172 //! \param freeBytes Reference to store the free bytes on the filesystem
173 //! \return Status of the operation
174 Status _getFreeSpace(const char* path, FwSizeType& totalBytes, FwSizeType& freeBytes) override;
175
176 //! \brief Get the current working directory
177 //!
178 //! Writes the current working directory path to the provided buffer of size bufferSize.
179 //! If the buffer is too small to hold the full path, the function will return BUFFER_TOO_SMALL.
180 //!
181 //! It is invalid to pass `nullptr` as the path.
182 //! It is invalid to pass a bufferSize of 0.
183 //!
184 //! \param path Buffer to store the current working directory path
185 //! \param bufferSize Size of the buffer
186 //! \return Status of the operation
187 Status _getWorkingDirectory(char* path, FwSizeType bufferSize) override;
188
189 //! \brief Change the current working directory to the specified path
190 //!
191 //! It is invalid to pass `nullptr` as the path.
192 //!
193 //! \param path The path of the new working directory
194 //! \return Status of the operation
195 Status _changeWorkingDirectory(const char* path) override;
196
197 //! \brief Get the type of the path (file, directory, etc.)
198 //!
199 //! It is invalid to pass `nullptr` as the path.
200 //!
201 //! \param path The path to check
202 //! \param pathType Reference to store the path type
203 //! \return Status of the operation
204 Status _getPathType(const char* path, PathType& pathType) override;
205
206 // ------------------------------------------------------------
207 // Implementation-specific FileSystem static functions
208 // ------------------------------------------------------------
209 // These are static variants that are exposed to the user, and call the above member functions
210
211 //! \brief Remove a directory at the specified path
212 //!
213 //! It is invalid to pass `nullptr` as the path.
214 //!
215 //! \param path The path of the directory to remove
216 //! \return Status of the operation
217 static Status removeDirectory(const char* path);
218
219 //! \brief Remove a file at the specified path
220 //!
221 //! It is invalid to pass `nullptr` as the path.
222 //!
223 //! \param path The path of the file to remove
224 //! \return Status of the operation
225 static Status removeFile(const char* path);
226
227 //! \brief Rename a file from source to destination
228 //!
229 //! If the rename fails due to a cross-device operation, this function should return EXDEV_ERROR
230 //! and moveFile can be used instead to force a copy-and-remove.
231 //!
232 //! It is invalid to pass `nullptr` as sourcePath or destPath.
233 //!
234 //! \param sourcePath The path of the source file
235 //! \param destPath The path of the destination file
236 //! \return Status of the operation
237 static Status rename(const char* sourcePath, const char* destPath);
238
239 //! \brief Get filesystem free and total space in bytes on the filesystem containing the specified path
240 //!
241 //! It is invalid to pass `nullptr` as the path.
242 //!
243 //! \param path The path on the filesystem to query
244 //! \param totalBytes Reference to store the total bytes on the filesystem
245 //! \param freeBytes Reference to store the free bytes on the filesystem
246 //! \return Status of the operation
247 static Status getFreeSpace(const char* path, FwSizeType& totalBytes, FwSizeType& freeBytes);
248
249 //! \brief Get the current working directory
250 //!
251 //! Writes the current working directory path to the provided buffer of size bufferSize.
252 //! If the buffer is too small to hold the full path, the function will return BUFFER_TOO_SMALL.
253 //!
254 //! It is invalid to pass `nullptr` as the path.
255 //! It is invalid to pass a bufferSize of 0.
256 //!
257 //! \param path Buffer to store the current working directory path
258 //! \param bufferSize Size of the buffer
259 //! \return Status of the operation
260 static Status getWorkingDirectory(char* path, FwSizeType bufferSize);
261
262 //! \brief Change the current working directory to the specified path
263 //!
264 //! It is invalid to pass `nullptr` as the path.
265 //!
266 //! \param path The path of the new working directory
267 //! \return Status of the operation
268 static Status changeWorkingDirectory(const char* path);
269
270 // ------------------------------------------------------------
271 // Additional functions built on top of OS-specific operations
272 // ------------------------------------------------------------
273
274 //! \brief Return true if the path exists, false otherwise
275 //!
276 //! It is invalid to pass `nullptr` as the path.
277 //!
278 //! \param path The path to check for existence
279 //! \return True if the path exists, false otherwise
280 static bool exists(const char* path);
281
282 //! \brief Return the type of the path (file, directory, or doesn't exist)
283 //!
284 //! It is invalid to pass `nullptr` as the path.
285 //!
286 //! \param path The path to check for existence
287 //! \return PathType enum representing the type of the path (FILE, DIRECTORY, NOT_EXIST)
288 static PathType getPathType(const char* path);
289
290 //! \brief Touch a file at the specified path, creating it if it doesn't exist
291 //!
292 //! It is invalid to pass `nullptr` as the path.
293 //!
294 //! \param path The path of the file to touch
295 //! \return Status of the operation
296 static Status touch(const char* path);
297
298 //! \brief Create a new directory at the specified path.
299 //!
300 //! The optional errorIfAlreadyExists (default=false) parameter can be set to true
301 //! to return an error status if the directory already exists.
302 //!
303 //! It is invalid to pass `nullptr` as the path.
304 //!
305 //! \param path The path where the new directory will be created
306 //! \param errorIfAlreadyExists If true, returns an error if the directory already exists
307 //! \return Status of the operation
308 static Status createDirectory(const char* path, bool errorIfAlreadyExists = false);
309
310 //! \brief Append the source file to the destination file
311 //!
312 //! This function opens both files, and iteratively reads the source by chunks and writes
313 //! chunks to the destination.
314 //! If the destination file does not exist and createMissingDest is true, a new file is created.
315 //!
316 //! It is invalid to pass `nullptr` as either the source or destination path.
317 //!
318 //! \param sourcePath The path of the source file
319 //! \param destPath The path of the destination file
320 //! \param createMissingDest If true, creates a new file if the destination doesn't exist
321 //! \return Status of the operation
322 static Status appendFile(const char* sourcePath, const char* destPath, bool createMissingDest = false);
323
324 //! \brief Copy a file from the source path to the destination path
325 //!
326 //! This function opens both files, and iteratively reads the source by chunks and writes
327 //! chunks to the destination.
328 //!
329 //! It is invalid to pass `nullptr` as either the source or destination path.
330 //!
331 //! \param sourcePath The path of the source file
332 //! \param destPath The path of the destination file
333 //! \return Status of the operation
334 static Status copyFile(const char* sourcePath, const char* destPath);
335
336 //! \brief Move a file from sourcePath to destPath
337 //!
338 //! This is done by first trying to rename, and if renaming fails,
339 //! copy it and then remove the original
340 //!
341 //! It is invalid to pass `nullptr` as either the source or destination path.
342 //!
343 //! \param sourcePath The path of the source file
344 //! \param destPath The path of the destination file
345 //! \return Status of the operation
346 static Status moveFile(const char* sourcePath, const char* destPath);
347
348 //! \brief Get the size of the file (in bytes) at the specified path
349 //!
350 //! It is invalid to pass `nullptr` as the path.
351 //!
352 //! \param path The path of the file
353 //! \param size Reference to store the size of the file
354 //! \return Status of the operation
355 static Status getFileSize(const char* path, FwSizeType& size);
356
357 public:
358 //! \brief initialize singleton
359 static void init();
360
361 //! \brief get a reference to singleton
362 //! \return reference to singleton
363 static FileSystem& getSingleton();
364
365 private:
366 // ------------------------------------------------------------
367 // Internal helper functions
368 // ------------------------------------------------------------
369
370 //! \brief Convert a File::Status to a FileSystem::Status
371 static Status handleFileError(File::Status fileStatus);
372
373 //! \brief Convert a Directory::Status to a FileSystem::Status
374 static Status handleDirectoryError(Directory::Status dirStatus);
375
376 //! \brief A helper function that writes all the file information in the source
377 //! file to the destination file (replaces/appends to end/etc. depending
378 //! on destination file mode).
379 //!
380 //! Files must already be open and will remain open after this function
381 //! completes.
382 //!
383 //! @param source File to copy data from
384 //! @param destination File to copy data to
385 //! @param size The number of bytes to copy
386 static Status copyFileData(File& source, File& destination, FwSizeType size);
387
388 private:
389 // This section is used to store the implementation-defined FileSystem handle. To Os::FileSystem and fprime, this
390 // type is opaque and thus normal allocation cannot be done. Instead, we allow the implementor to store then handle
391 // in the byte-array here and set `handle` to that address for storage.
392
393 alignas(FW_HANDLE_ALIGNMENT) FileSystemHandleStorage m_handle_storage; //!< FileSystem handle storage
394 FileSystemInterface& m_delegate;
395 };
396
397 } // namespace Os
398
399 #endif
400