F´ Flight Software - C/C++ Documentation
A framework for building embedded system applications to NASA flight quality standards.
FileSystem.cpp
Go to the documentation of this file.
1 // ======================================================================
2 // \title Os/FileSystem.cpp
3 // \brief common function implementation for Os::FileSystem
4 // ======================================================================
5 #include <Fw/Types/Assert.hpp>
6 #include <Os/FileSystem.hpp>
7 
8 namespace Os {
9 
10 FileSystem::FileSystem() : m_handle_storage(), m_delegate(*FileSystemInterface::getDelegate(m_handle_storage)) {
11  FW_ASSERT(&this->m_delegate == reinterpret_cast<FileSystemInterface*>(&this->m_handle_storage[0]));
12 }
13 
15  FW_ASSERT(&this->m_delegate == reinterpret_cast<FileSystemInterface*>(&this->m_handle_storage[0]));
16  m_delegate.~FileSystemInterface();
17 }
18 
20  FW_ASSERT(&this->m_delegate == reinterpret_cast<FileSystemInterface*>(&this->m_handle_storage[0]));
21  return this->m_delegate.getHandle();
22 }
23 
25  FW_ASSERT(&this->m_delegate == reinterpret_cast<FileSystemInterface*>(&this->m_handle_storage[0]));
26  FW_ASSERT(path != nullptr);
27  return this->m_delegate._removeDirectory(path);
28 }
29 
31  FW_ASSERT(&this->m_delegate == reinterpret_cast<FileSystemInterface*>(&this->m_handle_storage[0]));
32  FW_ASSERT(path != nullptr);
33  return this->m_delegate._removeFile(path);
34 }
35 
36 FileSystem::Status FileSystem::_rename(const char* sourcePath, const char* destPath) {
37  FW_ASSERT(&this->m_delegate == reinterpret_cast<FileSystemInterface*>(&this->m_handle_storage[0]));
38  FW_ASSERT(sourcePath != nullptr);
39  FW_ASSERT(destPath != nullptr);
40  return this->m_delegate._rename(sourcePath, destPath);
41 }
42 
44  FW_ASSERT(&this->m_delegate == reinterpret_cast<FileSystemInterface*>(&this->m_handle_storage[0]));
45  FW_ASSERT(path != nullptr);
46  FW_ASSERT(bufferSize > 0); // because bufferSize=0 would trigger a malloc in some implementations (e.g. Posix)
47  return this->m_delegate._getWorkingDirectory(path, bufferSize);
48 }
49 
51  FW_ASSERT(&this->m_delegate == reinterpret_cast<FileSystemInterface*>(&this->m_handle_storage[0]));
52  FW_ASSERT(path != nullptr);
53  return this->m_delegate._changeWorkingDirectory(path);
54 }
55 
56 FileSystem::Status FileSystem::_getFreeSpace(const char* path, FwSizeType& totalBytes, FwSizeType& freeBytes) {
57  FW_ASSERT(&this->m_delegate == reinterpret_cast<FileSystemInterface*>(&this->m_handle_storage[0]));
58  FW_ASSERT(path != nullptr);
59  return this->m_delegate._getFreeSpace(path, totalBytes, freeBytes);
60 }
61 
63  // Force trigger on the fly singleton setup
64  (void) FileSystem::getSingleton();
65 }
66 
68  static FileSystem s_singleton;
69  return s_singleton;
70 }
71 
72 
73 // ------------------------------------------------------------
74 // Static functions calling implementation-specific operations
75 // ------------------------------------------------------------
76 
79 }
80 
83 }
84 
85 FileSystem::Status FileSystem::rename(const char* sourcePath, const char* destPath) {
86  return FileSystem::getSingleton()._rename(sourcePath, destPath);
87 }
88 
90  return FileSystem::getSingleton()._getWorkingDirectory(path, bufferSize);
91 }
92 
95 }
96 
97 FileSystem::Status FileSystem::getFreeSpace(const char* path, FwSizeType& totalBytes, FwSizeType& freeBytes) {
98  return FileSystem::getSingleton()._getFreeSpace(path, totalBytes, freeBytes);
99 }
100 
101 
102 // ------------------------------------------------------------
103 // Additional functions built on top of OS-specific operations
104 // ------------------------------------------------------------
105 
106 FileSystem::Status FileSystem::createDirectory(const char* path, bool errorIfAlreadyExists) {
107  FW_ASSERT(path != nullptr);
108  Status status = Status::OP_OK;
109  Os::Directory dir;
110  // If errorIfAlreadyExists is true, use CREATE_EXCLUSIVE mode, otherwise use CREATE_IF_MISSING
111  Directory::OpenMode mode = errorIfAlreadyExists ? Directory::OpenMode::CREATE_EXCLUSIVE : Directory::OpenMode::CREATE_IF_MISSING;
112  Directory::Status dirStatus = dir.open(path, mode);
113  dir.close();
114  if (dirStatus != Directory::OP_OK) {
115  return FileSystem::handleDirectoryError(dirStatus);
116  }
117  return status;
118 }
119 
121  FW_ASSERT(path != nullptr);
122  Status status = Status::OP_OK;
123  Os::File file;
124  File::Status file_status = file.open(path, Os::File::OPEN_WRITE);
125  file.close();
126  if (file_status != File::OP_OK) {
127  status = FileSystem::handleFileError(file_status);
128  }
129  return status;
130 }
131 
133  FW_ASSERT(path != nullptr);
134  Os::File file;
135  File::Status file_status = file.open(path, Os::File::OPEN_READ);
136  file.close();
137  if (file_status == File::OP_OK) {
138  return PathType::FILE;
139  }
140  Os::Directory dir;
141  Directory::Status dir_status = dir.open(path, Os::Directory::OpenMode::READ);
142  dir.close();
143  if (dir_status == Directory::Status::OP_OK) {
144  return PathType::DIRECTORY;
145  }
146  return PathType::NOT_EXIST;
147 } // end getPathType
148 
149 bool FileSystem::exists(const char* path) {
150  return FileSystem::getPathType(path) != PathType::NOT_EXIST;
151 } // end exists
152 
153 FileSystem::Status FileSystem::copyFile(const char* sourcePath, const char* destPath) {
154  FW_ASSERT(sourcePath != nullptr);
155  FW_ASSERT(destPath != nullptr);
156  Os::File source;
157  Os::File destination;
158  Os::File::Status fileStatus = source.open(sourcePath, Os::File::OPEN_READ);
159  if (fileStatus != Os::File::OP_OK) {
160  return FileSystem::handleFileError(fileStatus);
161  }
162  fileStatus = destination.open(destPath, Os::File::OPEN_WRITE);
163  if (fileStatus != Os::File::OP_OK) {
164  return FileSystem::handleFileError(fileStatus);
165  }
166 
167  FwSignedSizeType sourceFileSize = 0;
168  FileSystem::Status fs_status = FileSystem::getFileSize(sourcePath, sourceFileSize);
169  if (fs_status != FileSystem::Status::OP_OK) {
170  return fs_status;
171  }
172 
173  fs_status = FileSystem::copyFileData(source, destination, sourceFileSize);
174 
175  return fs_status;
176 } // end copyFile
177 
178 FileSystem::Status FileSystem::appendFile(const char* sourcePath, const char* destPath, bool createMissingDest) {
179  Os::File source;
180  Os::File destination;
181 
182  // If requested, check if destination file exists and exit if does not exist
183  if (not createMissingDest and not FileSystem::exists(destPath)) {
184  return Status::DOESNT_EXIST;
185  }
186 
187  Os::File::Status fileStatus = source.open(sourcePath, Os::File::OPEN_READ);
188  if (fileStatus != Os::File::OP_OK) {
189  return FileSystem::handleFileError(fileStatus);
190  }
191  fileStatus = destination.open(destPath, Os::File::OPEN_APPEND);
192  if (fileStatus != Os::File::OP_OK) {
193  return FileSystem::handleFileError(fileStatus);
194  }
195 
197 
198  FwSignedSizeType sourceFileSize = 0;
199  fs_status = FileSystem::getFileSize(sourcePath, sourceFileSize);
200  if (fs_status != FileSystem::Status::OP_OK) {
201  return fs_status;
202  }
203 
204  fs_status = FileSystem::copyFileData(source, destination, sourceFileSize);
205 
206  return fs_status;
207 } // end appendFile
208 
209 FileSystem::Status FileSystem::moveFile(const char* source, const char* destination) {
210  Status status = Status::OP_OK;
211 
212  // Try to rename the file
213  status = FileSystem::rename(source, destination);
214 
215  // If rename fails because of cross-device rename, attempt to copy and remove instead
216  if (status == Status::EXDEV_ERROR) {
217  status = FileSystem::copyFile(source, destination);
218  if (status != Status::OP_OK) {
219  return status;
220  }
221  status = FileSystem::removeFile(source);
222  }
223 
224  return status;
225 }
226 
228  Os::File file;
229  Os::File::Status status = file.open(path, Os::File::OPEN_READ);
230  if (status != File::Status::OP_OK) {
231  return FileSystem::handleFileError(status);
232  }
233  status = file.size(size);
234  if (status != File::Status::OP_OK) {
235  return FileSystem::handleFileError(status);
236  }
237  return FileSystem::OP_OK;
238 }
239 
240 
241 // ------------------------------------------------------------
242 // Internal helper functions
243 // ------------------------------------------------------------
244 
245 FileSystem::Status FileSystem::handleFileError(File::Status fileStatus) {
247 
248  switch (fileStatus) {
249  case File::NO_SPACE:
250  status = FileSystem::NO_SPACE;
251  break;
252  case File::NO_PERMISSION:
253  status = FileSystem::NO_PERMISSION;
254  break;
255  case File::DOESNT_EXIST:
256  status = FileSystem::DOESNT_EXIST;
257  break;
258  default:
259  status = FileSystem::OTHER_ERROR;
260  }
261  return status;
262 } // end handleFileError
263 
264 FileSystem::Status FileSystem::handleDirectoryError(Directory::Status dirStatus) {
266 
267  switch (dirStatus) {
269  status = FileSystem::DOESNT_EXIST;
270  break;
272  status = FileSystem::NO_PERMISSION;
273  break;
276  break;
278  status = FileSystem::NOT_SUPPORTED;
279  break;
280  default:
281  status = FileSystem::OTHER_ERROR;
282  }
283  return status;
284 } // end handleFileError
285 
286 FileSystem::Status FileSystem::copyFileData(File& source, File& destination, FwSignedSizeType size) {
287  static_assert(FILE_SYSTEM_FILE_CHUNK_SIZE != 0, "FILE_SYSTEM_FILE_CHUNK_SIZE must be >0");
288  U8 fileBuffer[FILE_SYSTEM_FILE_CHUNK_SIZE];
289  File::Status file_status;
290 
291  FwSignedSizeType copiedSize = 0;
292  FwSignedSizeType chunkSize = FILE_SYSTEM_FILE_CHUNK_SIZE;
293 
294  // Copy the file in chunks - loop until all data is copied
295  for (copiedSize = 0; copiedSize < size; copiedSize += chunkSize) {
296  // chunkSize is FILE_SYSTEM_FILE_CHUNK_SIZE unless size-copiedSize is less than that
297  // in which case chunkSize is size-copiedSize, ensuring the last chunk reads the remaining data
298  chunkSize = FW_MIN(FILE_SYSTEM_FILE_CHUNK_SIZE, size - copiedSize);
299  file_status = source.read(fileBuffer, chunkSize, Os::File::WaitType::WAIT);
300  if (file_status != File::OP_OK) {
301  return FileSystem::handleFileError(file_status);
302  }
303  file_status = destination.write(fileBuffer, chunkSize, Os::File::WaitType::WAIT);
304  if (file_status != File::OP_OK) {
305  return FileSystem::handleFileError(file_status);
306  }
307  }
308 
309  return FileSystem::OP_OK;
310 } // end copyFileData
311 
312 } // namespace Os
FileSystemHandle * getHandle() override
return the underlying FileSystem handle (implementation specific)
Definition: FileSystem.cpp:19
static Status rename(const char *sourcePath, const char *destPath)
Rename a file from source to destination.
Definition: FileSystem.cpp:85
Operation succeeded.
Definition: Os.hpp:26
Status size(FwSignedSizeType &size_result) override
get size of currently open file
Definition: File.cpp:85
static Status moveFile(const char *sourcePath, const char *destPath)
Move a file from sourcePath to destPath.
Definition: FileSystem.cpp:209
static Status getFreeSpace(const char *path, FwSizeType &totalBytes, FwSizeType &freeBytes)
Get filesystem free and total space in bytes on the filesystem containing the specified path...
Definition: FileSystem.cpp:97
Status _getWorkingDirectory(char *path, FwSizeType bufferSize) override
Get the current working directory.
Definition: FileSystem.cpp:43
static Status removeDirectory(const char *path)
Remove a directory at the specified path.
Definition: FileSystem.cpp:77
static Status appendFile(const char *sourcePath, const char *destPath, bool createMissingDest=false)
Append the source file to the destination file.
Definition: FileSystem.cpp:178
PlatformSizeType FwSizeType
Definition: FpConfig.h:35
No permission to read/write file.
Definition: File.hpp:33
Open file for writing.
Definition: File.hpp:23
Directory doesn&#39;t exist.
Definition: Directory.hpp:21
static bool exists(const char *path)
Return true if the path exists, false otherwise.
Definition: FileSystem.cpp:149
Os::FileInterface::Status open(const char *path, Mode mode)
open file with supplied path and mode
static void init()
initialize singleton
Definition: FileSystem.cpp:62
Status _rename(const char *sourcePath, const char *destPath) override
Rename a file from source to destination.
Definition: FileSystem.cpp:36
No permission to read directory.
Definition: Directory.hpp:22
Open file for appending.
Definition: File.hpp:25
No space left.
Definition: File.hpp:32
static FileSystem & getSingleton()
get a reference to singleton
Definition: FileSystem.cpp:67
#define FW_MIN(a, b)
MIN macro.
Definition: BasicTypes.h:87
void close() override
Close directory.
Definition: Directory.cpp:72
File doesn&#39;t exist (for read)
Definition: File.hpp:31
Status _removeFile(const char *path) override
Remove a file at the specified path.
Definition: FileSystem.cpp:30
void close() override
close the file, if not opened then do nothing
Definition: File.cpp:70
Status _getFreeSpace(const char *path, FwSizeType &totalBytes, FwSizeType &freeBytes) override
Get filesystem free and total space in bytes on the filesystem containing the specified path...
Definition: FileSystem.cpp:56
Status _removeDirectory(const char *path) override
Remove a directory at the specified path.
Definition: FileSystem.cpp:24
static Status getWorkingDirectory(char *path, FwSizeType bufferSize)
Get the current working directory.
Definition: FileSystem.cpp:89
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:32
Directory class.
Definition: Directory.hpp:117
static Status createDirectory(const char *path, bool errorIfAlreadyExists=false)
Create a new directory at the specified path.
Definition: FileSystem.cpp:106
static PathType getPathType(const char *path)
Return the type of the path (file, directory, or doesn&#39;t exist)
Definition: FileSystem.cpp:132
other OS-specific error
Definition: FileSystem.hpp:41
Operation was successful.
Definition: File.hpp:30
Operation was successful.
Definition: Directory.hpp:20
Operation is not supported by the current implementation.
Definition: FileSystem.hpp:40
FileSystem class.
Definition: FileSystem.hpp:117
Open file for reading.
Definition: File.hpp:21
Status open(const char *path, OpenMode mode) override
Open or create a directory.
Definition: Directory.cpp:30
PlatformSignedSizeType FwSignedSizeType
Definition: FpConfig.h:30
static Status copyFile(const char *sourcePath, const char *destPath)
Copy a file from the source path to the destination path.
Definition: FileSystem.cpp:153
static Status getFileSize(const char *path, FwSignedSizeType &size)
Get the size of the file (in bytes) at the specified path.
Definition: FileSystem.cpp:227
Operation was successful.
Definition: FileSystem.hpp:25
Directory already exists.
Definition: Directory.hpp:28
~FileSystem() final
Destructor.
Definition: FileSystem.cpp:14
Operation is not supported by the current implementation.
Definition: Directory.hpp:29
static Status changeWorkingDirectory(const char *path)
Change the current working directory to the specified path.
Definition: FileSystem.cpp:93
Status _changeWorkingDirectory(const char *path) override
Change the current working directory to the specified path.
Definition: FileSystem.cpp:50
#define FW_ASSERT(...)
Definition: Assert.hpp:14
static Status removeFile(const char *path)
Remove a file at the specified path.
Definition: FileSystem.cpp:81
Path doesn&#39;t exist.
Definition: FileSystem.hpp:33
static Status touch(const char *path)
Touch a file at the specified path, creating it if it doesn&#39;t exist.
Definition: FileSystem.cpp:120