mirror of
https://github.com/nasa/fprime.git
synced 2025-12-11 23:38:06 -06:00
* lestarch: update for small platform support (no U64) * first-pass at fixing types interface * fixing U64s in merged commit * fixing improper loop limit * fixing FwSizeType redefinition * fixing review comments * formatting Linux/FileSystem * fixing static analysis errors * fixing UTs when file system or memory to large * disabling broken ut and fixing spelling * cleaning up unused variable * adding more comments to explain casting checks
240 lines
6.1 KiB
C++
240 lines
6.1 KiB
C++
// ======================================================================
|
|
// \title CRCChecker.cpp
|
|
// \author ortega
|
|
// \brief cpp file for a crc32 checker
|
|
//
|
|
// \copyright
|
|
// Copyright 2009-2020, by the California Institute of Technology.
|
|
// ALL RIGHTS RESERVED. United States Government Sponsorship
|
|
// acknowledged.
|
|
// ======================================================================
|
|
|
|
#include <FpConfig.hpp>
|
|
#include <cstdio> // For snprintf
|
|
#include <Utils/CRCChecker.hpp>
|
|
#include <Fw/Types/Assert.hpp>
|
|
#include <Os/File.hpp>
|
|
#include <Os/FileSystem.hpp>
|
|
#include <Utils/Hash/Hash.hpp>
|
|
|
|
namespace Utils {
|
|
|
|
crc_stat_t create_checksum_file(const char* const fname)
|
|
{
|
|
FW_ASSERT(fname != nullptr);
|
|
|
|
NATIVE_INT_TYPE i;
|
|
NATIVE_INT_TYPE blocks;
|
|
NATIVE_INT_TYPE remaining_bytes;
|
|
FwSizeType filesize;
|
|
Os::File f;
|
|
Os::FileSystem::Status fs_stat;
|
|
Os::File::Status stat;
|
|
Utils::Hash hash;
|
|
U32 checksum;
|
|
I32 s_stat;
|
|
NATIVE_INT_TYPE int_file_size;
|
|
NATIVE_INT_TYPE bytes_to_read;
|
|
NATIVE_INT_TYPE bytes_to_write;
|
|
char hashFilename[CRC_MAX_FILENAME_SIZE];
|
|
char block_data[CRC_FILE_READ_BLOCK];
|
|
|
|
fs_stat = Os::FileSystem::getFileSize(fname, filesize);
|
|
if(fs_stat != Os::FileSystem::OP_OK)
|
|
{
|
|
return FAILED_FILE_SIZE;
|
|
}
|
|
|
|
int_file_size = static_cast<NATIVE_INT_TYPE>(filesize);
|
|
if(static_cast<FwSizeType>(int_file_size) != filesize)
|
|
{
|
|
return FAILED_FILE_SIZE_CAST;
|
|
}
|
|
|
|
// Open file
|
|
stat = f.open(fname, Os::File::OPEN_READ);
|
|
if(stat != Os::File::OP_OK)
|
|
{
|
|
return FAILED_FILE_OPEN;
|
|
}
|
|
|
|
// Read file
|
|
bytes_to_read = CRC_FILE_READ_BLOCK;
|
|
blocks = int_file_size / CRC_FILE_READ_BLOCK;
|
|
for(i = 0; i < blocks; i++)
|
|
{
|
|
stat = f.read(block_data, bytes_to_read);
|
|
if(stat != Os::File::OP_OK || bytes_to_read != CRC_FILE_READ_BLOCK)
|
|
{
|
|
f.close();
|
|
return FAILED_FILE_READ;
|
|
}
|
|
|
|
hash.update(block_data, bytes_to_read);
|
|
}
|
|
|
|
remaining_bytes = int_file_size % CRC_FILE_READ_BLOCK;
|
|
bytes_to_read = remaining_bytes;
|
|
if(remaining_bytes > 0)
|
|
{
|
|
stat = f.read(block_data, bytes_to_read);
|
|
if(stat != Os::File::OP_OK || bytes_to_read != remaining_bytes)
|
|
{
|
|
f.close();
|
|
return FAILED_FILE_READ;
|
|
}
|
|
|
|
hash.update(block_data, remaining_bytes);
|
|
}
|
|
|
|
// close file
|
|
f.close();
|
|
|
|
// generate checksum
|
|
hash.final(checksum);
|
|
|
|
// open checksum file
|
|
s_stat = snprintf(hashFilename, CRC_MAX_FILENAME_SIZE, "%s%s", fname, HASH_EXTENSION_STRING);
|
|
FW_ASSERT(s_stat > 0);
|
|
|
|
stat = f.open(hashFilename, Os::File::OPEN_WRITE);
|
|
if(stat != Os::File::OP_OK)
|
|
{
|
|
return FAILED_FILE_CRC_OPEN;
|
|
}
|
|
|
|
// Write checksum file
|
|
bytes_to_write = sizeof(checksum);
|
|
stat = f.write(reinterpret_cast<U8*>(&checksum), bytes_to_write);
|
|
if(stat != Os::File::OP_OK || sizeof(checksum) != bytes_to_write)
|
|
{
|
|
f.close();
|
|
return FAILED_FILE_CRC_WRITE;
|
|
}
|
|
|
|
// close checksum file
|
|
f.close();
|
|
|
|
return PASSED_FILE_CRC_WRITE;
|
|
}
|
|
|
|
crc_stat_t read_crc32_from_file(const char* const fname, U32 &checksum_from_file) {
|
|
Os::File f;
|
|
Os::File::Status stat;
|
|
char hashFilename[CRC_MAX_FILENAME_SIZE];
|
|
FW_ASSERT(fname != nullptr);
|
|
// open checksum file
|
|
I32 s_stat = snprintf(hashFilename, CRC_MAX_FILENAME_SIZE, "%s%s", fname, HASH_EXTENSION_STRING);
|
|
FW_ASSERT(s_stat > 0);
|
|
|
|
stat = f.open(hashFilename, Os::File::OPEN_READ);
|
|
if(stat != Os::File::OP_OK)
|
|
{
|
|
return FAILED_FILE_CRC_OPEN;
|
|
}
|
|
|
|
// Read checksum file
|
|
NATIVE_INT_TYPE checksum_from_file_size = sizeof(checksum_from_file);
|
|
stat = f.read(reinterpret_cast<U8*>(&checksum_from_file), checksum_from_file_size);
|
|
if(stat != Os::File::OP_OK || checksum_from_file_size != sizeof(checksum_from_file))
|
|
{
|
|
f.close();
|
|
return FAILED_FILE_CRC_READ;
|
|
}
|
|
|
|
// close checksum file
|
|
f.close();
|
|
return PASSED_FILE_CRC_CHECK;
|
|
}
|
|
|
|
crc_stat_t verify_checksum(const char* const fname, U32 &expected, U32 &actual)
|
|
{
|
|
FW_ASSERT(fname != nullptr);
|
|
|
|
NATIVE_INT_TYPE i;
|
|
NATIVE_INT_TYPE blocks;
|
|
NATIVE_INT_TYPE remaining_bytes;
|
|
FwSizeType filesize;
|
|
Os::File f;
|
|
Os::FileSystem::Status fs_stat;
|
|
Os::File::Status stat;
|
|
Utils::Hash hash;
|
|
U32 checksum;
|
|
U32 checksum_from_file;
|
|
NATIVE_INT_TYPE int_file_size;
|
|
NATIVE_INT_TYPE bytes_to_read;
|
|
char block_data[CRC_FILE_READ_BLOCK];
|
|
|
|
fs_stat = Os::FileSystem::getFileSize(fname, filesize);
|
|
if(fs_stat != Os::FileSystem::OP_OK)
|
|
{
|
|
return FAILED_FILE_SIZE;
|
|
}
|
|
|
|
int_file_size = static_cast<NATIVE_INT_TYPE>(filesize);
|
|
if(static_cast<FwSizeType>(int_file_size) != filesize)
|
|
{
|
|
return FAILED_FILE_SIZE_CAST;
|
|
}
|
|
|
|
// Open file
|
|
stat = f.open(fname, Os::File::OPEN_READ);
|
|
if(stat != Os::File::OP_OK)
|
|
{
|
|
return FAILED_FILE_OPEN;
|
|
}
|
|
|
|
// Read file
|
|
bytes_to_read = CRC_FILE_READ_BLOCK;
|
|
blocks = int_file_size / CRC_FILE_READ_BLOCK;
|
|
for(i = 0; i < blocks; i++)
|
|
{
|
|
stat = f.read(block_data, bytes_to_read);
|
|
if(stat != Os::File::OP_OK || bytes_to_read != CRC_FILE_READ_BLOCK)
|
|
{
|
|
f.close();
|
|
return FAILED_FILE_READ;
|
|
}
|
|
|
|
hash.update(block_data, bytes_to_read);
|
|
}
|
|
|
|
remaining_bytes = int_file_size % CRC_FILE_READ_BLOCK;
|
|
bytes_to_read = remaining_bytes;
|
|
if(remaining_bytes > 0)
|
|
{
|
|
stat = f.read(block_data, bytes_to_read);
|
|
if(stat != Os::File::OP_OK || bytes_to_read != remaining_bytes)
|
|
{
|
|
f.close();
|
|
return FAILED_FILE_READ;
|
|
}
|
|
|
|
hash.update(block_data, remaining_bytes);
|
|
}
|
|
|
|
// close file
|
|
f.close();
|
|
// generate checksum
|
|
hash.final(checksum);
|
|
|
|
crc_stat_t crcstat = read_crc32_from_file(fname, checksum_from_file);
|
|
if (crcstat != PASSED_FILE_CRC_CHECK) {
|
|
return crcstat;
|
|
}
|
|
|
|
// compare checksums
|
|
if(checksum != checksum_from_file)
|
|
{
|
|
expected = checksum_from_file;
|
|
actual = checksum;
|
|
return FAILED_FILE_CRC_CHECK;
|
|
}
|
|
|
|
expected = checksum_from_file;
|
|
actual = checksum;
|
|
return PASSED_FILE_CRC_CHECK;
|
|
}
|
|
|
|
}
|