#include #include #include #include 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(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(hashBuffer.getCapacity()); status = hashFile.read(savedHash, size); if (File::OP_OK != status) { return status; } if (static_cast(size) != hashBuffer.getCapacity()) { return File::BAD_SIZE; } hashFile.close(); // Return the hash buffer: Utils::HashBuffer savedHashBuffer(savedHash, static_cast(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(hashBuffer.getSize()); status = hashFile.write(hashBuffer.getBuffAddr(), size, Os::File::WaitType::NO_WAIT); if (File::OP_OK != status) { return status; } if (static_cast(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