/src/libwtcdb/libwtcdb/libwtcdb_cache_entry.c
Line | Count | Source |
1 | | /* |
2 | | * Cache entry functions |
3 | | * |
4 | | * Copyright (C) 2010-2026, Joachim Metz <joachim.metz@gmail.com> |
5 | | * |
6 | | * Refer to AUTHORS for acknowledgements. |
7 | | * |
8 | | * This program is free software: you can redistribute it and/or modify |
9 | | * it under the terms of the GNU Lesser General Public License as published by |
10 | | * the Free Software Foundation, either version 3 of the License, or |
11 | | * (at your option) any later version. |
12 | | * |
13 | | * This program is distributed in the hope that it will be useful, |
14 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | | * GNU General Public License for more details. |
17 | | * |
18 | | * You should have received a copy of the GNU Lesser General Public License |
19 | | * along with this program. If not, see <https://www.gnu.org/licenses/>. |
20 | | */ |
21 | | |
22 | | #include <common.h> |
23 | | #include <memory.h> |
24 | | #include <types.h> |
25 | | |
26 | | #include "libwtcdb_cache_entry.h" |
27 | | #include "libwtcdb_crc.h" |
28 | | #include "libwtcdb_debug.h" |
29 | | #include "libwtcdb_definitions.h" |
30 | | #include "libwtcdb_io_handle.h" |
31 | | #include "libwtcdb_libbfio.h" |
32 | | #include "libwtcdb_libcerror.h" |
33 | | #include "libwtcdb_libcnotify.h" |
34 | | #include "libwtcdb_libuna.h" |
35 | | |
36 | | #include "wtcdb_cache_entry.h" |
37 | | |
38 | | /* Creates a cache entry |
39 | | * Make sure the value cache_entry is referencing, is set to NULL |
40 | | * Returns 1 if successful or -1 on error |
41 | | */ |
42 | | int libwtcdb_cache_entry_initialize( |
43 | | libwtcdb_cache_entry_t **cache_entry, |
44 | | libcerror_error_t **error ) |
45 | 3.50k | { |
46 | 3.50k | static char *function = "libwtcdb_cache_entry_initialize"; |
47 | | |
48 | 3.50k | if( cache_entry == NULL ) |
49 | 0 | { |
50 | 0 | libcerror_error_set( |
51 | 0 | error, |
52 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
53 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
54 | 0 | "%s: invalid cache entry.", |
55 | 0 | function ); |
56 | |
|
57 | 0 | return( -1 ); |
58 | 0 | } |
59 | 3.50k | if( *cache_entry != NULL ) |
60 | 0 | { |
61 | 0 | libcerror_error_set( |
62 | 0 | error, |
63 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
64 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, |
65 | 0 | "%s: invalid cache entry value already set.", |
66 | 0 | function ); |
67 | |
|
68 | 0 | return( -1 ); |
69 | 0 | } |
70 | 3.50k | *cache_entry = memory_allocate_structure( |
71 | 3.50k | libwtcdb_cache_entry_t ); |
72 | | |
73 | 3.50k | if( *cache_entry == NULL ) |
74 | 0 | { |
75 | 0 | libcerror_error_set( |
76 | 0 | error, |
77 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
78 | 0 | LIBCERROR_MEMORY_ERROR_INSUFFICIENT, |
79 | 0 | "%s: unable to create cache entry.", |
80 | 0 | function ); |
81 | |
|
82 | 0 | goto on_error; |
83 | 0 | } |
84 | 3.50k | if( memory_set( |
85 | 3.50k | *cache_entry, |
86 | 3.50k | 0, |
87 | 3.50k | sizeof( libwtcdb_cache_entry_t ) ) == NULL ) |
88 | 0 | { |
89 | 0 | libcerror_error_set( |
90 | 0 | error, |
91 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
92 | 0 | LIBCERROR_MEMORY_ERROR_SET_FAILED, |
93 | 0 | "%s: unable to clear cache entry.", |
94 | 0 | function ); |
95 | |
|
96 | 0 | goto on_error; |
97 | 0 | } |
98 | 3.50k | return( 1 ); |
99 | | |
100 | 0 | on_error: |
101 | 0 | if( *cache_entry != NULL ) |
102 | 0 | { |
103 | 0 | memory_free( |
104 | 0 | *cache_entry ); |
105 | |
|
106 | 0 | *cache_entry = NULL; |
107 | 0 | } |
108 | 0 | return( -1 ); |
109 | 3.50k | } |
110 | | |
111 | | /* Frees a cache entry |
112 | | * Returns 1 if successful or -1 on error |
113 | | */ |
114 | | int libwtcdb_cache_entry_free( |
115 | | libwtcdb_cache_entry_t **cache_entry, |
116 | | libcerror_error_t **error ) |
117 | 3.50k | { |
118 | 3.50k | static char *function = "libwtcdb_cache_entry_free"; |
119 | | |
120 | 3.50k | if( cache_entry == NULL ) |
121 | 0 | { |
122 | 0 | libcerror_error_set( |
123 | 0 | error, |
124 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
125 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
126 | 0 | "%s: invalid cache entry.", |
127 | 0 | function ); |
128 | |
|
129 | 0 | return( -1 ); |
130 | 0 | } |
131 | 3.50k | if( *cache_entry != NULL ) |
132 | 3.50k | { |
133 | 3.50k | if( ( *cache_entry )->identifier != NULL ) |
134 | 597 | { |
135 | 597 | memory_free( |
136 | 597 | ( *cache_entry )->identifier ); |
137 | 597 | } |
138 | 3.50k | memory_free( |
139 | 3.50k | *cache_entry ); |
140 | | |
141 | 3.50k | *cache_entry = NULL; |
142 | 3.50k | } |
143 | 3.50k | return( 1 ); |
144 | 3.50k | } |
145 | | |
146 | | /* Reads a cache entry header |
147 | | * Returns 1 if successful or -1 on error |
148 | | */ |
149 | | int libwtcdb_cache_entry_header_read_data( |
150 | | libwtcdb_cache_entry_t *cache_entry, |
151 | | libwtcdb_io_handle_t *io_handle, |
152 | | const uint8_t *data, |
153 | | size_t data_size, |
154 | | libcerror_error_t **error ) |
155 | 3.43k | { |
156 | 3.43k | static char *function = "libwtcdb_cache_entry_header_read_data"; |
157 | 3.43k | size_t cache_entry_header_size = 0; |
158 | 3.43k | uint64_t calculated_crc = 0; |
159 | 3.43k | uint64_t stored_header_crc = 0; |
160 | | |
161 | | #if defined( HAVE_DEBUG_OUTPUT ) |
162 | | uint64_t value_64bit = 0; |
163 | | uint32_t value_32bit = 0; |
164 | | #endif |
165 | | |
166 | 3.43k | if( cache_entry == NULL ) |
167 | 0 | { |
168 | 0 | libcerror_error_set( |
169 | 0 | error, |
170 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
171 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
172 | 0 | "%s: invalid cache entry.", |
173 | 0 | function ); |
174 | |
|
175 | 0 | return( -1 ); |
176 | 0 | } |
177 | 3.43k | if( io_handle == NULL ) |
178 | 0 | { |
179 | 0 | libcerror_error_set( |
180 | 0 | error, |
181 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
182 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
183 | 0 | "%s: invalid IO handle.", |
184 | 0 | function ); |
185 | |
|
186 | 0 | return( -1 ); |
187 | 0 | } |
188 | 3.43k | if( io_handle->file_type != LIBWTCDB_FILE_TYPE_CACHE ) |
189 | 0 | { |
190 | 0 | libcerror_error_set( |
191 | 0 | error, |
192 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
193 | 0 | LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, |
194 | 0 | "%s: invalid IO handle - unsupported file type.", |
195 | 0 | function ); |
196 | |
|
197 | 0 | return( -1 ); |
198 | 0 | } |
199 | 3.43k | if( ( io_handle->format_version != 20 ) |
200 | 3.05k | && ( io_handle->format_version != 21 ) |
201 | 1.40k | && ( io_handle->format_version != 30 ) |
202 | 903 | && ( io_handle->format_version != 31 ) |
203 | 386 | && ( io_handle->format_version != 32 ) ) |
204 | 0 | { |
205 | 0 | libcerror_error_set( |
206 | 0 | error, |
207 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
208 | 0 | LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, |
209 | 0 | "%s: invalid IO handle - unsupported format version: %" PRIu32 ".", |
210 | 0 | function, |
211 | 0 | io_handle->format_version ); |
212 | |
|
213 | 0 | return( -1 ); |
214 | 0 | } |
215 | 3.43k | if( io_handle->format_version == 20 ) |
216 | 383 | { |
217 | 383 | cache_entry_header_size = sizeof( wtcdb_cache_entry_v20_t ); |
218 | 383 | } |
219 | 3.05k | else if( io_handle->format_version == 21 ) |
220 | 1.64k | { |
221 | 1.64k | cache_entry_header_size = sizeof( wtcdb_cache_entry_v21_t ); |
222 | 1.64k | } |
223 | 1.40k | else if( ( io_handle->format_version == 30 ) |
224 | 903 | || ( io_handle->format_version == 31 ) |
225 | 386 | || ( io_handle->format_version == 32 ) ) |
226 | 1.40k | { |
227 | 1.40k | cache_entry_header_size = sizeof( wtcdb_cache_entry_v30_t ); |
228 | 1.40k | } |
229 | 3.43k | if( data == NULL ) |
230 | 0 | { |
231 | 0 | libcerror_error_set( |
232 | 0 | error, |
233 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
234 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
235 | 0 | "%s: invalid data.", |
236 | 0 | function ); |
237 | |
|
238 | 0 | return( -1 ); |
239 | 0 | } |
240 | 3.43k | if( data_size < cache_entry_header_size ) |
241 | 0 | { |
242 | 0 | libcerror_error_set( |
243 | 0 | error, |
244 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
245 | 0 | LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, |
246 | 0 | "%s: invalid data size value too small.", |
247 | 0 | function ); |
248 | |
|
249 | 0 | return( -1 ); |
250 | 0 | } |
251 | 3.43k | if( data_size > (size_t) SSIZE_MAX ) |
252 | 0 | { |
253 | 0 | libcerror_error_set( |
254 | 0 | error, |
255 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
256 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, |
257 | 0 | "%s: invalid data size value exceeds maximum.", |
258 | 0 | function ); |
259 | |
|
260 | 0 | return( -1 ); |
261 | 0 | } |
262 | | #if defined( HAVE_DEBUG_OUTPUT ) |
263 | | if( libcnotify_verbose != 0 ) |
264 | | { |
265 | | libcnotify_printf( |
266 | | "%s: cache entry header data:\n", |
267 | | function ); |
268 | | libcnotify_print_data( |
269 | | data, |
270 | | data_size, |
271 | | LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); |
272 | | } |
273 | | #endif |
274 | 3.43k | if( memory_compare( |
275 | 3.43k | ( (wtcdb_cache_entry_v20_t *) data )->signature, |
276 | 3.43k | wtcdb_cache_file_signature, |
277 | 3.43k | 4 ) != 0 ) |
278 | 4 | { |
279 | 4 | libcerror_error_set( |
280 | 4 | error, |
281 | 4 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
282 | 4 | LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, |
283 | 4 | "%s: invalid signature.", |
284 | 4 | function ); |
285 | | |
286 | 4 | return( -1 ); |
287 | 4 | } |
288 | 3.42k | byte_stream_copy_to_uint32_little_endian( |
289 | 3.42k | ( (wtcdb_cache_entry_v20_t *) data )->size, |
290 | 3.42k | cache_entry->data_size ); |
291 | | |
292 | 3.42k | byte_stream_copy_to_uint64_little_endian( |
293 | 3.42k | ( (wtcdb_cache_entry_v20_t *) data )->entry_hash, |
294 | 3.42k | cache_entry->hash ); |
295 | | |
296 | 3.42k | if( io_handle->format_version == 20 ) |
297 | 383 | { |
298 | 383 | byte_stream_copy_to_uint32_little_endian( |
299 | 383 | ( (wtcdb_cache_entry_v20_t *) data )->identifier_string_size, |
300 | 383 | cache_entry->identifier_size ); |
301 | | |
302 | 383 | byte_stream_copy_to_uint32_little_endian( |
303 | 383 | ( (wtcdb_cache_entry_v20_t *) data )->padding_size, |
304 | 383 | cache_entry->padding_size ); |
305 | | |
306 | 383 | byte_stream_copy_to_uint32_little_endian( |
307 | 383 | ( (wtcdb_cache_entry_v20_t *) data )->data_size, |
308 | 383 | cache_entry->cached_data_size ); |
309 | | |
310 | 383 | byte_stream_copy_to_uint64_little_endian( |
311 | 383 | ( (wtcdb_cache_entry_v20_t *) data )->header_checksum, |
312 | 383 | stored_header_crc ); |
313 | | |
314 | 383 | byte_stream_copy_to_uint64_little_endian( |
315 | 383 | ( (wtcdb_cache_entry_v20_t *) data )->data_checksum, |
316 | 383 | cache_entry->data_crc ); |
317 | 383 | } |
318 | 3.04k | else if( io_handle->format_version == 21 ) |
319 | 1.64k | { |
320 | 1.64k | byte_stream_copy_to_uint32_little_endian( |
321 | 1.64k | ( (wtcdb_cache_entry_v21_t *) data )->identifier_string_size, |
322 | 1.64k | cache_entry->identifier_size ); |
323 | | |
324 | 1.64k | byte_stream_copy_to_uint32_little_endian( |
325 | 1.64k | ( (wtcdb_cache_entry_v21_t *) data )->padding_size, |
326 | 1.64k | cache_entry->padding_size ); |
327 | | |
328 | 1.64k | byte_stream_copy_to_uint32_little_endian( |
329 | 1.64k | ( (wtcdb_cache_entry_v21_t *) data )->data_size, |
330 | 1.64k | cache_entry->cached_data_size ); |
331 | | |
332 | 1.64k | byte_stream_copy_to_uint64_little_endian( |
333 | 1.64k | ( (wtcdb_cache_entry_v21_t *) data )->data_checksum, |
334 | 1.64k | cache_entry->data_crc ); |
335 | | |
336 | 1.64k | byte_stream_copy_to_uint64_little_endian( |
337 | 1.64k | ( (wtcdb_cache_entry_v21_t *) data )->header_checksum, |
338 | 1.64k | stored_header_crc ); |
339 | 1.64k | } |
340 | 1.40k | else if( ( io_handle->format_version == 30 ) |
341 | 902 | || ( io_handle->format_version == 31 ) |
342 | 386 | || ( io_handle->format_version == 32 ) ) |
343 | 1.40k | { |
344 | 1.40k | byte_stream_copy_to_uint32_little_endian( |
345 | 1.40k | ( (wtcdb_cache_entry_v30_t *) data )->identifier_string_size, |
346 | 1.40k | cache_entry->identifier_size ); |
347 | | |
348 | 1.40k | byte_stream_copy_to_uint32_little_endian( |
349 | 1.40k | ( (wtcdb_cache_entry_v30_t *) data )->padding_size, |
350 | 1.40k | cache_entry->padding_size ); |
351 | | |
352 | 1.40k | byte_stream_copy_to_uint32_little_endian( |
353 | 1.40k | ( (wtcdb_cache_entry_v30_t *) data )->data_size, |
354 | 1.40k | cache_entry->cached_data_size ); |
355 | | |
356 | 1.40k | byte_stream_copy_to_uint64_little_endian( |
357 | 1.40k | ( (wtcdb_cache_entry_v30_t *) data )->data_checksum, |
358 | 1.40k | cache_entry->data_crc ); |
359 | | |
360 | 1.40k | byte_stream_copy_to_uint64_little_endian( |
361 | 1.40k | ( (wtcdb_cache_entry_v30_t *) data )->header_checksum, |
362 | 1.40k | stored_header_crc ); |
363 | 1.40k | } |
364 | | #if defined( HAVE_DEBUG_OUTPUT ) |
365 | | if( libcnotify_verbose != 0 ) |
366 | | { |
367 | | libcnotify_printf( |
368 | | "%s: signature\t\t\t: %c%c%c%c\n", |
369 | | function, |
370 | | ( (wtcdb_cache_entry_v20_t *) data )->signature[ 0 ], |
371 | | ( (wtcdb_cache_entry_v20_t *) data )->signature[ 1 ], |
372 | | ( (wtcdb_cache_entry_v20_t *) data )->signature[ 2 ], |
373 | | ( (wtcdb_cache_entry_v20_t *) data )->signature[ 3 ] ); |
374 | | |
375 | | libcnotify_printf( |
376 | | "%s: size\t\t\t\t: %" PRIu32 "\n", |
377 | | function, |
378 | | cache_entry->data_size ); |
379 | | |
380 | | libcnotify_printf( |
381 | | "%s: entry hash\t\t\t: 0x%08" PRIx64 "\n", |
382 | | function, |
383 | | cache_entry->hash ); |
384 | | |
385 | | if( io_handle->format_version == 20 ) |
386 | | { |
387 | | /* TODO make a string of this ?*/ |
388 | | libcnotify_printf( |
389 | | "%s: file extension\t\t\t: ", |
390 | | function ); |
391 | | |
392 | | if( ( (wtcdb_cache_entry_v20_t *) data )->file_extension[ 0 ] == 0 ) |
393 | | { |
394 | | libcnotify_printf( |
395 | | "(none)" ); |
396 | | } |
397 | | else |
398 | | { |
399 | | libcnotify_printf( |
400 | | "%c", |
401 | | ( (wtcdb_cache_entry_v20_t *) data )->file_extension[ 0 ] ); |
402 | | } |
403 | | if( ( (wtcdb_cache_entry_v20_t *) data )->file_extension[ 2 ] != 0 ) |
404 | | { |
405 | | libcnotify_printf( |
406 | | "%c", |
407 | | ( (wtcdb_cache_entry_v20_t *) data )->file_extension[ 2 ] ); |
408 | | } |
409 | | if( ( (wtcdb_cache_entry_v20_t *) data )->file_extension[ 4 ] != 0 ) |
410 | | { |
411 | | libcnotify_printf( |
412 | | "%c", |
413 | | ( (wtcdb_cache_entry_v20_t *) data )->file_extension[ 4 ] ); |
414 | | } |
415 | | if( ( (wtcdb_cache_entry_v20_t *) data )->file_extension[ 6 ] != 0 ) |
416 | | { |
417 | | libcnotify_printf( |
418 | | "%c", |
419 | | ( (wtcdb_cache_entry_v20_t *) data )->file_extension[ 6 ] ); |
420 | | } |
421 | | libcnotify_printf( |
422 | | "\n" ); |
423 | | } |
424 | | libcnotify_printf( |
425 | | "%s: identifier string size\t\t: %" PRIu32 "\n", |
426 | | function, |
427 | | cache_entry->identifier_size ); |
428 | | |
429 | | libcnotify_printf( |
430 | | "%s: padding size\t\t\t: %" PRIu32 "\n", |
431 | | function, |
432 | | cache_entry->padding_size ); |
433 | | |
434 | | libcnotify_printf( |
435 | | "%s: data size\t\t\t: %" PRIu32 "\n", |
436 | | function, |
437 | | cache_entry->cached_data_size ); |
438 | | |
439 | | if( io_handle->format_version == 20 ) |
440 | | { |
441 | | byte_stream_copy_to_uint32_little_endian( |
442 | | ( (wtcdb_cache_entry_v20_t *) data )->unknown1, |
443 | | value_32bit ); |
444 | | } |
445 | | else if( ( io_handle->format_version == 21 ) |
446 | | || ( io_handle->format_version == 30 ) |
447 | | || ( io_handle->format_version == 31 ) |
448 | | || ( io_handle->format_version == 32 ) ) |
449 | | { |
450 | | byte_stream_copy_to_uint32_little_endian( |
451 | | ( (wtcdb_cache_entry_v21_t *) data )->unknown1, |
452 | | value_32bit ); |
453 | | } |
454 | | libcnotify_printf( |
455 | | "%s: unknown1\t\t\t\t: 0x%08" PRIx32 "\n", |
456 | | function, |
457 | | value_32bit ); |
458 | | |
459 | | if( ( io_handle->format_version == 30 ) |
460 | | || ( io_handle->format_version == 31 ) |
461 | | || ( io_handle->format_version == 32 ) ) |
462 | | { |
463 | | byte_stream_copy_to_uint64_little_endian( |
464 | | ( (wtcdb_cache_entry_v30_t *) data )->unknown2, |
465 | | value_64bit ); |
466 | | libcnotify_printf( |
467 | | "%s: unknown2\t\t\t\t: 0x%08" PRIx64 "\n", |
468 | | function, |
469 | | value_64bit ); |
470 | | } |
471 | | libcnotify_printf( |
472 | | "%s: data checksum\t\t\t: 0x%08" PRIx64 "\n", |
473 | | function, |
474 | | cache_entry->data_crc ); |
475 | | |
476 | | libcnotify_printf( |
477 | | "%s: header checksum\t\t\t: 0x%08" PRIx64 "\n", |
478 | | function, |
479 | | stored_header_crc ); |
480 | | |
481 | | libcnotify_printf( |
482 | | "\n" ); |
483 | | } |
484 | | #endif /* defined( HAVE_DEBUG_OUTPUT ) */ |
485 | | |
486 | | #if ( SIZEOF_SIZE_T <= 4 ) |
487 | | if( ( cache_entry->data_size < cache_entry_header_size ) |
488 | | || ( cache_entry->data_size > (uint32_t) SSIZE_MAX ) ) |
489 | | #else |
490 | 3.42k | if( cache_entry->data_size < cache_entry_header_size ) |
491 | 12 | #endif |
492 | 12 | { |
493 | 12 | libcerror_error_set( |
494 | 12 | error, |
495 | 12 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
496 | 12 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
497 | 12 | "%s: invalid cache entry - data value out of bounds.", |
498 | 12 | function ); |
499 | | |
500 | 12 | return( -1 ); |
501 | 12 | } |
502 | 3.41k | if( libwtcdb_crc64_weak_calculate( |
503 | 3.41k | &calculated_crc, |
504 | 3.41k | data, |
505 | 3.41k | cache_entry_header_size - 8, |
506 | 3.41k | (uint64_t) -1, |
507 | 3.41k | error ) != 1 ) |
508 | 0 | { |
509 | 0 | libcerror_error_set( |
510 | 0 | error, |
511 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
512 | 0 | LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, |
513 | 0 | "%s: unable to calculate CRC-64.", |
514 | 0 | function ); |
515 | |
|
516 | 0 | return( -1 ); |
517 | 0 | } |
518 | 3.41k | if( stored_header_crc != calculated_crc ) |
519 | 3.41k | { |
520 | | #if defined( HAVE_DEBUG_OUTPUT ) |
521 | | if( libcnotify_verbose != 0 ) |
522 | | { |
523 | | libcnotify_printf( |
524 | | "%s: mismatch in header CRC-64 ( 0x%08" PRIx64 " != 0x%08" PRIx64 " ).\n", |
525 | | function, |
526 | | stored_header_crc, |
527 | | calculated_crc ); |
528 | | } |
529 | | #endif |
530 | 3.41k | } |
531 | 3.41k | return( 1 ); |
532 | 3.41k | } |
533 | | |
534 | | /* Reads a cache entry |
535 | | * Returns 1 if successful or -1 on error |
536 | | */ |
537 | | int libwtcdb_cache_entry_read_file_io_handle( |
538 | | libwtcdb_cache_entry_t *cache_entry, |
539 | | libwtcdb_io_handle_t *io_handle, |
540 | | libbfio_handle_t *file_io_handle, |
541 | | off64_t file_offset, |
542 | | libcerror_error_t **error ) |
543 | 3.50k | { |
544 | 3.50k | uint8_t cache_entry_data[ sizeof( wtcdb_cache_entry_v20_t ) ]; |
545 | | |
546 | 3.50k | static char *function = "libwtcdb_cache_entry_read_file_io_handle"; |
547 | 3.50k | uint32_t cache_entry_header_size = 0; |
548 | 3.50k | size_t data_offset = 0; |
549 | 3.50k | ssize_t read_count = 0; |
550 | | |
551 | | #if defined( HAVE_DEBUG_OUTPUT ) |
552 | | uint8_t *padding_data = NULL; |
553 | | #endif |
554 | | |
555 | 3.50k | if( cache_entry == NULL ) |
556 | 0 | { |
557 | 0 | libcerror_error_set( |
558 | 0 | error, |
559 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
560 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
561 | 0 | "%s: invalid cache entry.", |
562 | 0 | function ); |
563 | |
|
564 | 0 | return( -1 ); |
565 | 0 | } |
566 | 3.50k | if( io_handle == NULL ) |
567 | 0 | { |
568 | 0 | libcerror_error_set( |
569 | 0 | error, |
570 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
571 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
572 | 0 | "%s: invalid IO handle.", |
573 | 0 | function ); |
574 | |
|
575 | 0 | return( -1 ); |
576 | 0 | } |
577 | 3.50k | if( io_handle->file_type != LIBWTCDB_FILE_TYPE_CACHE ) |
578 | 0 | { |
579 | 0 | libcerror_error_set( |
580 | 0 | error, |
581 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
582 | 0 | LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, |
583 | 0 | "%s: invalid IO handle - unsupported file type.", |
584 | 0 | function ); |
585 | |
|
586 | 0 | return( -1 ); |
587 | 0 | } |
588 | 3.50k | if( ( io_handle->format_version != 20 ) |
589 | 3.10k | && ( io_handle->format_version != 21 ) |
590 | 1.43k | && ( io_handle->format_version != 30 ) |
591 | 924 | && ( io_handle->format_version != 31 ) |
592 | 397 | && ( io_handle->format_version != 32 ) ) |
593 | 0 | { |
594 | 0 | libcerror_error_set( |
595 | 0 | error, |
596 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
597 | 0 | LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, |
598 | 0 | "%s: invalid IO handle - unsupported format version: %" PRIu32 ".", |
599 | 0 | function, |
600 | 0 | io_handle->format_version ); |
601 | |
|
602 | 0 | return( -1 ); |
603 | 0 | } |
604 | 3.50k | if( io_handle->format_version == 20 ) |
605 | 394 | { |
606 | 394 | cache_entry_header_size = sizeof( wtcdb_cache_entry_v20_t ); |
607 | 394 | } |
608 | 3.10k | else if( io_handle->format_version == 21 ) |
609 | 1.67k | { |
610 | 1.67k | cache_entry_header_size = sizeof( wtcdb_cache_entry_v21_t ); |
611 | 1.67k | } |
612 | 1.43k | else if( ( io_handle->format_version == 30 ) |
613 | 924 | || ( io_handle->format_version == 31 ) |
614 | 397 | || ( io_handle->format_version == 32 ) ) |
615 | 1.43k | { |
616 | 1.43k | cache_entry_header_size = sizeof( wtcdb_cache_entry_v30_t ); |
617 | 1.43k | } |
618 | 3.50k | if( cache_entry->identifier != NULL ) |
619 | 0 | { |
620 | 0 | memory_free( |
621 | 0 | cache_entry->identifier ); |
622 | |
|
623 | 0 | cache_entry->identifier = NULL; |
624 | 0 | } |
625 | | #if defined( HAVE_DEBUG_OUTPUT ) |
626 | | if( libcnotify_verbose != 0 ) |
627 | | { |
628 | | libcnotify_printf( |
629 | | "%s: reading cache entry header at offset: %" PRIi64 " (0x%08" PRIx64 ")\n", |
630 | | function, |
631 | | file_offset, |
632 | | file_offset ); |
633 | | } |
634 | | #endif |
635 | 3.50k | read_count = libbfio_handle_read_buffer_at_offset( |
636 | 3.50k | file_io_handle, |
637 | 3.50k | cache_entry_data, |
638 | 3.50k | cache_entry_header_size, |
639 | 3.50k | file_offset, |
640 | 3.50k | error ); |
641 | | |
642 | 3.50k | if( read_count != (ssize_t) cache_entry_header_size ) |
643 | 67 | { |
644 | 67 | libcerror_error_set( |
645 | 67 | error, |
646 | 67 | LIBCERROR_ERROR_DOMAIN_IO, |
647 | 67 | LIBCERROR_IO_ERROR_READ_FAILED, |
648 | 67 | "%s: unable to read cache entry header data at offset: %" PRIi64 " (0x%08" PRIx64 ").", |
649 | 67 | function, |
650 | 67 | file_offset, |
651 | 67 | file_offset ); |
652 | | |
653 | 67 | goto on_error; |
654 | 67 | } |
655 | 3.43k | if( libwtcdb_cache_entry_header_read_data( |
656 | 3.43k | cache_entry, |
657 | 3.43k | io_handle, |
658 | 3.43k | cache_entry_data, |
659 | 3.43k | cache_entry_header_size, |
660 | 3.43k | error ) != 1 ) |
661 | 16 | { |
662 | 16 | libcerror_error_set( |
663 | 16 | error, |
664 | 16 | LIBCERROR_ERROR_DOMAIN_IO, |
665 | 16 | LIBCERROR_IO_ERROR_READ_FAILED, |
666 | 16 | "%s: unable to read cache entry header.", |
667 | 16 | function ); |
668 | | |
669 | 16 | goto on_error; |
670 | 16 | } |
671 | 3.41k | data_offset = cache_entry_header_size; |
672 | | |
673 | 3.41k | if( cache_entry->identifier_size > 0 ) |
674 | 763 | { |
675 | 763 | if( cache_entry->identifier_size > MEMORY_MAXIMUM_ALLOCATION_SIZE ) |
676 | 41 | { |
677 | 41 | libcerror_error_set( |
678 | 41 | error, |
679 | 41 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
680 | 41 | LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, |
681 | 41 | "%s: invalid cache entry - identifier size value exceeds maximum allocation size.", |
682 | 41 | function ); |
683 | | |
684 | 41 | goto on_error; |
685 | 41 | } |
686 | 722 | if( ( cache_entry->identifier_size > cache_entry->data_size ) |
687 | 699 | || ( data_offset > ( cache_entry->data_size - cache_entry->identifier_size ) ) ) |
688 | 31 | { |
689 | 31 | libcerror_error_set( |
690 | 31 | error, |
691 | 31 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
692 | 31 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
693 | 31 | "%s: invalid identifier size value out of bounds.", |
694 | 31 | function ); |
695 | | |
696 | 31 | goto on_error; |
697 | 31 | } |
698 | 691 | cache_entry->identifier = (uint8_t *) memory_allocate( |
699 | 691 | sizeof( uint8_t ) * cache_entry->identifier_size ); |
700 | | |
701 | 691 | if( cache_entry->identifier == NULL ) |
702 | 0 | { |
703 | 0 | libcerror_error_set( |
704 | 0 | error, |
705 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
706 | 0 | LIBCERROR_MEMORY_ERROR_INSUFFICIENT, |
707 | 0 | "%s: unable to create identifier string.", |
708 | 0 | function ); |
709 | |
|
710 | 0 | goto on_error; |
711 | 0 | } |
712 | 691 | read_count = libbfio_handle_read_buffer( |
713 | 691 | file_io_handle, |
714 | 691 | cache_entry->identifier, |
715 | 691 | cache_entry->identifier_size, |
716 | 691 | error ); |
717 | | |
718 | 691 | if( read_count != (ssize_t) cache_entry->identifier_size ) |
719 | 93 | { |
720 | 93 | libcerror_error_set( |
721 | 93 | error, |
722 | 93 | LIBCERROR_ERROR_DOMAIN_IO, |
723 | 93 | LIBCERROR_IO_ERROR_READ_FAILED, |
724 | 93 | "%s: unable to read cache entry identifier string.", |
725 | 93 | function ); |
726 | | |
727 | 93 | goto on_error; |
728 | 93 | } |
729 | | #if defined( HAVE_DEBUG_OUTPUT ) |
730 | | if( libcnotify_verbose != 0 ) |
731 | | { |
732 | | libcnotify_printf( |
733 | | "%s: identifier string data:\n", |
734 | | function ); |
735 | | libcnotify_print_data( |
736 | | cache_entry->identifier, |
737 | | cache_entry->identifier_size, |
738 | | LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); |
739 | | } |
740 | | #endif |
741 | | #if defined( HAVE_DEBUG_OUTPUT ) |
742 | | if( libcnotify_verbose != 0 ) |
743 | | { |
744 | | if( libwtcdb_debug_print_utf16_string_value( |
745 | | function, |
746 | | "identifier string\t\t", |
747 | | cache_entry->identifier, |
748 | | cache_entry->identifier_size, |
749 | | LIBUNA_ENDIAN_LITTLE, |
750 | | error ) != 1 ) |
751 | | { |
752 | | libcerror_error_set( |
753 | | error, |
754 | | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
755 | | LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, |
756 | | "%s: unable to print UTF-16 string value.", |
757 | | function ); |
758 | | |
759 | | goto on_error; |
760 | | } |
761 | | } |
762 | | #endif /* defined( HAVE_DEBUG_OUTPUT ) */ |
763 | | |
764 | 598 | data_offset += cache_entry->identifier_size; |
765 | 598 | } |
766 | 3.25k | if( cache_entry->padding_size > 0 ) |
767 | 471 | { |
768 | 471 | if( cache_entry->padding_size > MEMORY_MAXIMUM_ALLOCATION_SIZE ) |
769 | 38 | { |
770 | 38 | libcerror_error_set( |
771 | 38 | error, |
772 | 38 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
773 | 38 | LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, |
774 | 38 | "%s: invalid cache entry - padding size value exceeds maximum allocation size.", |
775 | 38 | function ); |
776 | | |
777 | 38 | goto on_error; |
778 | 38 | } |
779 | 433 | if( ( cache_entry->padding_size > cache_entry->data_size ) |
780 | 422 | || ( data_offset > ( cache_entry->data_size - cache_entry->padding_size ) ) ) |
781 | 13 | { |
782 | 13 | libcerror_error_set( |
783 | 13 | error, |
784 | 13 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
785 | 13 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
786 | 13 | "%s: invalid padding size value out of bounds.", |
787 | 13 | function ); |
788 | | |
789 | 13 | goto on_error; |
790 | 13 | } |
791 | | #if defined( HAVE_DEBUG_OUTPUT ) |
792 | | if( libcnotify_verbose != 0 ) |
793 | | { |
794 | | padding_data = (uint8_t *) memory_allocate( |
795 | | sizeof( uint8_t ) * cache_entry->padding_size ); |
796 | | |
797 | | if( padding_data == NULL ) |
798 | | { |
799 | | libcerror_error_set( |
800 | | error, |
801 | | LIBCERROR_ERROR_DOMAIN_MEMORY, |
802 | | LIBCERROR_MEMORY_ERROR_INSUFFICIENT, |
803 | | "%s: unable to create padding data.", |
804 | | function ); |
805 | | |
806 | | goto on_error; |
807 | | } |
808 | | read_count = libbfio_handle_read_buffer( |
809 | | file_io_handle, |
810 | | padding_data, |
811 | | cache_entry->padding_size, |
812 | | error ); |
813 | | |
814 | | if( read_count != (ssize_t) cache_entry->padding_size ) |
815 | | { |
816 | | libcerror_error_set( |
817 | | error, |
818 | | LIBCERROR_ERROR_DOMAIN_IO, |
819 | | LIBCERROR_IO_ERROR_READ_FAILED, |
820 | | "%s: unable to read cache entry padding data.", |
821 | | function ); |
822 | | |
823 | | goto on_error; |
824 | | } |
825 | | libcnotify_printf( |
826 | | "%s: padding data:\n", |
827 | | function ); |
828 | | libcnotify_print_data( |
829 | | padding_data, |
830 | | cache_entry->padding_size, |
831 | | LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); |
832 | | } |
833 | | data_offset += cache_entry->padding_size; |
834 | | |
835 | | #endif /* defined( HAVE_DEBUG_OUTPUT ) */ |
836 | 433 | } |
837 | | #if defined( HAVE_DEBUG_OUTPUT ) |
838 | | else if( libcnotify_verbose != 0 ) |
839 | | { |
840 | | libcnotify_printf( |
841 | | "\n" ); |
842 | | } |
843 | | #endif |
844 | 3.20k | return( 1 ); |
845 | | |
846 | 299 | on_error: |
847 | 299 | if( cache_entry->identifier != NULL ) |
848 | 94 | { |
849 | 94 | memory_free( |
850 | 94 | cache_entry->identifier ); |
851 | | |
852 | | cache_entry->identifier = NULL; |
853 | 94 | } |
854 | 299 | return( -1 ); |
855 | 3.25k | } |
856 | | |