fprime/Os/ValidateFileCommon.cpp
Vince Woo 48e4720419
Created new SerialBufferBase as a parent of SerializeBufferBase (now renamed LinearBufferBase). (#4288)
* Created new SerialBufferBase as a parent of SerializeBufferBase. Renaming interface functions to be less confusing.

* Deprecating copyRawOffset. No direct use-cases in F' core.

* Make SerialBufferBase a true pure virtual interface.

* Changing Serializable to work with SerialBufferBase parent interface.

* Changing copyRaw and copyRawOffset to work with SerialBufferBase

* Updating documentation for SerialBufferBase usage

* Adding some documentation. Adding missing ASSERT in copyRaw. Fixing some bugs that new ASSERT uncovered.

* Renaming SerializeBufferBase to LinearBufferBase. Add a using declaration to maintain backwards compatability. Properly mark LinearBufferBase functions as override.

* Filling in the rest of the docstrings for the classes in Serializable

* Removing redundant virtual keyword on override function

* Applying clang formatting

* Incorporating PR comments

* Fix compile issues

* Bump version to alpha

* Format

* v

---------

Co-authored-by: M Starch <LeStarch@googlemail.com>
2025-11-06 16:23:20 -08:00

225 lines
7.0 KiB
C++

#include <Os/File.hpp>
#include <Os/FileSystem.hpp>
#include <Os/ValidateFile.hpp>
#include <Utils/Hash/Hash.hpp>
namespace Os {
File::Status computeHash(const char* fileName, Utils::HashBuffer& hashBuffer) {
File::Status status;
// Open file:
File file;
status = file.open(fileName, File::OPEN_READ);
if (File::OP_OK != status) {
return status;
}
// Get the file size:
FileSystem::Status fs_status;
FwSizeType fileSize = 0;
fs_status = FileSystem::getFileSize(fileName, fileSize); //!< gets the size of the file (in bytes) at location path
if (FileSystem::OP_OK != fs_status) {
return File::BAD_SIZE;
}
const FwSizeType max_itr = (fileSize / VFILE_HASH_CHUNK_SIZE + 1);
// Read all data from file and update hash:
Utils::Hash hash;
hash.init();
U8 buffer[VFILE_HASH_CHUNK_SIZE];
FwSizeType size = 0;
FwSizeType cnt = 0;
while (cnt <= max_itr) {
// Read out chunk from file:
size = sizeof(buffer);
status = file.read(buffer, size, Os::File::WaitType::NO_WAIT);
if (File::OP_OK != status) {
return status;
}
// If end of file, break:
if (size == 0) {
break;
}
// Add chunk to hash calculation:
hash.update(&buffer, static_cast<FwSizeType>(size));
cnt++;
}
file.close();
// We should not have left the loop because of cnt > max_itr:
FW_ASSERT(size == 0);
FW_ASSERT(cnt <= max_itr);
// Calculate hash:
Utils::HashBuffer computedHashBuffer;
hash.final(computedHashBuffer);
hashBuffer = computedHashBuffer;
return status;
}
File::Status readHash(const char* hashFileName, Utils::HashBuffer& hashBuffer) {
File::Status status;
// Open hash file:
File hashFile;
status = hashFile.open(hashFileName, File::OPEN_READ);
if (File::OP_OK != status) {
return status;
}
// Read hash from checksum file:
unsigned char savedHash[HASH_DIGEST_LENGTH];
FwSizeType size = static_cast<FwSizeType>(hashBuffer.getCapacity());
status = hashFile.read(savedHash, size);
if (File::OP_OK != status) {
return status;
}
if (static_cast<FwSizeType>(size) != hashBuffer.getCapacity()) {
return File::BAD_SIZE;
}
hashFile.close();
// Return the hash buffer:
Utils::HashBuffer savedHashBuffer(savedHash, static_cast<FwSizeType>(size));
hashBuffer = savedHashBuffer;
return status;
}
File::Status writeHash(const char* hashFileName, Utils::HashBuffer hashBuffer) {
// Open hash file:
File hashFile;
File::Status status;
status = hashFile.open(hashFileName, File::OPEN_WRITE);
if (File::OP_OK != status) {
return status;
}
// Write out the hash
FwSizeType size = static_cast<FwSizeType>(hashBuffer.getSize());
status = hashFile.write(hashBuffer.getBuffAddr(), size, Os::File::WaitType::NO_WAIT);
if (File::OP_OK != status) {
return status;
}
if (static_cast<FwSizeType>(size) != hashBuffer.getSize()) {
return File::BAD_SIZE;
}
hashFile.close();
return status;
}
// Enum and function for translating from a status to a validation status:
typedef enum { FileType, HashFileType } StatusFileType;
ValidateFile::Status translateStatus(File::Status status, StatusFileType type) {
switch (type) {
case FileType:
switch (status) {
case File::OP_OK:
return ValidateFile::VALIDATION_OK;
case File::DOESNT_EXIST:
return ValidateFile::FILE_DOESNT_EXIST;
case File::NO_SPACE:
return ValidateFile::NO_SPACE;
case File::NO_PERMISSION:
return ValidateFile::FILE_NO_PERMISSION;
case File::BAD_SIZE:
return ValidateFile::FILE_BAD_SIZE;
case File::NOT_OPENED:
return ValidateFile::OTHER_ERROR;
case File::OTHER_ERROR:
return ValidateFile::OTHER_ERROR;
default:
FW_ASSERT(0, status);
}
break;
case HashFileType:
switch (status) {
case File::OP_OK:
return ValidateFile::VALIDATION_OK;
case File::DOESNT_EXIST:
return ValidateFile::VALIDATION_FILE_DOESNT_EXIST;
case File::NO_SPACE:
return ValidateFile::NO_SPACE;
case File::NO_PERMISSION:
return ValidateFile::VALIDATION_FILE_NO_PERMISSION;
case File::BAD_SIZE:
return ValidateFile::VALIDATION_FILE_BAD_SIZE;
case File::NOT_OPENED:
return ValidateFile::OTHER_ERROR;
case File::OTHER_ERROR:
return ValidateFile::OTHER_ERROR;
default:
FW_ASSERT(0, status);
}
break;
default:
FW_ASSERT(0, type);
}
return ValidateFile::OTHER_ERROR;
}
ValidateFile::Status ValidateFile::validate(const char* fileName, const char* hashFileName) {
Utils::HashBuffer hashBuffer; // pass by reference - final value is unused
return validate(fileName, hashFileName, hashBuffer);
}
ValidateFile::Status ValidateFile::validate(const char* fileName,
const char* hashFileName,
Utils::HashBuffer& hashBuffer) {
File::Status status;
// Read the hash file:
Utils::HashBuffer savedHash;
status = readHash(hashFileName, savedHash);
if (File::OP_OK != status) {
return translateStatus(status, HashFileType);
}
// Compute the file's hash:
Utils::HashBuffer computedHash;
status = computeHash(fileName, computedHash);
if (File::OP_OK != status) {
return translateStatus(status, FileType);
}
// Compare hashes and return:
if (savedHash != computedHash) {
return ValidateFile::VALIDATION_FAIL;
}
hashBuffer = savedHash;
return ValidateFile::VALIDATION_OK;
}
ValidateFile::Status ValidateFile::createValidation(const char* fileName,
const char* hashFileName,
Utils::HashBuffer& hashBuffer) {
File::Status status;
// Compute the file's hash:
status = computeHash(fileName, hashBuffer);
if (File::OP_OK != status) {
return translateStatus(status, FileType);
}
status = writeHash(hashFileName, hashBuffer);
if (File::OP_OK != status) {
return translateStatus(status, HashFileType);
}
return ValidateFile::VALIDATION_OK;
}
ValidateFile::Status ValidateFile::createValidation(const char* fileName, const char* hashFileName) {
Utils::HashBuffer hashBuffer; // pass by reference - final value is unused
return createValidation(fileName, hashFileName, hashBuffer);
}
} // namespace Os