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