| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // ====================================================================== | ||
| 2 | // \title Os/File.hpp | ||
| 3 | // \brief common function definitions for Os::File | ||
| 4 | // ====================================================================== | ||
| 5 | #ifndef Os_File_hpp_ | ||
| 6 | #define Os_File_hpp_ | ||
| 7 | |||
| 8 | #include <Fw/FPrimeBasicTypes.hpp> | ||
| 9 | #include <Fw/Types/ConstStringBase.hpp> | ||
| 10 | #include <Os/Os.hpp> | ||
| 11 | #include <Utils/Hash/Hash.hpp> | ||
| 12 | |||
| 13 | // Forward declaration for UTs | ||
| 14 | namespace Os { | ||
| 15 | namespace Test { | ||
| 16 | namespace FileTest { | ||
| 17 | struct Tester; | ||
| 18 | } | ||
| 19 | } // namespace Test | ||
| 20 | } // namespace Os | ||
| 21 | |||
| 22 | namespace Os { | ||
| 23 | |||
| 24 | //! \brief base implementation of FileHandle | ||
| 25 | //! | ||
| 26 | struct FileHandle {}; | ||
| 27 | |||
| 28 | // This class encapsulates a very simple file interface that has the most often-used features | ||
| 29 | class FileInterface { | ||
| 30 | public: | ||
| 31 | enum Mode { | ||
| 32 | OPEN_NO_MODE, //!< File mode not yet selected | ||
| 33 | OPEN_READ, //!< Open file for reading | ||
| 34 | OPEN_CREATE, //!< Open file for writing and truncates file if it exists, ie same flags as creat() | ||
| 35 | OPEN_WRITE, //!< Open file for writing | ||
| 36 | OPEN_SYNC_WRITE, //!< Open file for writing; writes don't return until data is on disk | ||
| 37 | OPEN_APPEND, //!< Open file for appending | ||
| 38 | MAX_OPEN_MODE //!< Maximum value of mode | ||
| 39 | }; | ||
| 40 | |||
| 41 | enum Status { | ||
| 42 | OP_OK, //!< Operation was successful | ||
| 43 | DOESNT_EXIST, //!< File doesn't exist (for read) | ||
| 44 | NO_SPACE, //!< No space left | ||
| 45 | NO_PERMISSION, //!< No permission to read/write file | ||
| 46 | BAD_SIZE, //!< Invalid size parameter | ||
| 47 | NOT_OPENED, //!< file hasn't been opened yet | ||
| 48 | FILE_EXISTS, //!< file already exist (for CREATE with O_EXCL enabled) | ||
| 49 | NOT_SUPPORTED, //!< Kernel or file system does not support operation | ||
| 50 | INVALID_MODE, //!< Mode for file access is invalid for current operation | ||
| 51 | INVALID_ARGUMENT, //!< Invalid argument passed in | ||
| 52 | NO_MORE_RESOURCES, //!< No more available resources | ||
| 53 | OTHER_ERROR, //!< A catch-all for other errors. Have to look in implementation-specific code | ||
| 54 | OUTSIDE_SANDBOX, //!< Path falls outside the configured sandbox directory | ||
| 55 | MAX_STATUS //!< Maximum value of status | ||
| 56 | }; | ||
| 57 | |||
| 58 | enum OverwriteType { | ||
| 59 | NO_OVERWRITE, //!< Do NOT overwrite existing files | ||
| 60 | OVERWRITE, //!< Overwrite file when it exists and creation was requested | ||
| 61 | MAX_OVERWRITE_TYPE | ||
| 62 | }; | ||
| 63 | |||
| 64 | enum SeekType { | ||
| 65 | RELATIVE, //!< Relative seek from current file offset | ||
| 66 | ABSOLUTE, //!< Absolute seek from beginning of file | ||
| 67 | MAX_SEEK_TYPE | ||
| 68 | }; | ||
| 69 | |||
| 70 | enum WaitType { | ||
| 71 | NO_WAIT, //!< Do not wait for read/write operation to finish | ||
| 72 | WAIT, //!< Do wait for read/write operation to finish | ||
| 73 | MAX_WAIT_TYPE | ||
| 74 | }; | ||
| 75 | |||
| 76 | 179598 | virtual ~FileInterface() = default; | |
| 77 | |||
| 78 | //! \brief open file with supplied path and mode | ||
| 79 | //! | ||
| 80 | //! Open the file passed in with the given mode. If overwrite is set to OVERWRITE, then opening files in | ||
| 81 | //! OPEN_CREATE mode will clobber existing files. Set overwrite to NO_OVERWRITE to preserve existing files. | ||
| 82 | //! The status of the open request is returned from the function call. Delegates to the chosen | ||
| 83 | //! implementation's `open` function. | ||
| 84 | //! | ||
| 85 | //! It is invalid to send `nullptr` as the path. | ||
| 86 | //! It is invalid to supply `mode` as a non-enumerated value. | ||
| 87 | //! It is invalid to supply `overwrite` as a non-enumerated value. | ||
| 88 | //! | ||
| 89 | //! \param path: c-string of path to open | ||
| 90 | //! \param mode: file operation mode | ||
| 91 | //! \param overwrite: overwrite existing file on create | ||
| 92 | //! \return: status of the open | ||
| 93 | //! | ||
| 94 | virtual Status open(const char* path, Mode mode, OverwriteType overwrite) = 0; | ||
| 95 | |||
| 96 | //! \brief close the file, if not opened then do nothing | ||
| 97 | //! | ||
| 98 | //! Closes the file, if open. Otherwise this function does nothing. Delegates to the chosen implementation's | ||
| 99 | //! `closeInternal` function. `mode` is set to `OPEN_NO_MODE`. | ||
| 100 | //! | ||
| 101 | virtual void close() = 0; | ||
| 102 | |||
| 103 | //! \brief get size of currently open file | ||
| 104 | //! | ||
| 105 | //! Get the size of the currently open file and fill the size parameter. Return status of the operation. | ||
| 106 | //! \param size: output parameter for size. | ||
| 107 | //! \return OP_OK on success otherwise error status | ||
| 108 | //! | ||
| 109 | virtual Status size(FwSizeType& size_result) = 0; | ||
| 110 | |||
| 111 | //! \brief get file pointer position of the currently open file | ||
| 112 | //! | ||
| 113 | //! Get the current position of the read/write pointer of the open file. | ||
| 114 | //! \param position: output parameter for size. | ||
| 115 | //! \return OP_OK on success otherwise error status | ||
| 116 | //! | ||
| 117 | virtual Status position(FwSizeType& position_result) = 0; | ||
| 118 | |||
| 119 | //! \brief pre-allocate file storage | ||
| 120 | //! | ||
| 121 | //! Pre-allocates file storage with at least `length` storage starting at `offset`. No-op on implementations | ||
| 122 | //! that cannot pre-allocate. | ||
| 123 | //! | ||
| 124 | //! It is invalid to pass a negative `offset`. | ||
| 125 | //! It is invalid to pass a negative `length`. | ||
| 126 | //! | ||
| 127 | //! \param offset: offset into file | ||
| 128 | //! \param length: length after offset to preallocate | ||
| 129 | //! \return OP_OK on success otherwise error status | ||
| 130 | //! | ||
| 131 | virtual Status preallocate(FwSizeType offset, FwSizeType length) = 0; | ||
| 132 | |||
| 133 | //! \brief seek the file pointer to the given offset | ||
| 134 | //! | ||
| 135 | //! Seek the file pointer to the given `offset`. If `seekType` is set to `ABSOLUTE` then the offset is calculated | ||
| 136 | //! from the start of the file, and if it is set to `RELATIVE` it is calculated from the current position. | ||
| 137 | //! | ||
| 138 | //! \param offset: offset to seek to | ||
| 139 | //! \param seekType: `ABSOLUTE` for seeking from beginning of file, `RELATIVE` to use current position. | ||
| 140 | //! \return OP_OK on success otherwise error status | ||
| 141 | //! | ||
| 142 | virtual Status seek(FwSignedSizeType offset, SeekType seekType) = 0; | ||
| 143 | |||
| 144 | //! \brief flush file contents to storage | ||
| 145 | //! | ||
| 146 | //! Flushes the file contents to storage (i.e. out of the OS cache to disk). Does nothing in implementations | ||
| 147 | //! that do not support flushing. | ||
| 148 | //! | ||
| 149 | //! \return OP_OK on success otherwise error status | ||
| 150 | //! | ||
| 151 | virtual Status flush() = 0; | ||
| 152 | |||
| 153 | //! \brief read data from this file into supplied buffer bounded by size | ||
| 154 | //! | ||
| 155 | //! Read data from this file up to the `size` and store it in `buffer`. When `wait` is set to `WAIT`, this | ||
| 156 | //! will block until the requested size has been read successfully read or the end of the file has been | ||
| 157 | //! reached. When `wait` is set to `NO_WAIT` it will return whatever data is currently available. | ||
| 158 | //! | ||
| 159 | //! `size` will be updated to the count of bytes actually read. Status will reflect the success/failure of | ||
| 160 | //! the read operation. | ||
| 161 | //! | ||
| 162 | //! It is invalid to pass `nullptr` to this function call. | ||
| 163 | //! It is invalid to pass a negative `size`. | ||
| 164 | //! It is invalid to supply wait as a non-enumerated value. | ||
| 165 | //! | ||
| 166 | //! \param buffer: memory location to store data read from file | ||
| 167 | //! \param size: size of data to read | ||
| 168 | //! \param wait: `WAIT` to wait for data, `NO_WAIT` to return what is currently available | ||
| 169 | //! \return OP_OK on success otherwise error status | ||
| 170 | //! | ||
| 171 | virtual Status read(U8* buffer, FwSizeType& size, WaitType wait) = 0; | ||
| 172 | |||
| 173 | //! \brief read data from this file into supplied buffer bounded by size | ||
| 174 | //! | ||
| 175 | //! Write data to this file up to the `size` from the `buffer`. When `wait` is set to `WAIT`, this | ||
| 176 | //! will block until the requested size has been written successfully to disk. When `wait` is set to | ||
| 177 | //! `NO_WAIT` it will return once the data is sent to the OS. | ||
| 178 | //! | ||
| 179 | //! `size` will be updated to the count of bytes actually written. Status will reflect the success/failure of | ||
| 180 | //! the read operation. | ||
| 181 | //! | ||
| 182 | //! It is invalid to pass `nullptr` to this function call. | ||
| 183 | //! It is invalid to pass a negative `size`. | ||
| 184 | //! It is invalid to supply wait as a non-enumerated value. | ||
| 185 | //! | ||
| 186 | //! \param buffer: memory location to store data read from file | ||
| 187 | //! \param size: size of data to read | ||
| 188 | //! \param wait: `WAIT` to wait for data to write to disk, `NO_WAIT` to return what is currently available | ||
| 189 | //! \return OP_OK on success otherwise error status | ||
| 190 | //! | ||
| 191 | virtual Status write(const U8* buffer, FwSizeType& size, WaitType wait) = 0; | ||
| 192 | |||
| 193 | //! \brief returns the raw file handle | ||
| 194 | //! | ||
| 195 | //! Gets the raw file handle from the implementation. Note: users must include the implementation specific | ||
| 196 | //! header to make any real use of this handle. Otherwise it will be as an opaque type. | ||
| 197 | //! | ||
| 198 | //! \return raw file handle | ||
| 199 | //! | ||
| 200 | virtual FileHandle* getHandle() = 0; | ||
| 201 | |||
| 202 | //! \brief provide a pointer to a file delegate object | ||
| 203 | //! | ||
| 204 | //! This function must return a pointer to a `FileInterface` object that contains the real implementation of the | ||
| 205 | //! file functions as defined by the implementor. This function must do several things to be considered correctly | ||
| 206 | //! implemented: | ||
| 207 | //! | ||
| 208 | //! 1. Assert that the supplied memory is non-null. e.g `FW_ASSERT(aligned_placement_new_memory != NULL);` | ||
| 209 | //! 2. Assert that their implementation fits within FW_HANDLE_MAX_SIZE. | ||
| 210 | //! e.g. `static_assert(sizeof(PosixFileImplementation) <= sizeof Os::File::m_handle_storage, | ||
| 211 | //! "FW_HANDLE_MAX_SIZE too small");` | ||
| 212 | //! 3. Assert that their implementation aligns within FW_HANDLE_ALIGNMENT. | ||
| 213 | //! e.g. `static_assert((FW_HANDLE_ALIGNMENT % alignof(PosixFileImplementation)) == 0, "Bad handle alignment");` | ||
| 214 | //! 4. If to_copy is null, placement new their implementation into `aligned_placement_new_memory` | ||
| 215 | //! e.g. `FileInterface* interface = new (aligned_placement_new_memory) PosixFileImplementation;` | ||
| 216 | //! 5. If to_copy is non-null, placement new using copy constructor their implementation into | ||
| 217 | //! `aligned_placement_new_memory` | ||
| 218 | //! e.g. `FileInterface* interface = new (aligned_placement_new_memory) PosixFileImplementation(*to_copy);` | ||
| 219 | //! 6. Return the result of the placement new | ||
| 220 | //! e.g. `return interface;` | ||
| 221 | //! | ||
| 222 | //! \return result of placement new, must be equivalent to `aligned_placement_new_memory` | ||
| 223 | //! | ||
| 224 | static FileInterface* getDelegate(FileHandleStorage& aligned_placement_new_memory, | ||
| 225 | const FileInterface* to_copy = nullptr); | ||
| 226 | }; | ||
| 227 | |||
| 228 | class File final : public FileInterface { | ||
| 229 | friend struct Os::Test::FileTest::Tester; | ||
| 230 | |||
| 231 | public: | ||
| 232 | //! \brief constructor | ||
| 233 | //! | ||
| 234 | File(); | ||
| 235 | //! \brief destructor | ||
| 236 | //! | ||
| 237 | //! Destructor closes the file if it is open | ||
| 238 | ~File() final; | ||
| 239 | |||
| 240 | //! \brief copy constructor that copies the internal representation | ||
| 241 | File(const File& other); | ||
| 242 | |||
| 243 | //! \brief assignment operator that copies the internal representation | ||
| 244 | File& operator=(const File& other); | ||
| 245 | |||
| 246 | //! \brief determine if the file is open | ||
| 247 | //! \return true if file is open, false otherwise | ||
| 248 | //! | ||
| 249 | bool isOpen() const; | ||
| 250 | |||
| 251 | // ------------------------------------ | ||
| 252 | // Functions supplying default values | ||
| 253 | // ------------------------------------ | ||
| 254 | |||
| 255 | //! \brief open file with supplied path and mode | ||
| 256 | //! | ||
| 257 | //! Open the file passed in with the given mode. Opening files with `OPEN_CREATE` mode will not clobber existing | ||
| 258 | //! files. Use other `open` method to set overwrite flag and clobber existing files. The status of the open | ||
| 259 | //! request is returned from the function call. Delegates to the chosen implementation's `open` function. | ||
| 260 | //! | ||
| 261 | //! It is invalid to send `nullptr` as the path. | ||
| 262 | //! It is invalid to supply `mode` as a non-enumerated value. | ||
| 263 | //! | ||
| 264 | //! \param path: c-string of path to open | ||
| 265 | //! \param mode: file operation mode | ||
| 266 | //! \return: status of the open | ||
| 267 | //! | ||
| 268 | Os::FileInterface::Status open(const char* path, Mode mode); | ||
| 269 | |||
| 270 | //! \brief open file with supplied path, bounded length, and mode | ||
| 271 | //! | ||
| 272 | //! Open the file passed in with the given mode. The path length is bounded by `length`. | ||
| 273 | //! Opening files with `OPEN_CREATE` mode will not clobber existing files. Use the overload | ||
| 274 | //! accepting `OverwriteType` to set overwrite flag and clobber existing files. | ||
| 275 | //! | ||
| 276 | //! It is invalid to send `nullptr` as the path. | ||
| 277 | //! It is invalid to supply `mode` as a non-enumerated value. | ||
| 278 | //! It is invalid for the path to not be null-terminated within `length` characters. | ||
| 279 | //! | ||
| 280 | //! \param path: c-string of path to open | ||
| 281 | //! \param length: bound on the path buffer size | ||
| 282 | //! \param mode: file operation mode | ||
| 283 | //! \return: status of the open | ||
| 284 | //! | ||
| 285 | Os::FileInterface::Status open(const char* path, FwSizeType length, Mode mode); | ||
| 286 | |||
| 287 | //! \brief open file with supplied string path and mode | ||
| 288 | //! | ||
| 289 | //! Open the file passed in with the given mode. Opening files with `OPEN_CREATE` mode will not clobber existing | ||
| 290 | //! files. Use the overload accepting `OverwriteType` to set overwrite flag and clobber existing files. | ||
| 291 | //! | ||
| 292 | //! It is invalid to supply `mode` as a non-enumerated value. | ||
| 293 | //! | ||
| 294 | //! \param path: ConstStringBase reference of path to open | ||
| 295 | //! \param mode: file operation mode | ||
| 296 | //! \return: status of the open | ||
| 297 | //! | ||
| 298 | Os::FileInterface::Status open(const Fw::ConstStringBase& path, Mode mode); | ||
| 299 | |||
| 300 | //! \brief open file with supplied string path, mode, and overwrite type | ||
| 301 | //! | ||
| 302 | //! Open the file passed in with the given mode. If overwrite is set to OVERWRITE, then opening files in | ||
| 303 | //! OPEN_CREATE mode will clobber existing files. Set overwrite to NO_OVERWRITE to preserve existing files. | ||
| 304 | //! | ||
| 305 | //! It is invalid to supply `mode` as a non-enumerated value. | ||
| 306 | //! It is invalid to supply `overwrite` as a non-enumerated value. | ||
| 307 | //! | ||
| 308 | //! \param path: ConstStringBase reference of path to open | ||
| 309 | //! \param mode: file operation mode | ||
| 310 | //! \param overwrite: overwrite existing file on create | ||
| 311 | //! \return: status of the open | ||
| 312 | //! | ||
| 313 | Os::FileInterface::Status open(const Fw::ConstStringBase& path, Mode mode, OverwriteType overwrite); | ||
| 314 | |||
| 315 | //! \brief read data from this file into supplied buffer bounded by size | ||
| 316 | //! | ||
| 317 | //! Read data from this file up to the `size` and store it in `buffer`. This version will | ||
| 318 | //! will block until the requested size has been read successfully read or the end of the file has been | ||
| 319 | //! reached. | ||
| 320 | //! | ||
| 321 | //! `size` will be updated to the count of bytes actually read. Status will reflect the success/failure of | ||
| 322 | //! the read operation. | ||
| 323 | //! | ||
| 324 | //! It is invalid to pass `nullptr` to this function call. | ||
| 325 | //! It is invalid to pass a negative `size`. | ||
| 326 | //! | ||
| 327 | //! \param buffer: memory location to store data read from file | ||
| 328 | //! \param size: size of data to read | ||
| 329 | //! \return OP_OK on success otherwise error status | ||
| 330 | //! | ||
| 331 | Status read(U8* buffer, FwSizeType& size); | ||
| 332 | |||
| 333 | //! \brief write data to this file from the supplied buffer bounded by size | ||
| 334 | //! | ||
| 335 | //! Write data from `buffer` up to the `size` and store it in this file. This call | ||
| 336 | //! will block until the requested size has been written. Otherwise, this call will write without blocking. | ||
| 337 | //! | ||
| 338 | //! `size` will be updated to the count of bytes actually written. Status will reflect the success/failure of | ||
| 339 | //! the write operation. | ||
| 340 | //! | ||
| 341 | //! It is invalid to pass `nullptr` to this function call. | ||
| 342 | //! It is invalid to pass a negative `size`. | ||
| 343 | //! | ||
| 344 | //! \param buffer: memory location of data to write to file | ||
| 345 | //! \param size: size of data to write | ||
| 346 | //! \return OP_OK on success otherwise error status | ||
| 347 | //! | ||
| 348 | Status write(const U8* buffer, FwSizeType& size); | ||
| 349 | |||
| 350 | // ------------------------------------ | ||
| 351 | // Functions overrides | ||
| 352 | // ------------------------------------ | ||
| 353 | |||
| 354 | //! \brief open file with supplied path and mode | ||
| 355 | //! | ||
| 356 | //! Open the file passed in with the given mode. If overwrite is set to OVERWRITE, then opening files in | ||
| 357 | //! OPEN_CREATE mode will clobber existing files. Set overwrite to NO_OVERWRITE to preserve existing files. | ||
| 358 | //! The status of the open request is returned from the function call. Delegates to the chosen | ||
| 359 | //! implementation's `open` function. | ||
| 360 | //! | ||
| 361 | //! It is invalid to send `nullptr` as the path. | ||
| 362 | //! It is invalid to supply `mode` as a non-enumerated value. | ||
| 363 | //! It is invalid to supply `overwrite` as a non-enumerated value. | ||
| 364 | //! | ||
| 365 | //! \param path: c-string of path to open | ||
| 366 | //! \param mode: file operation mode | ||
| 367 | //! \param overwrite: overwrite existing file on create | ||
| 368 | //! \return: status of the open | ||
| 369 | //! | ||
| 370 | Os::FileInterface::Status open(const char* path, Mode mode, OverwriteType overwrite) override; | ||
| 371 | |||
| 372 | //! \brief open file with supplied path, bounded length, mode, and overwrite type | ||
| 373 | //! | ||
| 374 | //! Open the file passed in with the given mode. The path length is bounded by `length`. | ||
| 375 | //! If overwrite is set to OVERWRITE, then opening files in OPEN_CREATE mode will clobber | ||
| 376 | //! existing files. Set overwrite to NO_OVERWRITE to preserve existing files. This is the | ||
| 377 | //! core open implementation to which all other open overloads delegate. | ||
| 378 | //! | ||
| 379 | //! It is invalid to send `nullptr` as the path. | ||
| 380 | //! It is invalid to supply `mode` as a non-enumerated value. | ||
| 381 | //! It is invalid to supply `overwrite` as a non-enumerated value. | ||
| 382 | //! It is invalid for the path to not be null-terminated within `length` characters. | ||
| 383 | //! | ||
| 384 | //! \param path: c-string of path to open | ||
| 385 | //! \param length: bound on the path buffer size | ||
| 386 | //! \param mode: file operation mode | ||
| 387 | //! \param overwrite: overwrite existing file on create | ||
| 388 | //! \return: status of the open | ||
| 389 | //! | ||
| 390 | Os::FileInterface::Status open(const char* path, FwSizeType length, Mode mode, OverwriteType overwrite); | ||
| 391 | |||
| 392 | //! \brief close the file, if not opened then do nothing | ||
| 393 | //! | ||
| 394 | //! Closes the file, if open. Otherwise this function does nothing. Delegates to the chosen implementation's | ||
| 395 | //! `closeInternal` function. `mode` is set to `OPEN_NO_MODE`. | ||
| 396 | //! | ||
| 397 | void close() override; | ||
| 398 | |||
| 399 | //! \brief get size of currently open file | ||
| 400 | //! | ||
| 401 | //! Get the size of the currently open file and fill the size parameter. Return status of the operation. | ||
| 402 | //! \param size: output parameter for size. | ||
| 403 | //! \return OP_OK on success otherwise error status | ||
| 404 | //! | ||
| 405 | Status size(FwSizeType& size_result) override; | ||
| 406 | |||
| 407 | //! \brief get file pointer position of the currently open file | ||
| 408 | //! | ||
| 409 | //! Get the current position of the read/write pointer of the open file. | ||
| 410 | //! \param position: output parameter for size. | ||
| 411 | //! \return OP_OK on success otherwise error status | ||
| 412 | //! | ||
| 413 | Status position(FwSizeType& position_result) override; | ||
| 414 | |||
| 415 | //! \brief pre-allocate file storage | ||
| 416 | //! | ||
| 417 | //! Pre-allocates file storage with at least `length` storage starting at `offset`. No-op on implementations | ||
| 418 | //! that cannot pre-allocate. | ||
| 419 | //! | ||
| 420 | //! It is invalid to pass a negative `offset`. | ||
| 421 | //! It is invalid to pass a negative `length`. | ||
| 422 | //! | ||
| 423 | //! \param offset: offset into file | ||
| 424 | //! \param length: length after offset to preallocate | ||
| 425 | //! \return OP_OK on success otherwise error status | ||
| 426 | //! | ||
| 427 | Status preallocate(FwSizeType offset, FwSizeType length) override; | ||
| 428 | |||
| 429 | //! \brief seek the file pointer to the given offset | ||
| 430 | //! | ||
| 431 | //! Seek the file pointer to the given `offset`. If `seekType` is set to `ABSOLUTE` then the offset is calculated | ||
| 432 | //! from the start of the file, and if it is set to `RELATIVE` it is calculated from the current position. | ||
| 433 | //! | ||
| 434 | //! \param offset: offset to seek to | ||
| 435 | //! \param seekType: `ABSOLUTE` for seeking from beginning of file, `RELATIVE` to use current position. | ||
| 436 | //! \return OP_OK on success otherwise error status | ||
| 437 | //! | ||
| 438 | Status seek(FwSignedSizeType offset, SeekType seekType) override; | ||
| 439 | |||
| 440 | //! \brief seek the file pointer to the given offset absolutely with the full range | ||
| 441 | //! | ||
| 442 | //! Seek the file pointer to the given `offset` absolutely from the beginning of the file. This function is | ||
| 443 | //! equivalent to calling `seek` with `ABSOLUTE` as the `seekType` with the exception that it can handle the | ||
| 444 | //! full range of `FwSizeType` values as returned by `size` and `position` calls. | ||
| 445 | //! | ||
| 446 | //! Internally, it will perform multiple seeks to reach the desired offset while never exceeding the signed | ||
| 447 | //! limit of the basic `seek` function. | ||
| 448 | //! | ||
| 449 | //! \param offset_unsigned: offset to absolutely seek to | ||
| 450 | //! \return OP_OK on success otherwise error status | ||
| 451 | Status seek_absolute(FwSizeType offset_unsigned); | ||
| 452 | |||
| 453 | //! \brief flush file contents to storage | ||
| 454 | //! | ||
| 455 | //! Flushes the file contents to storage (i.e. out of the OS cache to disk). Does nothing in implementations | ||
| 456 | //! that do not support flushing. | ||
| 457 | //! | ||
| 458 | //! \return OP_OK on success otherwise error status | ||
| 459 | //! | ||
| 460 | Status flush() override; | ||
| 461 | |||
| 462 | //! \brief read data from this file into supplied buffer bounded by size | ||
| 463 | //! | ||
| 464 | //! Read data from this file up to the `size` and store it in `buffer`. When `wait` is set to `WAIT`, this | ||
| 465 | //! will block until the requested size has been read successfully read or the end of the file has been | ||
| 466 | //! reached. When `wait` is set to `NO_WAIT` it will return whatever data is currently available. | ||
| 467 | //! | ||
| 468 | //! `size` will be updated to the count of bytes actually read. Status will reflect the success/failure of | ||
| 469 | //! the read operation. | ||
| 470 | //! | ||
| 471 | //! It is invalid to pass `nullptr` to this function call. | ||
| 472 | //! It is invalid to pass a negative `size`. | ||
| 473 | //! It is invalid to supply wait as a non-enumerated value. | ||
| 474 | //! | ||
| 475 | //! \param buffer: memory location to store data read from file | ||
| 476 | //! \param size: size of data to read | ||
| 477 | //! \param wait: `WAIT` to wait for data, `NO_WAIT` to return what is currently available | ||
| 478 | |||
| 479 | //! | ||
| 480 | Status read(U8* buffer, FwSizeType& size, WaitType wait) override; | ||
| 481 | |||
| 482 | //! \brief read a line from the file using `\n` as the delimiter | ||
| 483 | //! | ||
| 484 | //! Reads a single line from the file including the terminating '\n'. This will return an error if no line is | ||
| 485 | //! found within the specified buffer size. In the case of EOF, the line is read without the terminating '\n'. | ||
| 486 | //! | ||
| 487 | //! In the case of an error, this function will seek to the original location in the file. Otherwise, the | ||
| 488 | //! pointer will point to the first character after the `\n` or EOF in the case of no `\n`. | ||
| 489 | //! | ||
| 490 | //! It is invalid to send a null buffer. | ||
| 491 | //! It is invalid to send a size less than 0. | ||
| 492 | //! It is an error if the file is not opened for reading. | ||
| 493 | //! | ||
| 494 | //! \param buffer: memory location to store data read from file | ||
| 495 | //! \param size: maximum size of buffer to store the new line | ||
| 496 | //! \param wait: `WAIT` to wait for data, `NO_WAIT` to return what is currently available | ||
| 497 | //! \return OP_OK on success otherwise error status | ||
| 498 | Status readline(U8* buffer, FwSizeType& size, WaitType wait); | ||
| 499 | |||
| 500 | //! \brief read data from this file into supplied buffer bounded by size | ||
| 501 | //! | ||
| 502 | //! Write data to this file up to the `size` from the `buffer`. When `wait` is set to `WAIT`, this | ||
| 503 | //! will block until the requested size has been written successfully to disk. When `wait` is set to | ||
| 504 | //! `NO_WAIT` it will return once the data is sent to the OS. | ||
| 505 | //! | ||
| 506 | //! `size` will be updated to the count of bytes actually written. Status will reflect the success/failure of | ||
| 507 | //! the read operation. | ||
| 508 | //! | ||
| 509 | //! It is invalid to pass `nullptr` to this function call. | ||
| 510 | //! It is invalid to pass a negative `size`. | ||
| 511 | //! It is invalid to supply wait as a non-enumerated value. | ||
| 512 | //! | ||
| 513 | //! \param buffer: memory location to store data read from file | ||
| 514 | //! \param size: size of data to read | ||
| 515 | //! \param wait: `WAIT` to wait for data to write to disk, `NO_WAIT` to return what is currently available | ||
| 516 | //! \return OP_OK on success otherwise error status | ||
| 517 | //! | ||
| 518 | Status write(const U8* buffer, FwSizeType& size, WaitType wait) override; | ||
| 519 | |||
| 520 | //! \brief returns the raw file handle | ||
| 521 | //! | ||
| 522 | //! Gets the raw file handle from the implementation. Note: users must include the implementation specific | ||
| 523 | //! header to make any real use of this handle. Otherwise it//!must* be passed as an opaque type. | ||
| 524 | //! | ||
| 525 | //! \return raw file handle | ||
| 526 | //! | ||
| 527 | FileHandle* getHandle() override; | ||
| 528 | |||
| 529 | //! \brief calculate the CRC32 of the entire file | ||
| 530 | //! | ||
| 531 | //! Calculates the CRC32 of the file's contents. The `crc` parameter will be updated to contain the CRC or 0 on | ||
| 532 | //! failure. Status will represent failure conditions. This call will be decomposed into calculations on | ||
| 533 | //! sections of the file `FW_FILE_CHUNK_SIZE` bytes long. | ||
| 534 | //! | ||
| 535 | //! This function requires that the file already be opened for "READ" mode. | ||
| 536 | //! | ||
| 537 | //! On error crc will be set to 0. | ||
| 538 | //! | ||
| 539 | //! \note: the file pointer will be positioned at the end of the file after this call. | ||
| 540 | //! | ||
| 541 | //! This function is equivalent to the following pseudo-code: | ||
| 542 | //! | ||
| 543 | //! ``` | ||
| 544 | //! U32 crc; | ||
| 545 | //! do { | ||
| 546 | //! size = FW_FILE_CHUNK_SIZE; | ||
| 547 | //! m_file.incrementalCrc(size); | ||
| 548 | //! while (size == FW_FILE_CHUNK_SIZE); | ||
| 549 | //! m_file.finalize(crc); | ||
| 550 | //! ``` | ||
| 551 | //! \param crc: U32 bit value to fill with CRC | ||
| 552 | //! \return OP_OK on success otherwise error status | ||
| 553 | //! | ||
| 554 | Status calculateCrc(U32& crc); | ||
| 555 | |||
| 556 | //! \brief calculate the CRC32 of the next section of data | ||
| 557 | //! | ||
| 558 | //! Starting at the current file pointer, this will add `size` bytes of data to the currently calculated CRC. | ||
| 559 | //! Call `finalizeCrc` to retrieve the CRC or `calculateCrc` to perform a CRC on the entire file. This call will | ||
| 560 | //! not block waiting for data on the underlying read, nor will it reset the file position pointer. On error, | ||
| 561 | //! the current CRC results should be discarded by reopening the file or calling `finalizeCrc` and | ||
| 562 | //! discarding its result. `size` will be updated with the `size` actually read and used in the CRC calculation. | ||
| 563 | //! | ||
| 564 | //! This function requires that the file already be opened for "READ" mode. | ||
| 565 | //! | ||
| 566 | //! It is illegal for size to be less than or equal to 0 or greater than FW_FILE_CHUNK_SIZE. | ||
| 567 | //! | ||
| 568 | //! \param size: size of data to read for CRC | ||
| 569 | //! \return: status of the CRC calculation | ||
| 570 | //! | ||
| 571 | Status incrementalCrc(FwSizeType& size); | ||
| 572 | |||
| 573 | //! \brief finalize and retrieve the CRC value | ||
| 574 | //! | ||
| 575 | //! Finalizes the CRC computation and returns the CRC value. The `crc` value will be modified to contain the | ||
| 576 | //! crc or 0 on error. Note: this will reset any active CRC calculation and effectively re-initializes any | ||
| 577 | //! `incrementalCrc` calculation. | ||
| 578 | //! | ||
| 579 | //! On error crc will be set to 0. | ||
| 580 | //! | ||
| 581 | //! \param crc: value to fill | ||
| 582 | //! \return status of the CRC calculation | ||
| 583 | //! | ||
| 584 | Status finalizeCrc(U32& crc); | ||
| 585 | |||
| 586 | private: | ||
| 587 | static const U32 INITIAL_CRC = 0xFFFFFFFF; //!< Initial value for CRC calculation | ||
| 588 | |||
| 589 | Mode m_mode = Mode::OPEN_NO_MODE; //!< Stores mode for error checking | ||
| 590 | |||
| 591 | Utils::Hash m_hash; //!< Hash object for incremental CRC calculation | ||
| 592 | U8 m_crc_buffer[FW_FILE_CHUNK_SIZE]; | ||
| 593 | |||
| 594 | // This section is used to store the implementation-defined file handle. To Os::File and fprime, this type is | ||
| 595 | // opaque and thus normal allocation cannot be done. Instead, we allow the implementor to store then handle in | ||
| 596 | // the byte-array here and set `handle` to that address for storage. | ||
| 597 | // | ||
| 598 | alignas(FW_HANDLE_ALIGNMENT) FileHandleStorage m_handle_storage; //!< Storage for aligned FileHandle data | ||
| 599 | FileInterface& m_delegate; //!< Delegate for the real implementation | ||
| 600 | }; | ||
| 601 | } // namespace Os | ||
| 602 | #endif | ||
| 603 |