F´ Flight Software - C/C++ Documentation
A framework for building embedded system applications to NASA flight quality standards.
CRCChecker.cpp
Go to the documentation of this file.
1 // ======================================================================
2 // \title CRCChecker.cpp
3 // \author ortega
4 // \brief cpp file for a crc32 checker
5 //
6 // \copyright
7 // Copyright 2009-2020, by the California Institute of Technology.
8 // ALL RIGHTS RESERVED. United States Government Sponsorship
9 // acknowledged.
10 // ======================================================================
11 
12 #include <FpConfig.hpp>
13 #include <Utils/CRCChecker.hpp>
14 #include <Fw/Types/Assert.hpp>
15 #include <Os/File.hpp>
16 #include <Os/FileSystem.hpp>
17 #include <Utils/Hash/Hash.hpp>
19 
20 namespace Utils {
22  "Cannot use CRC checker without full string formatting");
23 
24  crc_stat_t create_checksum_file(const char* const fname)
25  {
26  FW_ASSERT(fname != nullptr);
27 
29  FwSignedSizeType blocks;
30  FwSignedSizeType remaining_bytes;
31  FwSignedSizeType filesize;
32  Os::File f;
33  Os::FileSystem::Status fs_stat;
34  Os::File::Status stat;
35  Utils::Hash hash;
36  U32 checksum;
37  FwSignedSizeType int_file_size;
38  FwSignedSizeType bytes_to_read;
39  FwSignedSizeType bytes_to_write;
40  Fw::FileNameString hashFilename;
41  U8 block_data[CRC_FILE_READ_BLOCK];
42 
43  fs_stat = Os::FileSystem::getFileSize(fname, filesize);
44  if(fs_stat != Os::FileSystem::OP_OK)
45  {
46  return FAILED_FILE_SIZE;
47  }
48 
49  int_file_size = filesize;
50 
51  // Open file
52  stat = f.open(fname, Os::File::OPEN_READ);
53  if(stat != Os::File::OP_OK)
54  {
55  return FAILED_FILE_OPEN;
56  }
57 
58  // Read file
59  bytes_to_read = CRC_FILE_READ_BLOCK;
60  blocks = int_file_size / CRC_FILE_READ_BLOCK;
61  for(i = 0; i < blocks; i++)
62  {
63  stat = f.read(block_data, bytes_to_read);
64  if(stat != Os::File::OP_OK || bytes_to_read != CRC_FILE_READ_BLOCK)
65  {
66  f.close();
67  return FAILED_FILE_READ;
68  }
69 
70  hash.update(block_data, static_cast<NATIVE_INT_TYPE>(bytes_to_read));
71  }
72 
73  remaining_bytes = int_file_size % CRC_FILE_READ_BLOCK;
74  bytes_to_read = remaining_bytes;
75  if(remaining_bytes > 0)
76  {
77  stat = f.read(block_data, bytes_to_read);
78  if(stat != Os::File::OP_OK || bytes_to_read != remaining_bytes)
79  {
80  f.close();
81  return FAILED_FILE_READ;
82  }
83 
84  hash.update(block_data, static_cast<NATIVE_INT_TYPE>(remaining_bytes));
85  }
86 
87  // close file
88  f.close();
89 
90  // generate checksum
91  hash.final(checksum);
92 
93  // open checksum file
94  Fw::FormatStatus formatStatus = hashFilename.format("%s%s", fname, HASH_EXTENSION_STRING);
95  FW_ASSERT(formatStatus == Fw::FormatStatus::SUCCESS);
96 
97  stat = f.open(hashFilename.toChar(), Os::File::OPEN_WRITE);
98  if(stat != Os::File::OP_OK)
99  {
100  return FAILED_FILE_CRC_OPEN;
101  }
102 
103  // Write checksum file
104  bytes_to_write = sizeof(checksum);
105  stat = f.write(reinterpret_cast<U8*>(&checksum), bytes_to_write);
106  if(stat != Os::File::OP_OK || sizeof(checksum) != bytes_to_write)
107  {
108  f.close();
109  return FAILED_FILE_CRC_WRITE;
110  }
111 
112  // close checksum file
113  f.close();
114 
115  return PASSED_FILE_CRC_WRITE;
116  }
117 
118  crc_stat_t read_crc32_from_file(const char* const fname, U32 &checksum_from_file) {
119  Os::File f;
120  Os::File::Status stat;
121  Fw::FileNameString hashFilename;
122  FW_ASSERT(fname != nullptr);
123  // open checksum file
124  Fw::FormatStatus formatStatus = hashFilename.format("%s%s", fname, HASH_EXTENSION_STRING);
125  FW_ASSERT(formatStatus == Fw::FormatStatus::SUCCESS);
126 
127  stat = f.open(hashFilename.toChar(), Os::File::OPEN_READ);
128  if(stat != Os::File::OP_OK)
129  {
130  return FAILED_FILE_CRC_OPEN;
131  }
132 
133  // Read checksum file
134  FwSignedSizeType checksum_from_file_size = static_cast<FwSignedSizeType>(sizeof(checksum_from_file));
135  stat = f.read(reinterpret_cast<U8*>(&checksum_from_file), checksum_from_file_size);
136  if(stat != Os::File::OP_OK || checksum_from_file_size != sizeof(checksum_from_file))
137  {
138  f.close();
139  return FAILED_FILE_CRC_READ;
140  }
141 
142  // close checksum file
143  f.close();
144  return PASSED_FILE_CRC_CHECK;
145  }
146 
147  crc_stat_t verify_checksum(const char* const fname, U32 &expected, U32 &actual)
148  {
149  FW_ASSERT(fname != nullptr);
150 
152  FwSignedSizeType blocks;
153  PlatformIntType remaining_bytes;
154  FwSignedSizeType filesize;
155  Os::File f;
156  Os::FileSystem::Status fs_stat;
157  Os::File::Status stat;
158  Utils::Hash hash;
159  U32 checksum;
160  U32 checksum_from_file;
161  FwSignedSizeType int_file_size;
162  FwSignedSizeType bytes_to_read;
163  U8 block_data[CRC_FILE_READ_BLOCK];
164 
165  fs_stat = Os::FileSystem::getFileSize(fname, filesize);
166  if(fs_stat != Os::FileSystem::OP_OK)
167  {
168  return FAILED_FILE_SIZE;
169  }
170 
171  int_file_size = static_cast<NATIVE_INT_TYPE>(filesize);
172  if(static_cast<FwSignedSizeType>(int_file_size) != filesize)
173  {
174  return FAILED_FILE_SIZE_CAST;
175  }
176 
177  // Open file
178  stat = f.open(fname, Os::File::OPEN_READ);
179  if(stat != Os::File::OP_OK)
180  {
181  return FAILED_FILE_OPEN;
182  }
183 
184  // Read file
185  bytes_to_read = CRC_FILE_READ_BLOCK;
186  blocks = filesize / CRC_FILE_READ_BLOCK;
187  for(i = 0; i < blocks; i++)
188  {
189  stat = f.read(block_data, bytes_to_read);
190  if(stat != Os::File::OP_OK || bytes_to_read != CRC_FILE_READ_BLOCK)
191  {
192  f.close();
193  return FAILED_FILE_READ;
194  }
195 
196  hash.update(block_data, static_cast<NATIVE_INT_TYPE>(bytes_to_read));
197  }
198 
199  remaining_bytes = static_cast<PlatformIntType>(int_file_size % CRC_FILE_READ_BLOCK);
200  bytes_to_read = remaining_bytes;
201  if(remaining_bytes > 0)
202  {
203  stat = f.read(block_data, bytes_to_read);
204  if(stat != Os::File::OP_OK || bytes_to_read != remaining_bytes)
205  {
206  f.close();
207  return FAILED_FILE_READ;
208  }
209 
210  hash.update(block_data, remaining_bytes);
211  }
212 
213  // close file
214  f.close();
215  // generate checksum
216  hash.final(checksum);
217 
218  crc_stat_t crcstat = read_crc32_from_file(fname, checksum_from_file);
219  if (crcstat != PASSED_FILE_CRC_CHECK) {
220  return crcstat;
221  }
222 
223  // compare checksums
224  if(checksum != checksum_from_file)
225  {
226  expected = checksum_from_file;
227  actual = checksum;
228  return FAILED_FILE_CRC_CHECK;
229  }
230 
231  expected = checksum_from_file;
232  actual = checksum;
233  return PASSED_FILE_CRC_CHECK;
234  }
235 
236 }
Status read(U8 *buffer, FwSignedSizeType &size)
read data from this file into supplied buffer bounded by size
Definition: File.cpp:143
PlatformIntType NATIVE_INT_TYPE
Definition: BasicTypes.h:55
Open file for writing.
Definition: File.hpp:23
Os::FileInterface::Status open(const char *path, Mode mode)
open file with supplied path and mode
void final(HashBuffer &buffer)
Definition: CRC32.cpp:64
crc_stat_t create_checksum_file(const char *const fname)
Definition: CRCChecker.cpp:24
int PlatformIntType
DefaultTypes.hpp provides fallback defaults for the platform types.
crc_stat_t read_crc32_from_file(const char *const fname, U32 &checksum_from_file)
Definition: CRCChecker.cpp:118
const char * toChar() const
#define FW_USE_PRINTF_FAMILY_FUNCTIONS_IN_STRING_FORMATTING
Definition: FpConfig.h:192
void close() override
close the file, if not opened then do nothing
Definition: File.cpp:70
A generic interface for creating and comparing hash values.
Definition: Hash.hpp:24
crc_stat_t verify_checksum(const char *const fname, U32 &expected, U32 &actual)
Definition: CRCChecker.cpp:147
FormatStatus format(const CHAR *formatString,...)
write formatted string to buffer
Definition: StringBase.cpp:55
C++-compatible configuration header for fprime configuration.
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:30
Operation was successful.
Definition: File.hpp:30
void update(const void *const data, const NATIVE_INT_TYPE len)
Definition: CRC32.cpp:53
Open file for reading.
Definition: File.hpp:21
PlatformSignedSizeType FwSignedSizeType
Definition: FpConfig.h:30
#define HASH_EXTENSION_STRING
Definition: CRC32.hpp:25
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
static const NATIVE_INT_TYPE CRC_FILE_READ_BLOCK
Definition: CRCChecker.hpp:19
Status write(const U8 *buffer, FwSignedSizeType &size)
write data to this file from the supplied buffer bounded by size
Definition: File.cpp:163
#define FW_ASSERT(...)
Definition: Assert.hpp:14
FormatStatus
status of string format calls
Definition: format.hpp:18