/src/libvshadow/libvshadow/libvshadow_io_handle.c
Line | Count | Source |
1 | | /* |
2 | | * Input/Output (IO) handle functions |
3 | | * |
4 | | * Copyright (C) 2011-2024, 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 <byte_stream.h> |
24 | | #include <memory.h> |
25 | | #include <types.h> |
26 | | |
27 | | #include "libvshadow_block_descriptor.h" |
28 | | #include "libvshadow_block_tree.h" |
29 | | #include "libvshadow_block_tree_node.h" |
30 | | #include "libvshadow_debug.h" |
31 | | #include "libvshadow_definitions.h" |
32 | | #include "libvshadow_io_handle.h" |
33 | | #include "libvshadow_libbfio.h" |
34 | | #include "libvshadow_libcdata.h" |
35 | | #include "libvshadow_libcerror.h" |
36 | | #include "libvshadow_libcnotify.h" |
37 | | #include "libvshadow_libfdatetime.h" |
38 | | #include "libvshadow_libfguid.h" |
39 | | #include "libvshadow_store_descriptor.h" |
40 | | |
41 | | #include "vshadow_catalog.h" |
42 | | #include "vshadow_volume.h" |
43 | | |
44 | | const uint8_t vshadow_vss_identifier[ 16 ] = { |
45 | | 0x6b, 0x87, 0x08, 0x38, 0x76, 0xc1, 0x48, 0x4e, 0xb7, 0xae, 0x04, 0x04, 0x6e, 0x6c, 0xc7, 0x52 }; |
46 | | |
47 | | /* Creates an IO handle |
48 | | * Make sure the value io_handle is referencing, is set to NULL |
49 | | * Returns 1 if successful or -1 on error |
50 | | */ |
51 | | int libvshadow_io_handle_initialize( |
52 | | libvshadow_io_handle_t **io_handle, |
53 | | libcerror_error_t **error ) |
54 | 1.61k | { |
55 | 1.61k | static char *function = "libvshadow_io_handle_initialize"; |
56 | | |
57 | 1.61k | if( io_handle == NULL ) |
58 | 0 | { |
59 | 0 | libcerror_error_set( |
60 | 0 | error, |
61 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
62 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
63 | 0 | "%s: invalid IO handle.", |
64 | 0 | function ); |
65 | |
|
66 | 0 | return( -1 ); |
67 | 0 | } |
68 | 1.61k | if( *io_handle != NULL ) |
69 | 0 | { |
70 | 0 | libcerror_error_set( |
71 | 0 | error, |
72 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
73 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, |
74 | 0 | "%s: invalid IO handle value already set.", |
75 | 0 | function ); |
76 | |
|
77 | 0 | return( -1 ); |
78 | 0 | } |
79 | 1.61k | *io_handle = memory_allocate_structure( |
80 | 1.61k | libvshadow_io_handle_t ); |
81 | | |
82 | 1.61k | if( *io_handle == NULL ) |
83 | 0 | { |
84 | 0 | libcerror_error_set( |
85 | 0 | error, |
86 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
87 | 0 | LIBCERROR_MEMORY_ERROR_INSUFFICIENT, |
88 | 0 | "%s: unable to create IO handle.", |
89 | 0 | function ); |
90 | |
|
91 | 0 | goto on_error; |
92 | 0 | } |
93 | 1.61k | if( memory_set( |
94 | 1.61k | *io_handle, |
95 | 1.61k | 0, |
96 | 1.61k | sizeof( libvshadow_io_handle_t ) ) == NULL ) |
97 | 0 | { |
98 | 0 | libcerror_error_set( |
99 | 0 | error, |
100 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
101 | 0 | LIBCERROR_MEMORY_ERROR_SET_FAILED, |
102 | 0 | "%s: unable to clear IO handle.", |
103 | 0 | function ); |
104 | |
|
105 | 0 | goto on_error; |
106 | 0 | } |
107 | 1.61k | ( *io_handle )->block_size = 0x4000; |
108 | | |
109 | 1.61k | return( 1 ); |
110 | | |
111 | 0 | on_error: |
112 | 0 | if( *io_handle != NULL ) |
113 | 0 | { |
114 | 0 | memory_free( |
115 | 0 | *io_handle ); |
116 | |
|
117 | 0 | *io_handle = NULL; |
118 | 0 | } |
119 | 0 | return( -1 ); |
120 | 1.61k | } |
121 | | |
122 | | /* Frees an IO handle |
123 | | * Returns 1 if successful or -1 on error |
124 | | */ |
125 | | int libvshadow_io_handle_free( |
126 | | libvshadow_io_handle_t **io_handle, |
127 | | libcerror_error_t **error ) |
128 | 1.61k | { |
129 | 1.61k | static char *function = "libvshadow_io_handle_free"; |
130 | | |
131 | 1.61k | if( io_handle == NULL ) |
132 | 0 | { |
133 | 0 | libcerror_error_set( |
134 | 0 | error, |
135 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
136 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
137 | 0 | "%s: invalid IO handle.", |
138 | 0 | function ); |
139 | |
|
140 | 0 | return( -1 ); |
141 | 0 | } |
142 | 1.61k | if( *io_handle != NULL ) |
143 | 1.61k | { |
144 | 1.61k | memory_free( |
145 | 1.61k | *io_handle ); |
146 | | |
147 | 1.61k | *io_handle = NULL; |
148 | 1.61k | } |
149 | 1.61k | return( 1 ); |
150 | 1.61k | } |
151 | | |
152 | | /* Clears the IO handle |
153 | | * Returns 1 if successful or -1 on error |
154 | | */ |
155 | | int libvshadow_io_handle_clear( |
156 | | libvshadow_io_handle_t *io_handle, |
157 | | libcerror_error_t **error ) |
158 | 60 | { |
159 | 60 | static char *function = "libvshadow_io_handle_clear"; |
160 | | |
161 | 60 | if( io_handle == NULL ) |
162 | 0 | { |
163 | 0 | libcerror_error_set( |
164 | 0 | error, |
165 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
166 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
167 | 0 | "%s: invalid IO handle.", |
168 | 0 | function ); |
169 | |
|
170 | 0 | return( -1 ); |
171 | 0 | } |
172 | 60 | if( memory_set( |
173 | 60 | io_handle, |
174 | 60 | 0, |
175 | 60 | sizeof( libvshadow_io_handle_t ) ) == NULL ) |
176 | 0 | { |
177 | 0 | libcerror_error_set( |
178 | 0 | error, |
179 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
180 | 0 | LIBCERROR_MEMORY_ERROR_SET_FAILED, |
181 | 0 | "%s: unable to clear IO handle.", |
182 | 0 | function ); |
183 | |
|
184 | 0 | return( -1 ); |
185 | 0 | } |
186 | 60 | io_handle->block_size = 0x4000; |
187 | | |
188 | 60 | return( 1 ); |
189 | 60 | } |
190 | | |
191 | | /* Checks if this is the first time the block is being read |
192 | | * Returns 1 if successful or -1 on error |
193 | | */ |
194 | | int libvshadow_io_handle_check_if_block_first_read( |
195 | | libvshadow_io_handle_t *io_handle, |
196 | | libvshadow_block_tree_t *block_tree, |
197 | | off64_t block_offset, |
198 | | libcerror_error_t **error ) |
199 | 866 | { |
200 | 866 | libvshadow_block_descriptor_t *existing_block_descriptor = NULL; |
201 | 866 | libvshadow_block_descriptor_t *new_block_descriptor = NULL; |
202 | 866 | libvshadow_block_tree_node_t *leaf_block_tree_node = NULL; |
203 | 866 | static char *function = "libvshadow_io_handle_check_if_block_first_read"; |
204 | 866 | int leaf_value_index = 0; |
205 | 866 | int result = 0; |
206 | | |
207 | 866 | if( io_handle == NULL ) |
208 | 0 | { |
209 | 0 | libcerror_error_set( |
210 | 0 | error, |
211 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
212 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
213 | 0 | "%s: invalid IO handle.", |
214 | 0 | function ); |
215 | |
|
216 | 0 | return( -1 ); |
217 | 0 | } |
218 | 866 | if( libvshadow_block_descriptor_initialize( |
219 | 866 | &new_block_descriptor, |
220 | 866 | error ) != 1 ) |
221 | 0 | { |
222 | 0 | libcerror_error_set( |
223 | 0 | error, |
224 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
225 | 0 | LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, |
226 | 0 | "%s: unable to create block descriptor.", |
227 | 0 | function ); |
228 | |
|
229 | 0 | goto on_error; |
230 | 0 | } |
231 | 866 | new_block_descriptor->offset = block_offset; |
232 | | |
233 | 866 | result = libvshadow_block_tree_insert_block_descriptor_by_offset( |
234 | 866 | block_tree, |
235 | 866 | block_offset, |
236 | 866 | new_block_descriptor, |
237 | 866 | &leaf_value_index, |
238 | 866 | &leaf_block_tree_node, |
239 | 866 | &existing_block_descriptor, |
240 | 866 | error ); |
241 | | |
242 | 866 | if( result == -1 ) |
243 | 114 | { |
244 | 114 | libcerror_error_set( |
245 | 114 | error, |
246 | 114 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
247 | 114 | LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, |
248 | 114 | "%s: unable to insert block descriptor in block tree.", |
249 | 114 | function ); |
250 | | |
251 | 114 | goto on_error; |
252 | 114 | } |
253 | 752 | else if( result == 0 ) |
254 | 2 | { |
255 | 2 | libcerror_error_set( |
256 | 2 | error, |
257 | 2 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
258 | 2 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
259 | 2 | "%s: invalid block offset: %" PRIi64 " (0x%08" PRIx64 ") value already exists.", |
260 | 2 | function, |
261 | 2 | block_offset, |
262 | 2 | block_offset ); |
263 | | |
264 | 2 | goto on_error; |
265 | 2 | } |
266 | 750 | new_block_descriptor = NULL; |
267 | | |
268 | 750 | return( 1 ); |
269 | | |
270 | 116 | on_error: |
271 | 116 | if( new_block_descriptor != NULL ) |
272 | 116 | { |
273 | 116 | libvshadow_block_descriptor_free( |
274 | 116 | &new_block_descriptor, |
275 | 116 | NULL ); |
276 | 116 | } |
277 | 116 | return( -1 ); |
278 | 866 | } |
279 | | |
280 | | /* Reads the volume header |
281 | | * Returns 1 if successful or -1 on error |
282 | | */ |
283 | | int libvshadow_io_handle_read_volume_header( |
284 | | libvshadow_io_handle_t *io_handle, |
285 | | libbfio_handle_t *file_io_handle, |
286 | | off64_t file_offset, |
287 | | off64_t *catalog_offset, |
288 | | libcerror_error_t **error ) |
289 | 1.01k | { |
290 | 1.01k | vshadow_volume_header_t volume_header; |
291 | | |
292 | 1.01k | static char *function = "libvshadow_io_handle_read_volume_header"; |
293 | 1.01k | ssize_t read_count = 0; |
294 | | |
295 | 1.01k | if( io_handle == NULL ) |
296 | 0 | { |
297 | 0 | libcerror_error_set( |
298 | 0 | error, |
299 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
300 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
301 | 0 | "%s: invalid IO handle.", |
302 | 0 | function ); |
303 | |
|
304 | 0 | return( -1 ); |
305 | 0 | } |
306 | | #if defined( HAVE_DEBUG_OUTPUT ) |
307 | | if( libcnotify_verbose != 0 ) |
308 | | { |
309 | | libcnotify_printf( |
310 | | "%s: reading volume header at offset: %" PRIi64 " (0x%08" PRIx64 ")\n", |
311 | | function, |
312 | | file_offset, |
313 | | file_offset ); |
314 | | } |
315 | | #endif |
316 | 1.01k | read_count = libbfio_handle_read_buffer_at_offset( |
317 | 1.01k | file_io_handle, |
318 | 1.01k | (uint8_t *) &volume_header, |
319 | 1.01k | sizeof( vshadow_volume_header_t ), |
320 | 1.01k | file_offset, |
321 | 1.01k | error ); |
322 | | |
323 | 1.01k | if( read_count != (ssize_t) sizeof( vshadow_volume_header_t ) ) |
324 | 34 | { |
325 | 34 | libcerror_error_set( |
326 | 34 | error, |
327 | 34 | LIBCERROR_ERROR_DOMAIN_IO, |
328 | 34 | LIBCERROR_IO_ERROR_READ_FAILED, |
329 | 34 | "%s: unable to read volume header data at offset: %" PRIi64 " (0x%08" PRIx64 ").", |
330 | 34 | function, |
331 | 34 | file_offset, |
332 | 34 | file_offset ); |
333 | | |
334 | 34 | return( -1 ); |
335 | 34 | } |
336 | 985 | if( libvshadow_io_handle_read_volume_header_data( |
337 | 985 | io_handle, |
338 | 985 | (uint8_t *) &volume_header, |
339 | 985 | sizeof( vshadow_volume_header_t ), |
340 | 985 | catalog_offset, |
341 | 985 | error ) != 1 ) |
342 | 80 | { |
343 | 80 | libcerror_error_set( |
344 | 80 | error, |
345 | 80 | LIBCERROR_ERROR_DOMAIN_IO, |
346 | 80 | LIBCERROR_IO_ERROR_READ_FAILED, |
347 | 80 | "%s: unable to read volume header.", |
348 | 80 | function ); |
349 | | |
350 | 80 | return( -1 ); |
351 | 80 | } |
352 | 905 | return( 1 ); |
353 | 985 | } |
354 | | |
355 | | /* Reads the volume header |
356 | | * Returns 1 if successful or -1 on error |
357 | | */ |
358 | | int libvshadow_io_handle_read_volume_header_data( |
359 | | libvshadow_io_handle_t *io_handle, |
360 | | const uint8_t *data, |
361 | | size_t data_size, |
362 | | off64_t *catalog_offset, |
363 | | libcerror_error_t **error ) |
364 | 985 | { |
365 | 985 | static char *function = "libvshadow_io_handle_read_volume_header_data"; |
366 | 985 | uint64_t safe_catalog_offset = 0; |
367 | 985 | uint32_t record_type = 0; |
368 | 985 | uint32_t version = 0; |
369 | | |
370 | | #if defined( HAVE_DEBUG_OUTPUT ) |
371 | | uint64_t value_64bit = 0; |
372 | | uint32_t value_32bit = 0; |
373 | | #endif |
374 | | |
375 | 985 | if( io_handle == NULL ) |
376 | 0 | { |
377 | 0 | libcerror_error_set( |
378 | 0 | error, |
379 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
380 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
381 | 0 | "%s: invalid IO handle.", |
382 | 0 | function ); |
383 | |
|
384 | 0 | return( -1 ); |
385 | 0 | } |
386 | 985 | if( data == NULL ) |
387 | 0 | { |
388 | 0 | libcerror_error_set( |
389 | 0 | error, |
390 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
391 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
392 | 0 | "%s: invalid data.", |
393 | 0 | function ); |
394 | |
|
395 | 0 | return( -1 ); |
396 | 0 | } |
397 | 985 | if( ( data_size < sizeof( vshadow_volume_header_t ) ) |
398 | 985 | || ( data_size > (size_t) SSIZE_MAX ) ) |
399 | 0 | { |
400 | 0 | libcerror_error_set( |
401 | 0 | error, |
402 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
403 | 0 | LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, |
404 | 0 | "%s: invalid data size value out of bounds.", |
405 | 0 | function ); |
406 | |
|
407 | 0 | return( -1 ); |
408 | 0 | } |
409 | 985 | if( catalog_offset == NULL ) |
410 | 0 | { |
411 | 0 | libcerror_error_set( |
412 | 0 | error, |
413 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
414 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
415 | 0 | "%s: invalid catalog offset.", |
416 | 0 | function ); |
417 | |
|
418 | 0 | return( -1 ); |
419 | 0 | } |
420 | | #if defined( HAVE_DEBUG_OUTPUT ) |
421 | | if( libcnotify_verbose != 0 ) |
422 | | { |
423 | | libcnotify_printf( |
424 | | "%s: volume header data:\n", |
425 | | function ); |
426 | | libcnotify_print_data( |
427 | | data, |
428 | | data_size, |
429 | | LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); |
430 | | } |
431 | | #endif |
432 | 985 | if( memory_compare( |
433 | 985 | ( (vshadow_volume_header_t *) data )->identifier, |
434 | 985 | vshadow_vss_identifier, |
435 | 985 | 8 ) != 0 ) |
436 | 1 | { |
437 | 1 | libcerror_error_set( |
438 | 1 | error, |
439 | 1 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
440 | 1 | LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, |
441 | 1 | "%s: invalid volume identifier.", |
442 | 1 | function ); |
443 | | |
444 | 1 | return( -1 ); |
445 | 1 | } |
446 | 984 | byte_stream_copy_to_uint32_little_endian( |
447 | 984 | ( (vshadow_volume_header_t *) data )->version, |
448 | 984 | version ); |
449 | | |
450 | 984 | byte_stream_copy_to_uint32_little_endian( |
451 | 984 | ( (vshadow_volume_header_t *) data )->record_type, |
452 | 984 | record_type ); |
453 | | |
454 | 984 | byte_stream_copy_to_uint64_little_endian( |
455 | 984 | ( (vshadow_volume_header_t *) data )->catalog_offset, |
456 | 984 | safe_catalog_offset ); |
457 | | |
458 | | #if defined( HAVE_DEBUG_OUTPUT ) |
459 | | if( libcnotify_verbose != 0 ) |
460 | | { |
461 | | if( libvshadow_debug_print_guid_value( |
462 | | function, |
463 | | "identifier\t\t", |
464 | | ( (vshadow_volume_header_t *) data )->identifier, |
465 | | 16, |
466 | | LIBFGUID_ENDIAN_LITTLE, |
467 | | LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE, |
468 | | error ) != 1 ) |
469 | | { |
470 | | libcerror_error_set( |
471 | | error, |
472 | | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
473 | | LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, |
474 | | "%s: unable to print GUID value.", |
475 | | function ); |
476 | | |
477 | | return( -1 ); |
478 | | } |
479 | | libcnotify_printf( |
480 | | "%s: version\t\t\t: %" PRIu32 "\n", |
481 | | function, |
482 | | version ); |
483 | | |
484 | | libcnotify_printf( |
485 | | "%s: record type\t\t: %" PRIu32 "\n", |
486 | | function, |
487 | | record_type ); |
488 | | |
489 | | byte_stream_copy_to_uint64_little_endian( |
490 | | ( (vshadow_volume_header_t *) data )->offset, |
491 | | value_64bit ); |
492 | | libcnotify_printf( |
493 | | "%s: offset\t\t\t: 0x%08" PRIx64 "\n", |
494 | | function, |
495 | | value_64bit ); |
496 | | |
497 | | byte_stream_copy_to_uint64_little_endian( |
498 | | ( (vshadow_volume_header_t *) data )->unknown1, |
499 | | value_64bit ); |
500 | | libcnotify_printf( |
501 | | "%s: unknown1\t\t\t: 0x%08" PRIx64 "\n", |
502 | | function, |
503 | | value_64bit ); |
504 | | |
505 | | byte_stream_copy_to_uint64_little_endian( |
506 | | ( (vshadow_volume_header_t *) data )->unknown2, |
507 | | value_64bit ); |
508 | | libcnotify_printf( |
509 | | "%s: unknown2\t\t\t: 0x%08" PRIx64 "\n", |
510 | | function, |
511 | | value_64bit ); |
512 | | |
513 | | libcnotify_printf( |
514 | | "%s: catalog offset\t\t: 0x%08" PRIx64 "\n", |
515 | | function, |
516 | | safe_catalog_offset ); |
517 | | |
518 | | byte_stream_copy_to_uint64_little_endian( |
519 | | ( (vshadow_volume_header_t *) data )->maximum_size, |
520 | | value_64bit ); |
521 | | libcnotify_printf( |
522 | | "%s: maximum size\t\t: %" PRIu64 "\n", |
523 | | function, |
524 | | value_64bit ); |
525 | | |
526 | | if( libvshadow_debug_print_guid_value( |
527 | | function, |
528 | | "volume identifier\t\t", |
529 | | ( (vshadow_volume_header_t *) data )->volume_identifier, |
530 | | 16, |
531 | | LIBFGUID_ENDIAN_LITTLE, |
532 | | LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE, |
533 | | error ) != 1 ) |
534 | | { |
535 | | libcerror_error_set( |
536 | | error, |
537 | | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
538 | | LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, |
539 | | "%s: unable to print GUID value.", |
540 | | function ); |
541 | | |
542 | | return( -1 ); |
543 | | } |
544 | | if( libvshadow_debug_print_guid_value( |
545 | | function, |
546 | | "store volume identifier\t", |
547 | | ( (vshadow_volume_header_t *) data )->store_volume_identifier, |
548 | | 16, |
549 | | LIBFGUID_ENDIAN_LITTLE, |
550 | | LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE, |
551 | | error ) != 1 ) |
552 | | { |
553 | | libcerror_error_set( |
554 | | error, |
555 | | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
556 | | LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, |
557 | | "%s: unable to print GUID value.", |
558 | | function ); |
559 | | |
560 | | return( -1 ); |
561 | | } |
562 | | byte_stream_copy_to_uint32_little_endian( |
563 | | ( (vshadow_volume_header_t *) data )->unknown3, |
564 | | value_32bit ); |
565 | | libcnotify_printf( |
566 | | "%s: unknown3\t\t\t: 0x%08" PRIx64 "\n", |
567 | | function, |
568 | | value_32bit ); |
569 | | |
570 | | libcnotify_printf( |
571 | | "%s: unknown4:\n", |
572 | | function ); |
573 | | libcnotify_print_data( |
574 | | ( (vshadow_volume_header_t *) data )->unknown4, |
575 | | 412, |
576 | | LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); |
577 | | } |
578 | | #endif /* defined( HAVE_DEBUG_OUTPUT ) */ |
579 | | |
580 | 984 | if( ( version != 1 ) |
581 | 942 | && ( version != 2 ) ) |
582 | 40 | { |
583 | 40 | libcerror_error_set( |
584 | 40 | error, |
585 | 40 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
586 | 40 | LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, |
587 | 40 | "%s: unsupported version: %" PRIu32 ".", |
588 | 40 | function, |
589 | 40 | version ); |
590 | | |
591 | 40 | return( -1 ); |
592 | 40 | } |
593 | 944 | if( record_type != LIBVSHADOW_RECORD_TYPE_VOLUME_HEADER ) |
594 | 39 | { |
595 | 39 | libcerror_error_set( |
596 | 39 | error, |
597 | 39 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
598 | 39 | LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, |
599 | 39 | "%s: unsupported record type: %" PRIu32 ".", |
600 | 39 | function, |
601 | 39 | version ); |
602 | | |
603 | 39 | return( -1 ); |
604 | 39 | } |
605 | 905 | *catalog_offset = (off64_t) safe_catalog_offset; |
606 | | |
607 | 905 | return( 1 ); |
608 | 944 | } |
609 | | |
610 | | /* Reads the catalog |
611 | | * Returns 1 if successful or -1 on error |
612 | | */ |
613 | | int libvshadow_io_handle_read_catalog( |
614 | | libvshadow_io_handle_t *io_handle, |
615 | | libbfio_handle_t *file_io_handle, |
616 | | off64_t file_offset, |
617 | | size64_t *volume_size, |
618 | | libcdata_array_t *store_descriptors_array, |
619 | | libcerror_error_t **error ) |
620 | 858 | { |
621 | 858 | libvshadow_block_tree_t *catalog_block_tree = NULL; |
622 | 858 | libvshadow_store_descriptor_t *last_store_descriptor = NULL; |
623 | 858 | libvshadow_store_descriptor_t *store_descriptor = NULL; |
624 | 858 | uint8_t *catalog_block_data = NULL; |
625 | 858 | static char *function = "libvshadow_io_handle_read_catalog"; |
626 | 858 | size64_t safe_volume_size = 0; |
627 | 858 | size_t catalog_block_offset = 0; |
628 | 858 | ssize_t read_count = 0; |
629 | 858 | off64_t next_offset = 0; |
630 | 858 | uint64_t catalog_entry_type = 0; |
631 | 858 | int result = 0; |
632 | 858 | int store_descriptor_index = 0; |
633 | | |
634 | 858 | if( io_handle == NULL ) |
635 | 0 | { |
636 | 0 | libcerror_error_set( |
637 | 0 | error, |
638 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
639 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
640 | 0 | "%s: invalid IO handle.", |
641 | 0 | function ); |
642 | |
|
643 | 0 | return( -1 ); |
644 | 0 | } |
645 | 858 | if( volume_size == NULL ) |
646 | 0 | { |
647 | 0 | libcerror_error_set( |
648 | 0 | error, |
649 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
650 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
651 | 0 | "%s: invalid volume size.", |
652 | 0 | function ); |
653 | |
|
654 | 0 | return( -1 ); |
655 | 0 | } |
656 | 858 | catalog_block_data = (uint8_t *) memory_allocate( |
657 | 858 | sizeof( uint8_t ) * io_handle->block_size ); |
658 | | |
659 | 858 | if( catalog_block_data == NULL ) |
660 | 0 | { |
661 | 0 | libcerror_error_set( |
662 | 0 | error, |
663 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
664 | 0 | LIBCERROR_MEMORY_ERROR_INSUFFICIENT, |
665 | 0 | "%s: unable to catalog block data.", |
666 | 0 | function ); |
667 | |
|
668 | 0 | goto on_error; |
669 | 0 | } |
670 | 858 | if( libvshadow_block_tree_initialize( |
671 | 858 | &catalog_block_tree, |
672 | 858 | io_handle->volume_size, |
673 | 858 | io_handle->block_size, |
674 | 858 | error ) != 1 ) |
675 | 0 | { |
676 | 0 | libcerror_error_set( |
677 | 0 | error, |
678 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
679 | 0 | LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, |
680 | 0 | "%s: unable to create catalog block tree.", |
681 | 0 | function ); |
682 | |
|
683 | 0 | goto on_error; |
684 | 0 | } |
685 | 858 | do |
686 | 866 | { |
687 | | #if defined( HAVE_DEBUG_OUTPUT ) |
688 | | if( libcnotify_verbose != 0 ) |
689 | | { |
690 | | libcnotify_printf( |
691 | | "%s: reading catalog block at offset: %" PRIi64 " (0x%08" PRIx64 ")\n", |
692 | | function, |
693 | | file_offset, |
694 | | file_offset ); |
695 | | } |
696 | | #endif |
697 | 866 | if( libvshadow_io_handle_check_if_block_first_read( |
698 | 866 | io_handle, |
699 | 866 | catalog_block_tree, |
700 | 866 | file_offset, |
701 | 866 | error ) != 1 ) |
702 | 116 | { |
703 | 116 | libcerror_error_set( |
704 | 116 | error, |
705 | 116 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
706 | 116 | LIBCERROR_RUNTIME_ERROR_GENERIC, |
707 | 116 | "%s: unable to check if first read of catalog block at offset: %" PRIi64 " (0x%08" PRIx64 ").", |
708 | 116 | function, |
709 | 116 | file_offset, |
710 | 116 | file_offset ); |
711 | | |
712 | 116 | goto on_error; |
713 | 116 | } |
714 | 750 | read_count = libbfio_handle_read_buffer_at_offset( |
715 | 750 | file_io_handle, |
716 | 750 | catalog_block_data, |
717 | 750 | io_handle->block_size, |
718 | 750 | file_offset, |
719 | 750 | error ); |
720 | | |
721 | 750 | if( read_count != (ssize_t) io_handle->block_size ) |
722 | 40 | { |
723 | 40 | libcerror_error_set( |
724 | 40 | error, |
725 | 40 | LIBCERROR_ERROR_DOMAIN_IO, |
726 | 40 | LIBCERROR_IO_ERROR_READ_FAILED, |
727 | 40 | "%s: unable to read catalog block data at offset: %" PRIi64 " (0x%08" PRIx64 ").", |
728 | 40 | function, |
729 | 40 | file_offset, |
730 | 40 | file_offset ); |
731 | | |
732 | 40 | goto on_error; |
733 | 40 | } |
734 | 710 | if( libvshadow_io_handle_read_catalog_header_data( |
735 | 710 | io_handle, |
736 | 710 | catalog_block_data, |
737 | 710 | io_handle->block_size, |
738 | 710 | &next_offset, |
739 | 710 | error ) != 1 ) |
740 | 138 | { |
741 | 138 | libcerror_error_set( |
742 | 138 | error, |
743 | 138 | LIBCERROR_ERROR_DOMAIN_IO, |
744 | 138 | LIBCERROR_IO_ERROR_READ_FAILED, |
745 | 138 | "%s: unable to read catalog block header.", |
746 | 138 | function ); |
747 | | |
748 | 138 | goto on_error; |
749 | 138 | } |
750 | 572 | catalog_block_offset = sizeof( vshadow_catalog_header_t ); |
751 | | |
752 | 27.4k | while( catalog_block_offset < io_handle->block_size ) |
753 | 27.2k | { |
754 | 27.2k | if( store_descriptor == NULL ) |
755 | 5.25k | { |
756 | 5.25k | if( libvshadow_store_descriptor_initialize( |
757 | 5.25k | &store_descriptor, |
758 | 5.25k | error ) != 1 ) |
759 | 0 | { |
760 | 0 | libcerror_error_set( |
761 | 0 | error, |
762 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
763 | 0 | LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, |
764 | 0 | "%s: unable to create store descriptor.", |
765 | 0 | function ); |
766 | |
|
767 | 0 | goto on_error; |
768 | 0 | } |
769 | 5.25k | } |
770 | 27.2k | result = libvshadow_store_descriptor_read_catalog_entry( |
771 | 27.2k | store_descriptor, |
772 | 27.2k | &( catalog_block_data[ catalog_block_offset ] ), |
773 | 27.2k | io_handle->block_size - catalog_block_offset, |
774 | 27.2k | &catalog_entry_type, |
775 | 27.2k | error ); |
776 | | |
777 | 27.2k | if( result == -1 ) |
778 | 406 | { |
779 | 406 | libcerror_error_set( |
780 | 406 | error, |
781 | 406 | LIBCERROR_ERROR_DOMAIN_IO, |
782 | 406 | LIBCERROR_IO_ERROR_READ_FAILED, |
783 | 406 | "%s: unable to read catalog entry.", |
784 | 406 | function ); |
785 | | |
786 | 406 | goto on_error; |
787 | 406 | } |
788 | 26.8k | if( catalog_entry_type == 2 ) |
789 | 4.73k | { |
790 | 4.73k | if( libcdata_array_insert_entry( |
791 | 4.73k | store_descriptors_array, |
792 | 4.73k | &store_descriptor_index, |
793 | 4.73k | (intptr_t *) store_descriptor, |
794 | 4.73k | (int(*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libvshadow_store_descriptor_compare_by_creation_time, |
795 | 4.73k | LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES, |
796 | 4.73k | error ) != 1 ) |
797 | 1 | { |
798 | 1 | libcerror_error_set( |
799 | 1 | error, |
800 | 1 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
801 | 1 | LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, |
802 | 1 | "%s: unable to append store descriptor to array.", |
803 | 1 | function ); |
804 | | |
805 | 1 | goto on_error; |
806 | 1 | } |
807 | 4.73k | if( ( safe_volume_size == 0 ) |
808 | 991 | && ( store_descriptor_index == 0 ) ) |
809 | 580 | { |
810 | 580 | safe_volume_size = store_descriptor->volume_size; |
811 | 580 | } |
812 | | #if defined( HAVE_DEBUG_OUTPUT ) |
813 | | else if( libcnotify_verbose != 0 ) |
814 | | { |
815 | | if( safe_volume_size != store_descriptor->volume_size ) |
816 | | { |
817 | | libcnotify_printf( |
818 | | "%s: store descriptor: %d - mismatch in volume size: %" PRIu64 " (expected: %" PRIu64 ").", |
819 | | function, |
820 | | store_descriptor_index, |
821 | | store_descriptor->volume_size, |
822 | | safe_volume_size ); |
823 | | } |
824 | | } |
825 | | #endif |
826 | 4.73k | last_store_descriptor = store_descriptor; |
827 | 4.73k | store_descriptor = NULL; |
828 | 4.73k | } |
829 | 22.0k | else if( catalog_entry_type == 3 ) |
830 | 2.21k | { |
831 | 2.21k | if( ( last_store_descriptor != NULL ) |
832 | 1.95k | && ( memory_compare( |
833 | 1.95k | store_descriptor->identifier, |
834 | 1.95k | last_store_descriptor->identifier, |
835 | 1.95k | 16 ) != 0 ) ) |
836 | 1.36k | { |
837 | 1.36k | result = libcdata_array_get_entry_by_value( |
838 | 1.36k | store_descriptors_array, |
839 | 1.36k | (intptr_t *) store_descriptor, |
840 | 1.36k | (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libvshadow_store_descriptor_compare_by_identifier, |
841 | 1.36k | (intptr_t **) &last_store_descriptor, |
842 | 1.36k | error ); |
843 | | |
844 | 1.36k | if( result == -1 ) |
845 | 0 | { |
846 | 0 | libcerror_error_set( |
847 | 0 | error, |
848 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
849 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
850 | 0 | "%s: unable to retrieve store descriptors by identifier.", |
851 | 0 | function ); |
852 | |
|
853 | 0 | goto on_error; |
854 | 0 | } |
855 | 1.36k | } |
856 | | /* TODO look for the last store decriptor ? */ |
857 | 2.21k | if( last_store_descriptor != NULL ) |
858 | 1.95k | { |
859 | 1.95k | last_store_descriptor->store_block_list_offset = store_descriptor->store_block_list_offset; |
860 | 1.95k | last_store_descriptor->store_header_offset = store_descriptor->store_header_offset; |
861 | 1.95k | last_store_descriptor->store_block_range_list_offset = store_descriptor->store_block_range_list_offset; |
862 | 1.95k | last_store_descriptor->store_bitmap_offset = store_descriptor->store_bitmap_offset; |
863 | 1.95k | last_store_descriptor->store_previous_bitmap_offset = store_descriptor->store_previous_bitmap_offset; |
864 | 1.95k | last_store_descriptor->has_in_volume_store_data = 1; |
865 | 1.95k | } |
866 | | #if defined( HAVE_DEBUG_OUTPUT ) |
867 | | else |
868 | | { |
869 | | libcnotify_printf( |
870 | | "%s: missing last store descriptor.\n", |
871 | | function ); |
872 | | } |
873 | | #endif |
874 | 2.21k | } |
875 | 26.8k | catalog_block_offset += (size_t) 128; |
876 | 26.8k | } |
877 | 165 | file_offset = next_offset; |
878 | 165 | } |
879 | 858 | while( file_offset != 0 ); |
880 | | |
881 | 157 | if( store_descriptor != NULL ) |
882 | 117 | { |
883 | 117 | if( libvshadow_store_descriptor_free( |
884 | 117 | &store_descriptor, |
885 | 117 | error ) != 1 ) |
886 | 0 | { |
887 | 0 | libcerror_error_set( |
888 | 0 | error, |
889 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
890 | 0 | LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, |
891 | 0 | "%s: unable to free store descriptor.", |
892 | 0 | function ); |
893 | |
|
894 | 0 | goto on_error; |
895 | 0 | } |
896 | 117 | } |
897 | 157 | if( libvshadow_block_tree_free( |
898 | 157 | &catalog_block_tree, |
899 | 157 | (int (*)(intptr_t **, libcerror_error_t **)) &libvshadow_block_descriptor_free, |
900 | 157 | error ) != 1 ) |
901 | 0 | { |
902 | 0 | libcerror_error_set( |
903 | 0 | error, |
904 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
905 | 0 | LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, |
906 | 0 | "%s: unable to free catalog block tree.", |
907 | 0 | function ); |
908 | |
|
909 | 0 | goto on_error; |
910 | 0 | } |
911 | 157 | memory_free( |
912 | 157 | catalog_block_data ); |
913 | | |
914 | 157 | *volume_size = safe_volume_size; |
915 | | |
916 | 157 | return( 1 ); |
917 | | |
918 | 701 | on_error: |
919 | 701 | if( store_descriptor != NULL ) |
920 | 412 | { |
921 | 412 | libvshadow_store_descriptor_free( |
922 | 412 | &store_descriptor, |
923 | 412 | NULL ); |
924 | 412 | } |
925 | 701 | if( catalog_block_tree != NULL ) |
926 | 701 | { |
927 | 701 | libvshadow_block_tree_free( |
928 | 701 | &catalog_block_tree, |
929 | 701 | (int (*)(intptr_t **, libcerror_error_t **)) &libvshadow_block_descriptor_free, |
930 | 701 | NULL ); |
931 | 701 | } |
932 | 701 | if( catalog_block_data != NULL ) |
933 | 701 | { |
934 | 701 | memory_free( |
935 | 701 | catalog_block_data ); |
936 | 701 | } |
937 | 701 | return( -1 ); |
938 | 157 | } |
939 | | |
940 | | /* Reads the catalog header |
941 | | * Returns 1 if successful or -1 on error |
942 | | */ |
943 | | int libvshadow_io_handle_read_catalog_header_data( |
944 | | libvshadow_io_handle_t *io_handle, |
945 | | const uint8_t *data, |
946 | | size_t data_size, |
947 | | off64_t *next_offset, |
948 | | libcerror_error_t **error ) |
949 | 710 | { |
950 | 710 | static char *function = "libvshadow_io_handle_read_catalog_header_data"; |
951 | 710 | uint64_t safe_next_offset = 0; |
952 | 710 | uint32_t record_type = 0; |
953 | 710 | uint32_t version = 0; |
954 | | |
955 | | #if defined( HAVE_DEBUG_OUTPUT ) |
956 | | uint64_t value_64bit = 0; |
957 | | #endif |
958 | | |
959 | 710 | if( io_handle == NULL ) |
960 | 0 | { |
961 | 0 | libcerror_error_set( |
962 | 0 | error, |
963 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
964 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
965 | 0 | "%s: invalid IO handle.", |
966 | 0 | function ); |
967 | |
|
968 | 0 | return( -1 ); |
969 | 0 | } |
970 | 710 | if( data == NULL ) |
971 | 0 | { |
972 | 0 | libcerror_error_set( |
973 | 0 | error, |
974 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
975 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
976 | 0 | "%s: invalid data.", |
977 | 0 | function ); |
978 | |
|
979 | 0 | return( -1 ); |
980 | 0 | } |
981 | 710 | if( data_size < sizeof( vshadow_catalog_header_t ) ) |
982 | 0 | { |
983 | 0 | libcerror_error_set( |
984 | 0 | error, |
985 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
986 | 0 | LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, |
987 | 0 | "%s: invalid data size value too small.", |
988 | 0 | function ); |
989 | |
|
990 | 0 | return( -1 ); |
991 | 0 | } |
992 | 710 | if( data_size > (size_t) SSIZE_MAX ) |
993 | 0 | { |
994 | 0 | libcerror_error_set( |
995 | 0 | error, |
996 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
997 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, |
998 | 0 | "%s: invalid data size value exceeds maximum.", |
999 | 0 | function ); |
1000 | |
|
1001 | 0 | return( -1 ); |
1002 | 0 | } |
1003 | 710 | if( next_offset == NULL ) |
1004 | 0 | { |
1005 | 0 | libcerror_error_set( |
1006 | 0 | error, |
1007 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
1008 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
1009 | 0 | "%s: invalid next offset.", |
1010 | 0 | function ); |
1011 | |
|
1012 | 0 | return( -1 ); |
1013 | 0 | } |
1014 | | #if defined( HAVE_DEBUG_OUTPUT ) |
1015 | | if( libcnotify_verbose != 0 ) |
1016 | | { |
1017 | | libcnotify_printf( |
1018 | | "%s: catalog header data:\n", |
1019 | | function ); |
1020 | | libcnotify_print_data( |
1021 | | data, |
1022 | | data_size, |
1023 | | LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); |
1024 | | } |
1025 | | #endif |
1026 | 710 | if( memory_compare( |
1027 | 710 | ( (vshadow_catalog_header_t *) data )->identifier, |
1028 | 710 | vshadow_vss_identifier, |
1029 | 710 | 8 ) != 0 ) |
1030 | 13 | { |
1031 | 13 | libcerror_error_set( |
1032 | 13 | error, |
1033 | 13 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1034 | 13 | LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, |
1035 | 13 | "%s: invalid catalog header identifier.", |
1036 | 13 | function ); |
1037 | | |
1038 | 13 | return( -1 ); |
1039 | 13 | } |
1040 | 697 | byte_stream_copy_to_uint32_little_endian( |
1041 | 697 | ( (vshadow_catalog_header_t *) data )->version, |
1042 | 697 | version ); |
1043 | | |
1044 | 697 | byte_stream_copy_to_uint32_little_endian( |
1045 | 697 | ( (vshadow_catalog_header_t *) data )->record_type, |
1046 | 697 | record_type ); |
1047 | | |
1048 | 697 | byte_stream_copy_to_uint64_little_endian( |
1049 | 697 | ( (vshadow_catalog_header_t *) data )->next_offset, |
1050 | 697 | safe_next_offset ); |
1051 | | |
1052 | | #if defined( HAVE_DEBUG_OUTPUT ) |
1053 | | if( libcnotify_verbose != 0 ) |
1054 | | { |
1055 | | if( libvshadow_debug_print_guid_value( |
1056 | | function, |
1057 | | "identifier\t\t", |
1058 | | ( (vshadow_catalog_header_t *) data )->identifier, |
1059 | | 16, |
1060 | | LIBFGUID_ENDIAN_LITTLE, |
1061 | | LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE, |
1062 | | error ) != 1 ) |
1063 | | { |
1064 | | libcerror_error_set( |
1065 | | error, |
1066 | | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1067 | | LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, |
1068 | | "%s: unable to print GUID value.", |
1069 | | function ); |
1070 | | |
1071 | | return( -1 ); |
1072 | | } |
1073 | | libcnotify_printf( |
1074 | | "%s: version\t\t\t: %" PRIu32 "\n", |
1075 | | function, |
1076 | | version ); |
1077 | | |
1078 | | libcnotify_printf( |
1079 | | "%s: record type\t\t: %" PRIu32 "\n", |
1080 | | function, |
1081 | | record_type ); |
1082 | | |
1083 | | byte_stream_copy_to_uint64_little_endian( |
1084 | | ( (vshadow_catalog_header_t *) data )->relative_offset, |
1085 | | value_64bit ); |
1086 | | libcnotify_printf( |
1087 | | "%s: relative offset\t\t: 0x%08" PRIx64 "\n", |
1088 | | function, |
1089 | | value_64bit ); |
1090 | | |
1091 | | byte_stream_copy_to_uint64_little_endian( |
1092 | | ( (vshadow_catalog_header_t *) data )->offset, |
1093 | | value_64bit ); |
1094 | | libcnotify_printf( |
1095 | | "%s: offset\t\t\t: 0x%08" PRIx64 "\n", |
1096 | | function, |
1097 | | value_64bit ); |
1098 | | |
1099 | | libcnotify_printf( |
1100 | | "%s: next offset\t\t: 0x%08" PRIx64 "\n", |
1101 | | function, |
1102 | | safe_next_offset ); |
1103 | | |
1104 | | libcnotify_printf( |
1105 | | "%s: unknown1:\n", |
1106 | | function ); |
1107 | | libcnotify_print_data( |
1108 | | ( (vshadow_catalog_header_t *) data )->unknown1, |
1109 | | 80, |
1110 | | LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); |
1111 | | } |
1112 | | #endif /* defined( HAVE_DEBUG_OUTPUT ) */ |
1113 | | |
1114 | 697 | if( version != 1 ) |
1115 | 37 | { |
1116 | 37 | libcerror_error_set( |
1117 | 37 | error, |
1118 | 37 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1119 | 37 | LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, |
1120 | 37 | "%s: unsupported version: %" PRIu32 ".", |
1121 | 37 | function, |
1122 | 37 | version ); |
1123 | | |
1124 | 37 | return( -1 ); |
1125 | 37 | } |
1126 | 660 | if( record_type != LIBVSHADOW_RECORD_TYPE_CATALOG ) |
1127 | 35 | { |
1128 | 35 | libcerror_error_set( |
1129 | 35 | error, |
1130 | 35 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1131 | 35 | LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, |
1132 | 35 | "%s: unsupported record type: %" PRIu32 ".", |
1133 | 35 | function, |
1134 | 35 | version ); |
1135 | | |
1136 | 35 | return( -1 ); |
1137 | 35 | } |
1138 | 625 | if( safe_next_offset > (uint64_t) INT64_MAX ) |
1139 | 53 | { |
1140 | 53 | libcerror_error_set( |
1141 | 53 | error, |
1142 | 53 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1143 | 53 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
1144 | 53 | "%s: invalid next offset value out of bounds.", |
1145 | 53 | function, |
1146 | 53 | version ); |
1147 | | |
1148 | 53 | return( -1 ); |
1149 | 53 | } |
1150 | 572 | *next_offset = (off64_t) safe_next_offset; |
1151 | | |
1152 | 572 | return( 1 ); |
1153 | 625 | } |
1154 | | |