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  NATIVE_INT_TYPE blocks;
28  NATIVE_INT_TYPE remaining_bytes;
29  FwSizeType 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  NATIVE_INT_TYPE int_file_size;
37  NATIVE_INT_TYPE bytes_to_read;
38  NATIVE_INT_TYPE bytes_to_write;
39  char hashFilename[CRC_MAX_FILENAME_SIZE];
40  char 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 = static_cast<NATIVE_INT_TYPE>(filesize);
49  if(static_cast<FwSizeType>(int_file_size) != filesize)
50  {
51  return FAILED_FILE_SIZE_CAST;
52  }
53 
54  // Open file
55  stat = f.open(fname, Os::File::OPEN_READ);
56  if(stat != Os::File::OP_OK)
57  {
58  return FAILED_FILE_OPEN;
59  }
60 
61  // Read file
62  bytes_to_read = CRC_FILE_READ_BLOCK;
63  blocks = int_file_size / CRC_FILE_READ_BLOCK;
64  for(i = 0; i < blocks; i++)
65  {
66  stat = f.read(block_data, bytes_to_read);
67  if(stat != Os::File::OP_OK || bytes_to_read != CRC_FILE_READ_BLOCK)
68  {
69  f.close();
70  return FAILED_FILE_READ;
71  }
72 
73  hash.update(block_data, bytes_to_read);
74  }
75 
76  remaining_bytes = int_file_size % CRC_FILE_READ_BLOCK;
77  bytes_to_read = remaining_bytes;
78  if(remaining_bytes > 0)
79  {
80  stat = f.read(block_data, bytes_to_read);
81  if(stat != Os::File::OP_OK || bytes_to_read != remaining_bytes)
82  {
83  f.close();
84  return FAILED_FILE_READ;
85  }
86 
87  hash.update(block_data, remaining_bytes);
88  }
89 
90  // close file
91  f.close();
92 
93  // generate checksum
94  hash.final(checksum);
95 
96  // open checksum file
97  s_stat = snprintf(hashFilename, CRC_MAX_FILENAME_SIZE, "%s%s", fname, HASH_EXTENSION_STRING);
98  FW_ASSERT(s_stat > 0);
99 
100  stat = f.open(hashFilename, Os::File::OPEN_WRITE);
101  if(stat != Os::File::OP_OK)
102  {
103  return FAILED_FILE_CRC_OPEN;
104  }
105 
106  // Write checksum file
107  bytes_to_write = sizeof(checksum);
108  stat = f.write(reinterpret_cast<U8*>(&checksum), bytes_to_write);
109  if(stat != Os::File::OP_OK || sizeof(checksum) != bytes_to_write)
110  {
111  f.close();
112  return FAILED_FILE_CRC_WRITE;
113  }
114 
115  // close checksum file
116  f.close();
117 
118  return PASSED_FILE_CRC_WRITE;
119  }
120 
121  crc_stat_t read_crc32_from_file(const char* const fname, U32 &checksum_from_file) {
122  Os::File f;
123  Os::File::Status stat;
124  char hashFilename[CRC_MAX_FILENAME_SIZE];
125  FW_ASSERT(fname != nullptr);
126  // open checksum file
127  I32 s_stat = snprintf(hashFilename, CRC_MAX_FILENAME_SIZE, "%s%s", fname, HASH_EXTENSION_STRING);
128  FW_ASSERT(s_stat > 0);
129 
130  stat = f.open(hashFilename, Os::File::OPEN_READ);
131  if(stat != Os::File::OP_OK)
132  {
133  return FAILED_FILE_CRC_OPEN;
134  }
135 
136  // Read checksum file
137  NATIVE_INT_TYPE checksum_from_file_size = sizeof(checksum_from_file);
138  stat = f.read(reinterpret_cast<U8*>(&checksum_from_file), checksum_from_file_size);
139  if(stat != Os::File::OP_OK || checksum_from_file_size != sizeof(checksum_from_file))
140  {
141  f.close();
142  return FAILED_FILE_CRC_READ;
143  }
144 
145  // close checksum file
146  f.close();
147  return PASSED_FILE_CRC_CHECK;
148  }
149 
150  crc_stat_t verify_checksum(const char* const fname, U32 &expected, U32 &actual)
151  {
152  FW_ASSERT(fname != nullptr);
153 
154  NATIVE_INT_TYPE i;
155  NATIVE_INT_TYPE blocks;
156  NATIVE_INT_TYPE remaining_bytes;
157  FwSizeType filesize;
158  Os::File f;
159  Os::FileSystem::Status fs_stat;
160  Os::File::Status stat;
161  Utils::Hash hash;
162  U32 checksum;
163  U32 checksum_from_file;
164  NATIVE_INT_TYPE int_file_size;
165  NATIVE_INT_TYPE bytes_to_read;
166  char block_data[CRC_FILE_READ_BLOCK];
167 
168  fs_stat = Os::FileSystem::getFileSize(fname, filesize);
169  if(fs_stat != Os::FileSystem::OP_OK)
170  {
171  return FAILED_FILE_SIZE;
172  }
173 
174  int_file_size = static_cast<NATIVE_INT_TYPE>(filesize);
175  if(static_cast<FwSizeType>(int_file_size) != filesize)
176  {
177  return FAILED_FILE_SIZE_CAST;
178  }
179 
180  // Open file
181  stat = f.open(fname, Os::File::OPEN_READ);
182  if(stat != Os::File::OP_OK)
183  {
184  return FAILED_FILE_OPEN;
185  }
186 
187  // Read file
188  bytes_to_read = CRC_FILE_READ_BLOCK;
189  blocks = int_file_size / CRC_FILE_READ_BLOCK;
190  for(i = 0; i < blocks; i++)
191  {
192  stat = f.read(block_data, bytes_to_read);
193  if(stat != Os::File::OP_OK || bytes_to_read != CRC_FILE_READ_BLOCK)
194  {
195  f.close();
196  return FAILED_FILE_READ;
197  }
198 
199  hash.update(block_data, bytes_to_read);
200  }
201 
202  remaining_bytes = int_file_size % CRC_FILE_READ_BLOCK;
203  bytes_to_read = remaining_bytes;
204  if(remaining_bytes > 0)
205  {
206  stat = f.read(block_data, bytes_to_read);
207  if(stat != Os::File::OP_OK || bytes_to_read != remaining_bytes)
208  {
209  f.close();
210  return FAILED_FILE_READ;
211  }
212 
213  hash.update(block_data, remaining_bytes);
214  }
215 
216  // close file
217  f.close();
218  // generate checksum
219  hash.final(checksum);
220 
221  crc_stat_t crcstat = read_crc32_from_file(fname, checksum_from_file);
222  if (crcstat != PASSED_FILE_CRC_CHECK) {
223  return crcstat;
224  }
225 
226  // compare checksums
227  if(checksum != checksum_from_file)
228  {
229  expected = checksum_from_file;
230  actual = checksum;
231  return FAILED_FILE_CRC_CHECK;
232  }
233 
234  expected = checksum_from_file;
235  actual = checksum;
236  return PASSED_FILE_CRC_CHECK;
237  }
238 
239 }
#define FW_ASSERT(...)
Definition: Assert.hpp:14
PlatformIntType NATIVE_INT_TYPE
Definition: BasicTypes.h:51
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:26
#define HASH_EXTENSION_STRING
Definition: CRC32.hpp:25
PlatformSizeType FwSizeType
Definition: FpConfig.h:18
C++-compatible configuration header for fprime configuration.
void close()
close file
Definition: File.cpp:36
Status
Definition: File.hpp:23
@ OP_OK
Operation was successful.
Definition: File.hpp:24
Status write(const void *buffer, NATIVE_INT_TYPE &size, bool waitForDone=true)
write size; will return amount written or errno
Definition: File.cpp:32
@ OPEN_WRITE
Open file for writing.
Definition: File.hpp:16
@ OPEN_READ
Open file for reading.
Definition: File.hpp:15
Status open(const char *fileName, Mode mode)
open file. Writing creates file if it doesn't exist
Definition: File.cpp:12
Status read(void *buffer, NATIVE_INT_TYPE &size, bool waitForFull=true)
waitForFull = true to wait for all bytes to be read
Definition: File.cpp:28
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
Status getFileSize(const char *path, FwSizeType &size)
append file origin to destination file. If boolean true, creates a brand new file if the destination ...
Definition: FileSystem.cpp:38
@ OP_OK
Operation was successful.
Definition: FileSystem.hpp:15
crc_stat_t read_crc32_from_file(const char *const fname, U32 &checksum_from_file)
Definition: CRCChecker.cpp:121
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:150
@ 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