F´ Flight Software - C/C++ Documentation  devel
A framework for building embedded system applications to NASA flight quality standards.
ValidateFileCommon.cpp
Go to the documentation of this file.
1 #include <Os/ValidateFile.hpp>
2 #include <Os/File.hpp>
3 #include <Utils/Hash/Hash.hpp>
4 #include <Os/FileSystem.hpp>
5 
6 namespace Os {
7 
8  File::Status computeHash(const char* fileName, Utils::HashBuffer &hashBuffer) {
9 
10  File::Status status;
11 
12  // Open file:
13  File file;
14  status = file.open(fileName, File::OPEN_READ);
15  if( File::OP_OK != status ) {
16  return status;
17  }
18 
19  // Get the file size:
20  FileSystem::Status fs_status;
21  FwSignedSizeType fileSize = 0;
22  fs_status = FileSystem::getFileSize(fileName, fileSize);
23  // fileSize will be used as a NATIVE_INT_TYPE below and thus must cast cleanly to that type
24  if( FileSystem::OP_OK != fs_status) {
25  return File::BAD_SIZE;
26  }
27  const NATIVE_INT_TYPE max_itr = static_cast<NATIVE_INT_TYPE>(fileSize/VFILE_HASH_CHUNK_SIZE + 1);
28 
29  // Read all data from file and update hash:
30  Utils::Hash hash;
31  hash.init();
32  U8 buffer[VFILE_HASH_CHUNK_SIZE];
33  FwSignedSizeType size = 0;
34  FwSignedSizeType cnt = 0;
35  while( cnt <= max_itr ) {
36  // Read out chunk from file:
37  size = sizeof(buffer);
38  status = file.read(buffer, size, Os::File::WaitType::NO_WAIT);
39  if( File::OP_OK != status ) {
40  return status;
41  }
42  // If end of file, break:
43  if( size == 0 ) {
44  break;
45  }
46  // Add chunk to hash calculation:
47  hash.update(&buffer, static_cast<NATIVE_INT_TYPE>(size));
48  cnt++;
49  }
50  file.close();
51 
52  // We should not have left the loop because of cnt > max_itr:
53  FW_ASSERT(size == 0);
54  FW_ASSERT(cnt <= max_itr);
55 
56  // Calculate hash:
57  Utils::HashBuffer computedHashBuffer;
58  hash.final(computedHashBuffer);
59  hashBuffer = computedHashBuffer;
60 
61  return status;
62  }
63 
64  File::Status readHash(const char* hashFileName, Utils::HashBuffer &hashBuffer) {
65 
66  File::Status status;
67 
68  // Open hash file:
69  File hashFile;
70  status = hashFile.open(hashFileName, File::OPEN_READ);
71  if( File::OP_OK != status ) {
72  return status;
73  }
74 
75  // Read hash from checksum file:
76  unsigned char savedHash[HASH_DIGEST_LENGTH];
77  FwSignedSizeType size = hashBuffer.getBuffCapacity();
78  status = hashFile.read(savedHash, size);
79  if( File::OP_OK != status ) {
80  return status;
81  }
82  if( size != static_cast<NATIVE_INT_TYPE>(hashBuffer.getBuffCapacity()) ) {
83  return File::BAD_SIZE;
84  }
85  hashFile.close();
86 
87  // Return the hash buffer:
88  Utils::HashBuffer savedHashBuffer(savedHash, static_cast<NATIVE_UINT_TYPE>(size));
89  hashBuffer = savedHashBuffer;
90 
91  return status;
92  }
93 
94  File::Status writeHash(const char* hashFileName, Utils::HashBuffer hashBuffer) {
95  // Open hash file:
96  File hashFile;
97  File::Status status;
98  status = hashFile.open(hashFileName, File::OPEN_WRITE);
99  if( File::OP_OK != status ) {
100  return status;
101  }
102 
103  // Write out the hash
104  FwSignedSizeType size = hashBuffer.getBuffLength();
105  status = hashFile.write(hashBuffer.getBuffAddr(), size, Os::File::WaitType::NO_WAIT);
106  if( File::OP_OK != status ) {
107  return status;
108  }
109  if( size != static_cast<NATIVE_INT_TYPE>(hashBuffer.getBuffLength()) ) {
110  return File::BAD_SIZE;
111  }
112  hashFile.close();
113 
114  return status;
115  }
116 
117  // Enum and function for translating from a status to a validation status:
118  typedef enum {
122 
124 
125  switch (type) {
126  case FileType:
127  switch (status) {
128  case File::OP_OK:
130  case File::DOESNT_EXIST:
132  case File::NO_SPACE:
133  return ValidateFile::NO_SPACE;
134  case File::NO_PERMISSION:
136  case File::BAD_SIZE:
138  case File::NOT_OPENED:
140  case File::OTHER_ERROR:
142  default:
143  FW_ASSERT(0, status);
144  }
145  break;
146  case HashFileType:
147  switch (status) {
148  case File::OP_OK:
150  case File::DOESNT_EXIST:
152  case File::NO_SPACE:
153  return ValidateFile::NO_SPACE;
154  case File::NO_PERMISSION:
156  case File::BAD_SIZE:
158  case File::NOT_OPENED:
160  case File::OTHER_ERROR:
162  default:
163  FW_ASSERT(0, status);
164  }
165  break;
166  default:
167  FW_ASSERT(0, type);
168  }
169 
171  }
172 
173  ValidateFile::Status ValidateFile::validate(const char* fileName, const char* hashFileName) {
174  Utils::HashBuffer hashBuffer; // pass by reference - final value is unused
175  return validate(fileName, hashFileName, hashBuffer);
176  }
177 
178  ValidateFile::Status ValidateFile::validate(const char* fileName, const char* hashFileName, Utils::HashBuffer &hashBuffer) {
179 
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 
206  ValidateFile::Status ValidateFile::createValidation(const char* fileName, const char* hashFileName, Utils::HashBuffer &hashBuffer) {
207 
208  File::Status status;
209 
210  // Compute the file's hash:
211  status = computeHash(fileName, hashBuffer);
212  if( File::OP_OK != status ) {
213  return translateStatus(status, FileType);
214  }
215 
216  status = writeHash(hashFileName, hashBuffer);
217  if( File::OP_OK != status ) {
218  return translateStatus(status, HashFileType);
219  }
220 
222  }
223 
224  ValidateFile::Status ValidateFile::createValidation(const char* fileName, const char* hashFileName) {
225  Utils::HashBuffer hashBuffer; // pass by reference - final value is unused
226  return createValidation(fileName, hashFileName, hashBuffer);
227  }
228 
229 }
#define FW_ASSERT(...)
Definition: Assert.hpp:14
PlatformIntType NATIVE_INT_TYPE
Definition: BasicTypes.h:51
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:26
PlatformUIntType NATIVE_UINT_TYPE
Definition: BasicTypes.h:52
#define HASH_DIGEST_LENGTH
Definition: CRC32.hpp:18
PlatformSignedSizeType FwSignedSizeType
Definition: FpConfig.h:25
Defines a file class to validate files or generate a file validator file.
#define VFILE_HASH_CHUNK_SIZE
Serializable::SizeType getBuffLength() const
returns current buffer size
Status read(U8 *buffer, FwSignedSizeType &size)
read data from this file into supplied buffer bounded by size
Definition: File.cpp:142
void close() override
close the file, if not opened then do nothing
Definition: File.cpp:69
Os::FileInterface::Status open(const char *path, Mode mode)
open file with supplied path and mode
Definition: File.cpp:45
Status write(const U8 *buffer, FwSignedSizeType &size)
write data to this file from the supplied buffer bounded by size
Definition: File.cpp:162
@ NO_SPACE
No space left.
Definition: File.hpp:32
@ NO_PERMISSION
No permission to read/write file.
Definition: File.hpp:33
@ NOT_OPENED
file hasn't been opened yet
Definition: File.hpp:35
@ OTHER_ERROR
A catch-all for other errors. Have to look in implementation-specific code.
Definition: File.hpp:40
@ BAD_SIZE
Invalid size parameter.
Definition: File.hpp:34
@ OP_OK
Operation was successful.
Definition: File.hpp:30
@ DOESNT_EXIST
File doesn't exist (for read)
Definition: File.hpp:31
@ OPEN_WRITE
Open file for writing.
Definition: File.hpp:23
@ OPEN_READ
Open file for reading.
Definition: File.hpp:21
A container class for holding a hash buffer.
Definition: HashBuffer.hpp:26
NATIVE_UINT_TYPE getBuffCapacity() const
A generic interface for creating and comparing hash values.
Definition: Hash.hpp:24
void init()
Definition: CRC32.cpp:47
void update(const void *const data, const NATIVE_INT_TYPE len)
Definition: CRC32.cpp:53
void final(HashBuffer &buffer)
Definition: CRC32.cpp:64
Status getFileSize(const char *path, FwSizeType &size)
Definition: FileSystem.cpp:38
@ OP_OK
Operation was successful.
Definition: FileSystem.hpp:15
@ FILE_NO_PERMISSION
No permission to read/write file.
@ VALIDATION_OK
The validation of the file passed.
@ VALIDATION_FILE_DOESNT_EXIST
Validation file doesn't exist (for read)
@ FILE_DOESNT_EXIST
File doesn't exist (for read)
@ VALIDATION_FAIL
The validation of the file did not pass.
@ OTHER_ERROR
A catch-all for other errors. Have to look in implementation-specific code.
@ FILE_BAD_SIZE
Invalid size parameter.
@ NO_SPACE
No space left on the device for writing.
@ VALIDATION_FILE_BAD_SIZE
Invalid size parameter.
@ VALIDATION_FILE_NO_PERMISSION
No permission to read/write file.
Status createValidation(const char *fileName, const char *hash, Utils::HashBuffer &hashBuffer)
Status validate(const char *fileName, const char *hashFileName, Utils::HashBuffer &hashBuffer)
Validate the contents of a file 'fileName' against its hash.
File::Status computeHash(const char *fileName, Utils::HashBuffer &hashBuffer)
File::Status readHash(const char *hashFileName, Utils::HashBuffer &hashBuffer)
File::Status writeHash(const char *hashFileName, Utils::HashBuffer hashBuffer)
ValidateFile::Status translateStatus(File::Status status, StatusFileType type)