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