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 <Fw/FPrimeBasicTypes.hpp>
13 #include <Fw/Types/Assert.hpp>
15 #include <Os/File.hpp>
16 #include <Os/FileSystem.hpp>
17 #include <Utils/CRCChecker.hpp>
18 #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  FW_ASSERT(fname != nullptr);
26 
27  FwSizeType i;
28  FwSizeType blocks;
29  FwSizeType remaining_bytes;
30  FwSizeType filesize;
31  Os::File f;
32  Os::FileSystem::Status fs_stat;
33  Os::File::Status stat;
34  Utils::Hash hash;
35  U32 checksum;
36  FwSizeType bytes_to_read;
37  FwSizeType bytes_to_write;
38  Fw::FileNameString hashFilename;
39  U8 block_data[CRC_FILE_READ_BLOCK];
40 
41  fs_stat = Os::FileSystem::getFileSize(fname, filesize);
42  if (fs_stat != Os::FileSystem::OP_OK) {
43  return FAILED_FILE_SIZE;
44  }
45 
46  // Open file
47  stat = f.open(fname, Os::File::OPEN_READ);
48  if (stat != Os::File::OP_OK) {
49  return FAILED_FILE_OPEN;
50  }
51 
52  // Read file
53  bytes_to_read = CRC_FILE_READ_BLOCK;
54  blocks = filesize / CRC_FILE_READ_BLOCK;
55  for (i = 0; i < blocks; i++) {
56  stat = f.read(block_data, bytes_to_read);
57  if (stat != Os::File::OP_OK || bytes_to_read != CRC_FILE_READ_BLOCK) {
58  f.close();
59  return FAILED_FILE_READ;
60  }
61 
62  hash.update(block_data, bytes_to_read);
63  }
64 
65  remaining_bytes = filesize % CRC_FILE_READ_BLOCK;
66  bytes_to_read = remaining_bytes;
67  if (remaining_bytes > 0) {
68  stat = f.read(block_data, bytes_to_read);
69  if (stat != Os::File::OP_OK || bytes_to_read != remaining_bytes) {
70  f.close();
71  return FAILED_FILE_READ;
72  }
73 
74  hash.update(block_data, remaining_bytes);
75  }
76 
77  // close file
78  f.close();
79 
80  // generate checksum
81  hash.final(checksum);
82 
83  // open checksum file
84  Fw::FormatStatus formatStatus = hashFilename.format("%s%s", fname, HASH_EXTENSION_STRING);
85  FW_ASSERT(formatStatus == Fw::FormatStatus::SUCCESS);
86 
87  stat = f.open(hashFilename.toChar(), Os::File::OPEN_WRITE);
88  if (stat != Os::File::OP_OK) {
89  return FAILED_FILE_CRC_OPEN;
90  }
91 
92  // Write checksum file
93  bytes_to_write = sizeof(checksum);
94  stat = f.write(reinterpret_cast<U8*>(&checksum), bytes_to_write);
95  if (stat != Os::File::OP_OK || sizeof(checksum) != bytes_to_write) {
96  f.close();
97  return FAILED_FILE_CRC_WRITE;
98  }
99 
100  // close checksum file
101  f.close();
102 
103  return PASSED_FILE_CRC_WRITE;
104 }
105 
106 crc_stat_t read_crc32_from_file(const char* const fname, U32& checksum_from_file) {
107  Os::File f;
108  Os::File::Status stat;
109  Fw::FileNameString hashFilename;
110  FW_ASSERT(fname != nullptr);
111  // open checksum file
112  Fw::FormatStatus formatStatus = hashFilename.format("%s%s", fname, HASH_EXTENSION_STRING);
113  FW_ASSERT(formatStatus == Fw::FormatStatus::SUCCESS);
114 
115  stat = f.open(hashFilename.toChar(), Os::File::OPEN_READ);
116  if (stat != Os::File::OP_OK) {
117  return FAILED_FILE_CRC_OPEN;
118  }
119 
120  // Read checksum file
121  FwSizeType checksum_from_file_size = static_cast<FwSizeType>(sizeof(checksum_from_file));
122  stat = f.read(reinterpret_cast<U8*>(&checksum_from_file), checksum_from_file_size);
123  if (stat != Os::File::OP_OK || checksum_from_file_size != sizeof(checksum_from_file)) {
124  f.close();
125  return FAILED_FILE_CRC_READ;
126  }
127 
128  // close checksum file
129  f.close();
130  return PASSED_FILE_CRC_CHECK;
131 }
132 
133 crc_stat_t verify_checksum(const char* const fname, U32& expected, U32& actual) {
134  FW_ASSERT(fname != nullptr);
135 
136  FwSizeType i;
137  FwSizeType blocks;
138  FwSizeType remaining_bytes;
139  FwSizeType filesize;
140  Os::File f;
141  Os::FileSystem::Status fs_stat;
142  Os::File::Status stat;
143  Utils::Hash hash;
144  U32 checksum;
145  U32 checksum_from_file;
146  FwSizeType bytes_to_read;
147  U8 block_data[CRC_FILE_READ_BLOCK];
148 
149  fs_stat = Os::FileSystem::getFileSize(fname, filesize);
150  if (fs_stat != Os::FileSystem::OP_OK) {
151  return FAILED_FILE_SIZE;
152  }
153 
154  // Open file
155  stat = f.open(fname, Os::File::OPEN_READ);
156  if (stat != Os::File::OP_OK) {
157  return FAILED_FILE_OPEN;
158  }
159 
160  // Read file
161  bytes_to_read = CRC_FILE_READ_BLOCK;
162  blocks = filesize / CRC_FILE_READ_BLOCK;
163  for (i = 0; i < blocks; i++) {
164  stat = f.read(block_data, bytes_to_read);
165  if (stat != Os::File::OP_OK || bytes_to_read != CRC_FILE_READ_BLOCK) {
166  f.close();
167  return FAILED_FILE_READ;
168  }
169 
170  hash.update(block_data, static_cast<FwSizeType>(bytes_to_read));
171  }
172 
173  remaining_bytes = filesize % CRC_FILE_READ_BLOCK;
174  bytes_to_read = remaining_bytes;
175  if (remaining_bytes > 0) {
176  stat = f.read(block_data, bytes_to_read);
177  if (stat != Os::File::OP_OK || bytes_to_read != remaining_bytes) {
178  f.close();
179  return FAILED_FILE_READ;
180  }
181 
182  hash.update(block_data, remaining_bytes);
183  }
184 
185  // close file
186  f.close();
187  // generate checksum
188  hash.final(checksum);
189 
190  crc_stat_t crcstat = read_crc32_from_file(fname, checksum_from_file);
191  if (crcstat != PASSED_FILE_CRC_CHECK) {
192  return crcstat;
193  }
194 
195  // compare checksums
196  if (checksum != checksum_from_file) {
197  expected = checksum_from_file;
198  actual = checksum;
199  return FAILED_FILE_CRC_CHECK;
200  }
201 
202  expected = checksum_from_file;
203  actual = checksum;
204  return PASSED_FILE_CRC_CHECK;
205 }
206 
207 } // namespace Utils
void update(const void *const data, const FwSizeType len)
Definition: CRC32.cpp:45
PlatformSizeType FwSizeType
static const FwSignedSizeType CRC_FILE_READ_BLOCK
Definition: CRCChecker.hpp:20
Open file for writing.
Definition: File.hpp:33
Os::FileInterface::Status open(const char *path, Mode mode)
open file with supplied path and mode
#define FW_USE_PRINTF_FAMILY_FUNCTIONS_IN_STRING_FORMATTING
Definition: FpConfig.h:65
void final(HashBuffer &buffer)
Definition: CRC32.cpp:54
crc_stat_t create_checksum_file(const char *const fname)
Definition: CRCChecker.cpp:24
crc_stat_t read_crc32_from_file(const char *const fname, U32 &checksum_from_file)
Definition: CRCChecker.cpp:106
const char * toChar() const
Convert to a C-style char*.
void close() override
close the file, if not opened then do nothing
Definition: File.cpp:70
Status write(const U8 *buffer, FwSizeType &size)
write data to this file from the supplied buffer bounded by size
Definition: File.cpp:187
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:133
FormatStatus format(const CHAR *formatString,...)
write formatted string to buffer
Definition: StringBase.cpp:39
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:53
static Status getFileSize(const char *path, FwSizeType &size)
Get the size of the file (in bytes) at the specified path.
Definition: FileSystem.cpp:225
Status read(U8 *buffer, FwSizeType &size)
read data from this file into supplied buffer bounded by size
Definition: File.cpp:168
Operation was successful.
Definition: File.hpp:40
Open file for reading.
Definition: File.hpp:31
#define HASH_EXTENSION_STRING
Definition: CRC32.hpp:25
Operation was successful.
Definition: FileSystem.hpp:24
#define FW_ASSERT(...)
Definition: Assert.hpp:14
FormatStatus
status of string format calls
Definition: format.hpp:18