F´ Flight Software - C/C++ Documentation
A framework for building embedded system applications to NASA flight quality standards.
ValidateFileCommon.cpp
Go to the documentation of this file.
1 #include <Os/File.hpp>
2 #include <Os/FileSystem.hpp>
3 #include <Os/ValidateFile.hpp>
4 #include <Utils/Hash/Hash.hpp>
5 
6 namespace Os {
7 
8 File::Status computeHash(const char* fileName, Utils::HashBuffer& hashBuffer) {
9  File::Status status;
10 
11  // Open file:
12  File file;
13  status = file.open(fileName, File::OPEN_READ);
14  if (File::OP_OK != status) {
15  return status;
16  }
17 
18  // Get the file size:
19  FileSystem::Status fs_status;
20  FwSizeType fileSize = 0;
21  fs_status = FileSystem::getFileSize(fileName, fileSize);
22  if (FileSystem::OP_OK != fs_status) {
23  return File::BAD_SIZE;
24  }
25  const FwSizeType max_itr = (fileSize / VFILE_HASH_CHUNK_SIZE + 1);
26 
27  // Read all data from file and update hash:
28  Utils::Hash hash;
29  hash.init();
30  U8 buffer[VFILE_HASH_CHUNK_SIZE];
31  FwSizeType size = 0;
32  FwSizeType cnt = 0;
33  while (cnt <= max_itr) {
34  // Read out chunk from file:
35  size = sizeof(buffer);
36  status = file.read(buffer, size, Os::File::WaitType::NO_WAIT);
37  if (File::OP_OK != status) {
38  return status;
39  }
40  // If end of file, break:
41  if (size == 0) {
42  break;
43  }
44  // Add chunk to hash calculation:
45  hash.update(&buffer, static_cast<FwSizeType>(size));
46  cnt++;
47  }
48  file.close();
49 
50  // The iteration bound is computed from the size at open; a file that grows while
51  // being hashed exhausts it with data still unread, which is an error, not a bug
52  if (size != 0) {
53  return File::BAD_SIZE;
54  }
55 
56  // Calculate hash:
57  Utils::HashBuffer computedHashBuffer;
58  hash.finalize(computedHashBuffer);
59  hashBuffer = computedHashBuffer;
60 
61  return status;
62 }
63 
64 File::Status readHash(const char* hashFileName, Utils::HashBuffer& hashBuffer) {
65  File::Status status;
66 
67  // Open hash file:
68  File hashFile;
69  status = hashFile.open(hashFileName, File::OPEN_READ);
70  if (File::OP_OK != status) {
71  return status;
72  }
73 
74  // Read hash from checksum file:
75  U8 savedHash[HASH_DIGEST_LENGTH];
76  FwSizeType size = static_cast<FwSizeType>(hashBuffer.getCapacity());
77  status = hashFile.read(savedHash, size);
78  if (File::OP_OK != status) {
79  return status;
80  }
81  if (static_cast<FwSizeType>(size) != hashBuffer.getCapacity()) {
82  return File::BAD_SIZE;
83  }
84  hashFile.close();
85 
86  // Return the hash buffer:
87  Utils::HashBuffer savedHashBuffer(savedHash, static_cast<FwSizeType>(size));
88  hashBuffer = savedHashBuffer;
89 
90  return status;
91 }
92 
93 File::Status writeHash(const char* hashFileName, Utils::HashBuffer hashBuffer) {
94  // Open hash file:
95  File hashFile;
96  File::Status status;
97  status = hashFile.open(hashFileName, File::OPEN_WRITE);
98  if (File::OP_OK != status) {
99  return status;
100  }
101 
102  // Write out the hash
103  FwSizeType size = static_cast<FwSizeType>(hashBuffer.getSize());
104  status = hashFile.write(hashBuffer.getBuffAddr(), size, Os::File::WaitType::NO_WAIT);
105  if (File::OP_OK != status) {
106  return status;
107  }
108  if (static_cast<FwSizeType>(size) != hashBuffer.getSize()) {
109  return File::BAD_SIZE;
110  }
111  hashFile.close();
112 
113  return status;
114 }
115 
116 // Enum and function for translating from a status to a validation status:
118 
120  switch (type) {
121  case FileType:
122  switch (status) {
123  case File::OP_OK:
125  case File::DOESNT_EXIST:
127  case File::NO_SPACE:
128  return ValidateFile::NO_SPACE;
129  case File::NO_PERMISSION:
131  case File::BAD_SIZE:
133  case File::NOT_OPENED:
135  case File::OTHER_ERROR:
137  default:
138  // Unlisted statuses (e.g. NOT_SUPPORTED, INVALID_ARGUMENT) can
139  // legitimately come from the OS layer; report rather than assert
141  }
142  break;
143  case HashFileType:
144  switch (status) {
145  case File::OP_OK:
147  case File::DOESNT_EXIST:
149  case File::NO_SPACE:
150  return ValidateFile::NO_SPACE;
151  case File::NO_PERMISSION:
153  case File::BAD_SIZE:
155  case File::NOT_OPENED:
157  case File::OTHER_ERROR:
159  default:
160  // Unlisted statuses (e.g. NOT_SUPPORTED, INVALID_ARGUMENT) can
161  // legitimately come from the OS layer; report rather than assert
163  }
164  break;
165  default:
166  FW_ASSERT(false, type);
167  }
168 
170 }
171 
172 ValidateFile::Status ValidateFile::validate(const char* fileName, const char* hashFileName) {
173  Utils::HashBuffer hashBuffer; // pass by reference - final value is unused
174  return validate(fileName, hashFileName, hashBuffer);
175 }
176 
178  const char* hashFileName,
179  Utils::HashBuffer& hashBuffer) {
180  File::Status status;
181 
182  // Read the hash file:
183  Utils::HashBuffer savedHash;
184  status = readHash(hashFileName, savedHash);
185  if (File::OP_OK != status) {
186  return translateStatus(status, HashFileType);
187  }
188 
189  // Compute the file's hash:
190  Utils::HashBuffer computedHash;
191  status = computeHash(fileName, computedHash);
192  if (File::OP_OK != status) {
193  return translateStatus(status, FileType);
194  }
195 
196  // Compare hashes and return:
197  if (savedHash != computedHash) {
199  }
200 
201  hashBuffer = savedHash;
202 
204 }
205 
207  const char* hashFileName,
208  Utils::HashBuffer& hashBuffer) {
209  File::Status status;
210 
211  // Compute the file's hash:
212  status = computeHash(fileName, hashBuffer);
213  if (File::OP_OK != status) {
214  return translateStatus(status, FileType);
215  }
216 
217  status = writeHash(hashFileName, hashBuffer);
218  if (File::OP_OK != status) {
219  return translateStatus(status, HashFileType);
220  }
221 
223 }
224 
225 ValidateFile::Status ValidateFile::createValidation(const char* fileName, const char* hashFileName) {
226  Utils::HashBuffer hashBuffer; // pass by reference - final value is unused
227  return createValidation(fileName, hashFileName, hashBuffer);
228 }
229 
230 ValidateFile::Status ValidateFile::createValidation(const char* hashFileName, const Utils::HashBuffer& hashBuffer) {
231  File::Status status;
232 
233  status = writeHash(hashFileName, hashBuffer);
234  if (File::OP_OK != status) {
235  return translateStatus(status, HashFileType);
236  }
237 
239 }
240 
241 } // namespace Os
void update(const void *const data, const FwSizeType len)
Definition: HashImpl.cpp:34
File doesn&#39;t exist (for read)
No permission to read/write file.
A catch-all for other errors. Have to look in implementation-specific code.
PlatformSizeType FwSizeType
Invalid size parameter.
Serializable::SizeType getSize() const override
Get current buffer size.
No permission to read/write file.
Definition: File.hpp:45
Open file for writing.
Definition: File.hpp:35
Validation file doesn&#39;t exist (for read)
Serializable::SizeType getCapacity() const override
Get buffer capacity.
void init()
Definition: HashImpl.cpp:30
The validation of the file passed.
Os::FileInterface::Status open(const char *path, Mode mode)
open file with supplied path and mode
Definition: File.cpp:50
U8 * getBuffAddr()
Get buffer address for data filling (non-const version)
No space left.
Definition: File.hpp:44
File doesn&#39;t exist (for read)
Definition: File.hpp:43
Status validate(const char *fileName, const char *hashFileName, Utils::HashBuffer &hashBuffer)
Validate the contents of a file &#39;fileName&#39; against its hash.
File::Status computeHash(const char *fileName, Utils::HashBuffer &hashBuffer)
#define HASH_DIGEST_LENGTH
Definition: Crc32.hpp:26
void close() override
close the file, if not opened then do nothing
Definition: File.cpp:97
Status write(const U8 *buffer, FwSizeType &size)
write data to this file from the supplied buffer bounded by size
Definition: File.cpp:213
A generic interface for creating and comparing hash values.
Definition: Hash.hpp:24
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:54
Status createValidation(const char *fileName, const char *hash, Utils::HashBuffer &hashBuffer)
static Status getFileSize(const char *path, FwSizeType &size)
Get the size of the file (in bytes) at the specified path.
Definition: FileSystem.cpp:227
Status read(U8 *buffer, FwSizeType &size)
read data from this file into supplied buffer bounded by size
Definition: File.cpp:194
No space left on the device for writing.
No permission to read/write file.
file hasn&#39;t been opened yet
Definition: File.hpp:47
Operation was successful.
Definition: File.hpp:42
A catch-all for other errors. Have to look in implementation-specific code.
Definition: File.hpp:53
Defines a file class to validate files or generate a file validator file.
Open file for reading.
Definition: File.hpp:33
A container class for holding a hash buffer.
Definition: HashBuffer.hpp:26
Operation was successful.
Definition: FileSystem.hpp:24
File::Status writeHash(const char *hashFileName, Utils::HashBuffer hashBuffer)
Invalid size parameter.
Definition: File.hpp:46
#define VFILE_HASH_CHUNK_SIZE
ValidateFile::Status translateStatus(File::Status status, StatusFileType type)
File::Status readHash(const char *hashFileName, Utils::HashBuffer &hashBuffer)
void finalize(HashBuffer &buffer) const
Definition: HashImpl.cpp:40
#define FW_ASSERT(...)
Definition: Assert.hpp:14
The validation of the file did not pass.