GCC Code Coverage Report


Directory: Os/
File: ValidateFileCommon.cpp
Date: 2026-09-03 21:15:10
Exec Total Coverage
Lines: 93 139 66.9%
Functions: 8 9 88.9%
Branches: 64 96 66.7%

Line Branch Exec Source
1 #include <Os/File.hpp>
2 #include <Os/FileSystem.hpp>
3 #include <Os/ValidateFile.hpp>
4 #include <Utils/Hash/Hash.hpp>
5
6 namespace Os {
7
8 5 File::Status computeHash(const char* fileName, Utils::HashBuffer& hashBuffer) {
9 File::Status status;
10
11 // Open file:
12
1/1
✓ Branch 2 taken 5 times.
5 File file;
13
1/1
✓ Branch 2 taken 5 times.
5 status = file.open(fileName, File::OPEN_READ);
14
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (File::OP_OK != status) {
15 1 return status;
16 }
17
18 // Get the file size:
19 FileSystem::Status fs_status;
20 4 FwSizeType fileSize = 0;
21
1/1
✓ Branch 1 taken 4 times.
4 fs_status = FileSystem::getFileSize(fileName, fileSize); //!< gets the size of the file (in bytes) at location path
22
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (FileSystem::OP_OK != fs_status) {
23 return File::BAD_SIZE;
24 }
25 4 const FwSizeType max_itr = (fileSize / VFILE_HASH_CHUNK_SIZE + 1);
26
27 // Read all data from file and update hash:
28
1/1
✓ Branch 2 taken 4 times.
4 Utils::Hash hash;
29
1/1
✓ Branch 1 taken 4 times.
4 hash.init();
30 4 U8 buffer[VFILE_HASH_CHUNK_SIZE];
31 4 FwSizeType size = 0;
32 4 FwSizeType cnt = 0;
33
1/2
✓ Branch 0 taken 244548 times.
✗ Branch 1 not taken.
244548 while (cnt <= max_itr) {
34 // Read out chunk from file:
35 244548 size = sizeof(buffer);
36
1/1
✓ Branch 2 taken 244548 times.
244548 status = file.read(buffer, size, Os::File::WaitType::NO_WAIT);
37
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 244548 times.
244548 if (File::OP_OK != status) {
38 return status;
39 }
40 // If end of file, break:
41
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 244544 times.
244548 if (size == 0) {
42 4 break;
43 }
44 // Add chunk to hash calculation:
45
1/1
✓ Branch 1 taken 244544 times.
244544 hash.update(&buffer, static_cast<FwSizeType>(size));
46 244544 cnt++;
47 }
48
1/1
✓ Branch 2 taken 4 times.
4 file.close();
49
50 // The iteration bound is computed from the size at open; a file that grows while
51 // being hashed exhausts it with data still unread, which is an error, not a bug
52
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (size != 0) {
53 return File::BAD_SIZE;
54 }
55
56 // Calculate hash:
57
1/1
✓ Branch 2 taken 4 times.
4 Utils::HashBuffer computedHashBuffer;
58
1/1
✓ Branch 1 taken 4 times.
4 hash.finalize(computedHashBuffer);
59
1/1
✓ Branch 4 taken 4 times.
4 hashBuffer = computedHashBuffer;
60
61 4 return status;
62 5 }
63
64 2 File::Status readHash(const char* hashFileName, Utils::HashBuffer& hashBuffer) {
65 File::Status status;
66
67 // Open hash file:
68
1/1
✓ Branch 2 taken 2 times.
2 File hashFile;
69
1/1
✓ Branch 2 taken 2 times.
2 status = hashFile.open(hashFileName, File::OPEN_READ);
70
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (File::OP_OK != status) {
71 return status;
72 }
73
74 // Read hash from checksum file:
75 2 U8 savedHash[HASH_DIGEST_LENGTH];
76
1/1
✓ Branch 11 taken 2 times.
2 FwSizeType size = static_cast<FwSizeType>(hashBuffer.getCapacity());
77
1/1
✓ Branch 2 taken 2 times.
2 status = hashFile.read(savedHash, size);
78
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (File::OP_OK != status) {
79 return status;
80 }
81
2/3
✓ Branch 10 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 2 times.
2 if (static_cast<FwSizeType>(size) != hashBuffer.getCapacity()) {
82 return File::BAD_SIZE;
83 }
84
1/1
✓ Branch 2 taken 2 times.
2 hashFile.close();
85
86 // Return the hash buffer:
87
1/1
✓ Branch 2 taken 2 times.
2 Utils::HashBuffer savedHashBuffer(savedHash, static_cast<FwSizeType>(size));
88
1/1
✓ Branch 4 taken 2 times.
2 hashBuffer = savedHashBuffer;
89
90 2 return status;
91 2 }
92
93 2 File::Status writeHash(const char* hashFileName, Utils::HashBuffer hashBuffer) {
94 // Open hash file:
95
1/1
✓ Branch 2 taken 2 times.
2 File hashFile;
96 File::Status status;
97
1/1
✓ Branch 2 taken 2 times.
2 status = hashFile.open(hashFileName, File::OPEN_WRITE);
98
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (File::OP_OK != status) {
99 1 return status;
100 }
101
102 // Write out the hash
103
1/1
✓ Branch 6 taken 1 times.
1 FwSizeType size = static_cast<FwSizeType>(hashBuffer.getSize());
104
1/1
✓ Branch 7 taken 1 times.
1 status = hashFile.write(hashBuffer.getBuffAddr(), size, Os::File::WaitType::NO_WAIT);
105
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (File::OP_OK != status) {
106 return status;
107 }
108
2/3
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
1 if (static_cast<FwSizeType>(size) != hashBuffer.getSize()) {
109 return File::BAD_SIZE;
110 }
111
1/1
✓ Branch 2 taken 1 times.
1 hashFile.close();
112
113 1 return status;
114 2 }
115
116 // Enum and function for translating from a status to a validation status:
117 typedef enum { FileType, HashFileType } StatusFileType;
118
119 2 ValidateFile::Status translateStatus(File::Status status, StatusFileType type) {
120
2/3
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 switch (type) {
121 1 case FileType:
122
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1 switch (status) {
123 case File::OP_OK:
124 return ValidateFile::VALIDATION_OK;
125 1 case File::DOESNT_EXIST:
126 1 return ValidateFile::FILE_DOESNT_EXIST;
127 case File::NO_SPACE:
128 return ValidateFile::NO_SPACE;
129 case File::NO_PERMISSION:
130 return ValidateFile::FILE_NO_PERMISSION;
131 case File::BAD_SIZE:
132 return ValidateFile::FILE_BAD_SIZE;
133 case File::NOT_OPENED:
134 return ValidateFile::OTHER_ERROR;
135 case File::OTHER_ERROR:
136 return ValidateFile::OTHER_ERROR;
137 default:
138 // Unlisted statuses (e.g. NOT_SUPPORTED, INVALID_ARGUMENT) can
139 // legitimately come from the OS layer; report rather than assert
140 return ValidateFile::OTHER_ERROR;
141 }
142 break;
143 1 case HashFileType:
144
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1 switch (status) {
145 case File::OP_OK:
146 return ValidateFile::VALIDATION_OK;
147 1 case File::DOESNT_EXIST:
148 1 return ValidateFile::VALIDATION_FILE_DOESNT_EXIST;
149 case File::NO_SPACE:
150 return ValidateFile::NO_SPACE;
151 case File::NO_PERMISSION:
152 return ValidateFile::VALIDATION_FILE_NO_PERMISSION;
153 case File::BAD_SIZE:
154 return ValidateFile::VALIDATION_FILE_BAD_SIZE;
155 case File::NOT_OPENED:
156 return ValidateFile::OTHER_ERROR;
157 case File::OTHER_ERROR:
158 return ValidateFile::OTHER_ERROR;
159 default:
160 // Unlisted statuses (e.g. NOT_SUPPORTED, INVALID_ARGUMENT) can
161 // legitimately come from the OS layer; report rather than assert
162 return ValidateFile::OTHER_ERROR;
163 }
164 break;
165 default:
166 FW_ASSERT(false, type);
167 }
168
169 return ValidateFile::OTHER_ERROR;
170 }
171
172 2 ValidateFile::Status ValidateFile::validate(const char* fileName, const char* hashFileName) {
173
1/1
✓ Branch 2 taken 2 times.
2 Utils::HashBuffer hashBuffer; // pass by reference - final value is unused
174
1/1
✓ Branch 1 taken 2 times.
4 return validate(fileName, hashFileName, hashBuffer);
175 2 }
176
177 2 ValidateFile::Status ValidateFile::validate(const char* fileName,
178 const char* hashFileName,
179 Utils::HashBuffer& hashBuffer) {
180 File::Status status;
181
182 // Read the hash file:
183
1/1
✓ Branch 2 taken 2 times.
2 Utils::HashBuffer savedHash;
184
1/1
✓ Branch 1 taken 2 times.
2 status = readHash(hashFileName, savedHash);
185
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (File::OP_OK != status) {
186 return translateStatus(status, HashFileType);
187 }
188
189 // Compute the file's hash:
190
1/1
✓ Branch 2 taken 2 times.
2 Utils::HashBuffer computedHash;
191
1/1
✓ Branch 1 taken 2 times.
2 status = computeHash(fileName, computedHash);
192
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (File::OP_OK != status) {
193 return translateStatus(status, FileType);
194 }
195
196 // Compare hashes and return:
197
3/3
✓ Branch 2 taken 2 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
2 if (savedHash != computedHash) {
198 1 return ValidateFile::VALIDATION_FAIL;
199 }
200
201
1/1
✓ Branch 4 taken 1 times.
1 hashBuffer = savedHash;
202
203 1 return ValidateFile::VALIDATION_OK;
204 2 }
205
206 3 ValidateFile::Status ValidateFile::createValidation(const char* fileName,
207 const char* hashFileName,
208 Utils::HashBuffer& hashBuffer) {
209 File::Status status;
210
211 // Compute the file's hash:
212 3 status = computeHash(fileName, hashBuffer);
213
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (File::OP_OK != status) {
214 1 return translateStatus(status, FileType);
215 }
216
217
2/2
✓ Branch 3 taken 2 times.
✓ Branch 6 taken 2 times.
2 status = writeHash(hashFileName, hashBuffer);
218
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (File::OP_OK != status) {
219 1 return translateStatus(status, HashFileType);
220 }
221
222 1 return ValidateFile::VALIDATION_OK;
223 }
224
225 3 ValidateFile::Status ValidateFile::createValidation(const char* fileName, const char* hashFileName) {
226
1/1
✓ Branch 2 taken 3 times.
3 Utils::HashBuffer hashBuffer; // pass by reference - final value is unused
227
1/1
✓ Branch 1 taken 3 times.
6 return createValidation(fileName, hashFileName, hashBuffer);
228 3 }
229
230 ValidateFile::Status ValidateFile::createValidation(const char* hashFileName, const Utils::HashBuffer& hashBuffer) {
231 File::Status status;
232
233 status = writeHash(hashFileName, hashBuffer);
234 if (File::OP_OK != status) {
235 return translateStatus(status, HashFileType);
236 }
237
238 return ValidateFile::VALIDATION_OK;
239 }
240
241 } // namespace Os
242