GCC Code Coverage Report


Directory: ./
File: Utils/CRCChecker.cpp
Date: 2026-09-23 22:11:34
Exec Total Coverage
Lines: 0 109 0.0%
Functions: 0 3 0.0%
Branches: 0 96 0.0%

Line Branch Exec Source
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>
14 #include <Fw/Types/FileNameString.hpp>
15 #include <Fw/Types/SerialBuffer.hpp>
16 #include <Os/File.hpp>
17 #include <Os/FileSystem.hpp>
18 #include <Utils/CRCChecker.hpp>
19 #include <Utils/Hash/Hash.hpp>
20
21 namespace Utils {
22 ✗ crc_stat_t create_checksum_file(const char* const fname) {
23 ✗ FW_ASSERT(fname != nullptr);
24
25 FwSizeType i;
26 FwSizeType blocks;
27 FwSizeType remaining_bytes;
28 FwSizeType filesize;
29 ✗ Os::File f;
30 Os::FileSystem::Status fs_stat;
31 Os::File::Status stat;
32 ✗ Utils::Hash hash;
33 U32 checksum;
34 FwSizeType bytes_to_read;
35 FwSizeType bytes_to_write;
36 ✗ Fw::FileNameString hashFilename;
37 U8 block_data[CRC_FILE_READ_BLOCK];
38
39 ✗ fs_stat = Os::FileSystem::getFileSize(fname, filesize);
40 ✗ if (fs_stat != Os::FileSystem::OP_OK) {
41 ✗ return FAILED_FILE_SIZE;
42 }
43
44 // Open file
45 ✗ stat = f.open(fname, Os::File::OPEN_READ);
46 ✗ if (stat != Os::File::OP_OK) {
47 ✗ return FAILED_FILE_OPEN;
48 }
49
50 // Read file
51 ✗ bytes_to_read = CRC_FILE_READ_BLOCK;
52 ✗ blocks = filesize / CRC_FILE_READ_BLOCK;
53 ✗ for (i = 0; i < blocks; i++) {
54 ✗ stat = f.read(block_data, bytes_to_read);
55 ✗ if (stat != Os::File::OP_OK || bytes_to_read != CRC_FILE_READ_BLOCK) {
56 ✗ f.close();
57 ✗ return FAILED_FILE_READ;
58 }
59
60 ✗ hash.update(block_data, bytes_to_read);
61 }
62
63 ✗ remaining_bytes = filesize % CRC_FILE_READ_BLOCK;
64 ✗ bytes_to_read = remaining_bytes;
65 ✗ if (remaining_bytes > 0) {
66 ✗ stat = f.read(block_data, bytes_to_read);
67 ✗ if (stat != Os::File::OP_OK || bytes_to_read != remaining_bytes) {
68 ✗ f.close();
69 ✗ return FAILED_FILE_READ;
70 }
71
72 ✗ hash.update(block_data, remaining_bytes);
73 }
74
75 // close file
76 ✗ f.close();
77
78 // generate checksum
79 ✗ hash.finalize(checksum);
80
81 // open checksum file. The filename is caller-supplied input: an overlong name is a reportable
82 // failure, not a coding error, so it must not assert.
83 ✗ Fw::FormatStatus formatStatus = hashFilename.format("%s%s", fname, HASH_EXTENSION_STRING);
84 ✗ if (formatStatus != Fw::FormatStatus::SUCCESS) {
85 ✗ return FAILED_FILE_NAME_TOO_LONG;
86 }
87
88 ✗ stat = f.open(hashFilename.toChar(), Os::File::OPEN_WRITE);
89 ✗ if (stat != Os::File::OP_OK) {
90 ✗ return FAILED_FILE_CRC_OPEN;
91 }
92
93 // Write checksum file. Serialize the value rather than writing the raw U32 bytes so that the
94 // file contents do not depend on the endianness of the processor.
95 ✗ U8 checksum_data[sizeof(checksum)] = {};
96 ✗ Fw::SerialBuffer checksum_buffer(checksum_data, sizeof(checksum_data));
97 ✗ Fw::SerializeStatus ser_stat = checksum_buffer.serializeFrom(checksum);
98 ✗ FW_ASSERT(Fw::FW_SERIALIZE_OK == ser_stat, static_cast<FwAssertArgType>(ser_stat));
99
100 ✗ bytes_to_write = checksum_buffer.getSize();
101 ✗ stat = f.write(checksum_buffer.getBuffAddr(), bytes_to_write);
102 ✗ if (stat != Os::File::OP_OK || sizeof(checksum) != bytes_to_write) {
103 ✗ f.close();
104 ✗ return FAILED_FILE_CRC_WRITE;
105 }
106
107 // close checksum file
108 ✗ f.close();
109
110 ✗ return PASSED_FILE_CRC_WRITE;
111 ✗ }
112
113 ✗ crc_stat_t read_crc32_from_file(const char* const fname, U32& checksum_from_file) {
114 ✗ Os::File f;
115 Os::File::Status stat;
116 ✗ Fw::FileNameString hashFilename;
117 ✗ FW_ASSERT(fname != nullptr);
118 // open checksum file. See create_checksum_file(): overlong names are reported, not asserted.
119 ✗ Fw::FormatStatus formatStatus = hashFilename.format("%s%s", fname, HASH_EXTENSION_STRING);
120 ✗ if (formatStatus != Fw::FormatStatus::SUCCESS) {
121 ✗ return FAILED_FILE_NAME_TOO_LONG;
122 }
123
124 ✗ stat = f.open(hashFilename.toChar(), Os::File::OPEN_READ);
125 ✗ if (stat != Os::File::OP_OK) {
126 ✗ return FAILED_FILE_CRC_OPEN;
127 }
128
129 // Read checksum file
130 ✗ U8 checksum_data[sizeof(checksum_from_file)] = {};
131 ✗ FwSizeType checksum_from_file_size = static_cast<FwSizeType>(sizeof(checksum_from_file));
132 ✗ stat = f.read(checksum_data, checksum_from_file_size);
133 ✗ if (stat != Os::File::OP_OK || checksum_from_file_size != sizeof(checksum_from_file)) {
134 ✗ f.close();
135 ✗ return FAILED_FILE_CRC_READ;
136 }
137
138 // Deserialize the value to match the serialized form written by create_checksum_file
139 ✗ Fw::SerialBuffer checksum_buffer(checksum_data, sizeof(checksum_data));
140 ✗ checksum_buffer.fill();
141 ✗ Fw::SerializeStatus ser_stat = checksum_buffer.deserializeTo(checksum_from_file);
142 ✗ FW_ASSERT(Fw::FW_SERIALIZE_OK == ser_stat, static_cast<FwAssertArgType>(ser_stat));
143
144 // close checksum file
145 ✗ f.close();
146 ✗ return PASSED_FILE_CRC_CHECK;
147 ✗ }
148
149 ✗ crc_stat_t verify_checksum(const char* const fname, U32& expected, U32& actual) {
150 ✗ FW_ASSERT(fname != nullptr);
151
152 FwSizeType i;
153 FwSizeType blocks;
154 FwSizeType remaining_bytes;
155 FwSizeType filesize;
156 ✗ Os::File f;
157 Os::FileSystem::Status fs_stat;
158 Os::File::Status stat;
159 ✗ Utils::Hash hash;
160 U32 checksum;
161 U32 checksum_from_file;
162 FwSizeType 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 ✗ return FAILED_FILE_SIZE;
168 }
169
170 // Open file
171 ✗ stat = f.open(fname, Os::File::OPEN_READ);
172 ✗ if (stat != Os::File::OP_OK) {
173 ✗ return FAILED_FILE_OPEN;
174 }
175
176 // Read file
177 ✗ bytes_to_read = CRC_FILE_READ_BLOCK;
178 ✗ blocks = filesize / CRC_FILE_READ_BLOCK;
179 ✗ for (i = 0; i < blocks; i++) {
180 ✗ stat = f.read(block_data, bytes_to_read);
181 ✗ if (stat != Os::File::OP_OK || bytes_to_read != CRC_FILE_READ_BLOCK) {
182 ✗ f.close();
183 ✗ return FAILED_FILE_READ;
184 }
185
186 ✗ hash.update(block_data, static_cast<FwSizeType>(bytes_to_read));
187 }
188
189 ✗ remaining_bytes = filesize % CRC_FILE_READ_BLOCK;
190 ✗ bytes_to_read = remaining_bytes;
191 ✗ if (remaining_bytes > 0) {
192 ✗ stat = f.read(block_data, bytes_to_read);
193 ✗ if (stat != Os::File::OP_OK || bytes_to_read != remaining_bytes) {
194 ✗ f.close();
195 ✗ return FAILED_FILE_READ;
196 }
197
198 ✗ hash.update(block_data, remaining_bytes);
199 }
200
201 // close file
202 ✗ f.close();
203 // generate checksum
204 ✗ hash.finalize(checksum);
205
206 ✗ crc_stat_t crcstat = read_crc32_from_file(fname, checksum_from_file);
207 ✗ if (crcstat != PASSED_FILE_CRC_CHECK) {
208 ✗ return crcstat;
209 }
210
211 // compare checksums
212 ✗ if (checksum != checksum_from_file) {
213 ✗ expected = checksum_from_file;
214 ✗ actual = checksum;
215 ✗ return FAILED_FILE_CRC_CHECK;
216 }
217
218 ✗ expected = checksum_from_file;
219 ✗ actual = checksum;
220 ✗ return PASSED_FILE_CRC_CHECK;
221 ✗ }
222
223 } // namespace Utils
224