/src/libpff/libpff/libpff_index.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Index functions |
3 | | * |
4 | | * Copyright (C) 2008-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 "libpff_block_descriptor.h" |
28 | | #include "libpff_block_tree.h" |
29 | | #include "libpff_block_tree_node.h" |
30 | | #include "libpff_definitions.h" |
31 | | #include "libpff_index.h" |
32 | | #include "libpff_index_node.h" |
33 | | #include "libpff_index_value.h" |
34 | | #include "libpff_libbfio.h" |
35 | | #include "libpff_libcerror.h" |
36 | | #include "libpff_libcnotify.h" |
37 | | #include "libpff_libfdata.h" |
38 | | #include "libpff_libfmapi.h" |
39 | | #include "libpff_unused.h" |
40 | | |
41 | | #include "pff_index_node.h" |
42 | | |
43 | | /* Creates an index |
44 | | * Make sure the value index is referencing, is set to NULL |
45 | | * Returns 1 if successful or -1 on error |
46 | | */ |
47 | | int libpff_index_initialize( |
48 | | libpff_index_t **index, |
49 | | uint8_t index_type, |
50 | | off64_t root_node_offset, |
51 | | uint64_t root_node_back_pointer, |
52 | | libcerror_error_t **error ) |
53 | 5.58k | { |
54 | 5.58k | static char *function = "libpff_index_initialize"; |
55 | | |
56 | 5.58k | if( index == NULL ) |
57 | 0 | { |
58 | 0 | libcerror_error_set( |
59 | 0 | error, |
60 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
61 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
62 | 0 | "%s: invalid index.", |
63 | 0 | function ); |
64 | |
|
65 | 0 | return( -1 ); |
66 | 0 | } |
67 | 5.58k | if( *index != NULL ) |
68 | 0 | { |
69 | 0 | libcerror_error_set( |
70 | 0 | error, |
71 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
72 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, |
73 | 0 | "%s: invalid index value already set.", |
74 | 0 | function ); |
75 | |
|
76 | 0 | return( -1 ); |
77 | 0 | } |
78 | 5.58k | *index = memory_allocate_structure( |
79 | 5.58k | libpff_index_t ); |
80 | | |
81 | 5.58k | if( *index == NULL ) |
82 | 0 | { |
83 | 0 | libcerror_error_set( |
84 | 0 | error, |
85 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
86 | 0 | LIBCERROR_MEMORY_ERROR_INSUFFICIENT, |
87 | 0 | "%s: unable to create index.", |
88 | 0 | function ); |
89 | |
|
90 | 0 | goto on_error; |
91 | 0 | } |
92 | 5.58k | if( memory_set( |
93 | 5.58k | *index, |
94 | 5.58k | 0, |
95 | 5.58k | sizeof( libpff_index_t ) ) == NULL ) |
96 | 0 | { |
97 | 0 | libcerror_error_set( |
98 | 0 | error, |
99 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
100 | 0 | LIBCERROR_MEMORY_ERROR_SET_FAILED, |
101 | 0 | "%s: unable to clear index.", |
102 | 0 | function ); |
103 | |
|
104 | 0 | goto on_error; |
105 | 0 | } |
106 | 5.58k | ( *index )->type = index_type; |
107 | 5.58k | ( *index )->root_node_offset = root_node_offset; |
108 | 5.58k | ( *index )->root_node_back_pointer = root_node_back_pointer; |
109 | | |
110 | 5.58k | return( 1 ); |
111 | | |
112 | 0 | on_error: |
113 | 0 | if( *index != NULL ) |
114 | 0 | { |
115 | 0 | memory_free( |
116 | 0 | *index ); |
117 | |
|
118 | 0 | *index = NULL; |
119 | 0 | } |
120 | 0 | return( -1 ); |
121 | 5.58k | } |
122 | | |
123 | | /* Frees an index |
124 | | * Returns 1 if successful or -1 on error |
125 | | */ |
126 | | int libpff_index_free( |
127 | | libpff_index_t **index, |
128 | | libcerror_error_t **error ) |
129 | 5.58k | { |
130 | 5.58k | static char *function = "libpff_index_free"; |
131 | | |
132 | 5.58k | if( index == NULL ) |
133 | 0 | { |
134 | 0 | libcerror_error_set( |
135 | 0 | error, |
136 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
137 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
138 | 0 | "%s: invalid index.", |
139 | 0 | function ); |
140 | |
|
141 | 0 | return( -1 ); |
142 | 0 | } |
143 | 5.58k | if( *index != NULL ) |
144 | 5.58k | { |
145 | 5.58k | memory_free( |
146 | 5.58k | *index ); |
147 | | |
148 | 5.58k | *index = NULL; |
149 | 5.58k | } |
150 | 5.58k | return( 1 ); |
151 | 5.58k | } |
152 | | |
153 | | /* Checks if this is the first time the index node block is being read |
154 | | * Returns 1 if successful or -1 on error |
155 | | */ |
156 | | int libpff_index_check_if_node_block_first_read( |
157 | | libpff_index_t *index, |
158 | | libpff_block_tree_t *node_block_tree, |
159 | | off64_t node_offset, |
160 | | uint64_t identifier, |
161 | | libcerror_error_t **error ) |
162 | 397k | { |
163 | 397k | libpff_block_descriptor_t *existing_block_descriptor = NULL; |
164 | 397k | libpff_block_descriptor_t *new_block_descriptor = NULL; |
165 | 397k | libpff_block_tree_node_t *leaf_block_tree_node = NULL; |
166 | 397k | static char *function = "libpff_index_check_if_node_block_first_read"; |
167 | 397k | int leaf_value_index = 0; |
168 | 397k | int result = 0; |
169 | | |
170 | 397k | if( index == NULL ) |
171 | 0 | { |
172 | 0 | libcerror_error_set( |
173 | 0 | error, |
174 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
175 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
176 | 0 | "%s: invalid index.", |
177 | 0 | function ); |
178 | |
|
179 | 0 | return( -1 ); |
180 | 0 | } |
181 | 397k | if( libpff_block_descriptor_initialize( |
182 | 397k | &new_block_descriptor, |
183 | 397k | error ) != 1 ) |
184 | 0 | { |
185 | 0 | libcerror_error_set( |
186 | 0 | error, |
187 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
188 | 0 | LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, |
189 | 0 | "%s: unable to create block descriptor.", |
190 | 0 | function ); |
191 | |
|
192 | 0 | goto on_error; |
193 | 0 | } |
194 | 397k | new_block_descriptor->identifier = identifier; |
195 | | |
196 | 397k | result = libpff_block_tree_insert_block_descriptor_by_offset( |
197 | 397k | node_block_tree, |
198 | 397k | node_offset, |
199 | 397k | new_block_descriptor, |
200 | 397k | &leaf_value_index, |
201 | 397k | &leaf_block_tree_node, |
202 | 397k | &existing_block_descriptor, |
203 | 397k | error ); |
204 | | |
205 | 397k | if( result == -1 ) |
206 | 232 | { |
207 | 232 | libcerror_error_set( |
208 | 232 | error, |
209 | 232 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
210 | 232 | LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, |
211 | 232 | "%s: unable to insert block descriptor for index node at offset: %" PRIi64 " (0x%08" PRIx64 ") in node block tree.", |
212 | 232 | function, |
213 | 232 | node_offset, |
214 | 232 | node_offset ); |
215 | | |
216 | 232 | goto on_error; |
217 | 232 | } |
218 | 397k | else if( result == 0 ) |
219 | 131 | { |
220 | 131 | libcerror_error_set( |
221 | 131 | error, |
222 | 131 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
223 | 131 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
224 | 131 | "%s: invalid index node at offset: %" PRIi64 " (0x%08" PRIx64 ") value already exists.", |
225 | 131 | function, |
226 | 131 | node_offset, |
227 | 131 | node_offset ); |
228 | | |
229 | 131 | goto on_error; |
230 | 131 | } |
231 | 396k | new_block_descriptor = NULL; |
232 | | |
233 | 396k | return( 1 ); |
234 | | |
235 | 363 | on_error: |
236 | 363 | if( new_block_descriptor != NULL ) |
237 | 363 | { |
238 | 363 | libpff_block_descriptor_free( |
239 | 363 | &new_block_descriptor, |
240 | 363 | NULL ); |
241 | 363 | } |
242 | 363 | return( -1 ); |
243 | 397k | } |
244 | | |
245 | | /* Retrieves the leaf node from an index node for the specific identifier |
246 | | * Returns 1 if successful, 0 if no leaf node was found or -1 on error |
247 | | */ |
248 | | int libpff_index_get_leaf_node_from_node_by_identifier( |
249 | | libpff_index_t *index, |
250 | | libpff_io_handle_t *io_handle, |
251 | | libbfio_handle_t *file_io_handle, |
252 | | libpff_block_tree_t *node_block_tree, |
253 | | off64_t node_offset, |
254 | | uint64_t node_back_pointer, |
255 | | uint64_t identifier, |
256 | | libpff_index_node_t **leaf_node, |
257 | | uint16_t *leaf_node_entry_index, |
258 | | libcerror_error_t **error ) |
259 | 397k | { |
260 | 397k | libpff_index_node_t *index_node = NULL; |
261 | 397k | uint8_t *node_entry_data = NULL; |
262 | 397k | static char *function = "libpff_index_get_leaf_node_from_node_by_identifier"; |
263 | 397k | uint64_t entry_identifier = 0; |
264 | 397k | uint64_t sub_node_back_pointer = 0; |
265 | 397k | uint64_t sub_node_offset = 0; |
266 | 397k | uint16_t entry_index = 0; |
267 | 397k | int result = 0; |
268 | | |
269 | 397k | if( index == NULL ) |
270 | 0 | { |
271 | 0 | libcerror_error_set( |
272 | 0 | error, |
273 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
274 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
275 | 0 | "%s: invalid index.", |
276 | 0 | function ); |
277 | |
|
278 | 0 | return( -1 ); |
279 | 0 | } |
280 | 397k | if( io_handle == NULL ) |
281 | 0 | { |
282 | 0 | libcerror_error_set( |
283 | 0 | error, |
284 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
285 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
286 | 0 | "%s: invalid IO handle.", |
287 | 0 | function ); |
288 | |
|
289 | 0 | return( -1 ); |
290 | 0 | } |
291 | 397k | if( leaf_node == NULL ) |
292 | 0 | { |
293 | 0 | libcerror_error_set( |
294 | 0 | error, |
295 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
296 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
297 | 0 | "%s: invalid leaf node.", |
298 | 0 | function ); |
299 | |
|
300 | 0 | return( -1 ); |
301 | 0 | } |
302 | 397k | if( leaf_node_entry_index == NULL ) |
303 | 0 | { |
304 | 0 | libcerror_error_set( |
305 | 0 | error, |
306 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
307 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
308 | 0 | "%s: invalid leaf node entry index.", |
309 | 0 | function ); |
310 | |
|
311 | 0 | return( -1 ); |
312 | 0 | } |
313 | | #if defined( HAVE_DEBUG_OUTPUT ) |
314 | | if( libcnotify_verbose != 0 ) |
315 | | { |
316 | | libcnotify_printf( |
317 | | "%s: requested identifier\t: 0x%08" PRIx64 " (%" PRIu64 ").\n", |
318 | | function, |
319 | | identifier, |
320 | | identifier ); |
321 | | } |
322 | | #endif |
323 | 397k | if( libpff_index_check_if_node_block_first_read( |
324 | 397k | index, |
325 | 397k | node_block_tree, |
326 | 397k | node_offset, |
327 | 397k | identifier, |
328 | 397k | error ) != 1 ) |
329 | 363 | { |
330 | 363 | libcerror_error_set( |
331 | 363 | error, |
332 | 363 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
333 | 363 | LIBCERROR_RUNTIME_ERROR_GENERIC, |
334 | 363 | "%s: unable to check if first read of index node at offset: %" PRIi64 " (0x%08" PRIx64 ").", |
335 | 363 | function, |
336 | 363 | node_offset, |
337 | 363 | node_offset ); |
338 | | |
339 | 363 | goto on_error; |
340 | 363 | } |
341 | 396k | if( libpff_index_node_initialize( |
342 | 396k | &index_node, |
343 | 396k | error ) != 1 ) |
344 | 0 | { |
345 | 0 | libcerror_error_set( |
346 | 0 | error, |
347 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
348 | 0 | LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, |
349 | 0 | "%s: unable to create index node.", |
350 | 0 | function ); |
351 | |
|
352 | 0 | goto on_error; |
353 | 0 | } |
354 | 396k | if( libpff_index_node_read_file_io_handle( |
355 | 396k | index_node, |
356 | 396k | file_io_handle, |
357 | 396k | node_offset, |
358 | 396k | io_handle->file_type, |
359 | 396k | error ) != 1 ) |
360 | 428 | { |
361 | 428 | libcerror_error_set( |
362 | 428 | error, |
363 | 428 | LIBCERROR_ERROR_DOMAIN_IO, |
364 | 428 | LIBCERROR_IO_ERROR_READ_FAILED, |
365 | 428 | "%s: unable to read index node at offset: %" PRIi64 " (0x%08" PRIx64 ").", |
366 | 428 | function, |
367 | 428 | node_offset, |
368 | 428 | node_offset ); |
369 | | |
370 | 428 | goto on_error; |
371 | 428 | } |
372 | 396k | if( index->type != index_node->type ) |
373 | 100 | { |
374 | 100 | libcerror_error_set( |
375 | 100 | error, |
376 | 100 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
377 | 100 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
378 | 100 | "%s: index type mismatch (index: 0x%02" PRIx8 ", node: 0x%02" PRIx8 ").", |
379 | 100 | function, |
380 | 100 | index->type, |
381 | 100 | index_node->type ); |
382 | | |
383 | | /* TODO error tollerance */ |
384 | | |
385 | 100 | goto on_error; |
386 | 100 | } |
387 | 396k | if( index_node->level != LIBPFF_INDEX_NODE_LEVEL_LEAF ) |
388 | 177k | { |
389 | 177k | if( index_node->back_pointer != node_back_pointer ) |
390 | 178 | { |
391 | 178 | libcerror_error_set( |
392 | 178 | error, |
393 | 178 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
394 | 178 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
395 | 178 | "%s: back pointer mismatch (index entry: %" PRIu64 ", node: %" PRIu64 ").", |
396 | 178 | function, |
397 | 178 | node_back_pointer, |
398 | 178 | index_node->back_pointer ); |
399 | | |
400 | | /* TODO error tollerance */ |
401 | | |
402 | 178 | goto on_error; |
403 | 178 | } |
404 | 177k | } |
405 | 396k | for( entry_index = 0; |
406 | 2.89M | entry_index < index_node->number_of_entries; |
407 | 2.50M | entry_index++ ) |
408 | 2.80M | { |
409 | 2.80M | if( libpff_index_node_get_entry_data( |
410 | 2.80M | index_node, |
411 | 2.80M | entry_index, |
412 | 2.80M | &node_entry_data, |
413 | 2.80M | error ) != 1 ) |
414 | 0 | { |
415 | 0 | libcerror_error_set( |
416 | 0 | error, |
417 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
418 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
419 | 0 | "%s: unable to retrieve node entry: %" PRIu16 " data.", |
420 | 0 | function, |
421 | 0 | entry_index ); |
422 | |
|
423 | 0 | goto on_error; |
424 | 0 | } |
425 | 2.80M | if( node_entry_data == NULL ) |
426 | 0 | { |
427 | 0 | libcerror_error_set( |
428 | 0 | error, |
429 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
430 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, |
431 | 0 | "%s: missing node entry: %" PRIu16 " data.", |
432 | 0 | function, |
433 | 0 | entry_index ); |
434 | |
|
435 | 0 | goto on_error; |
436 | 0 | } |
437 | 2.80M | if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT ) |
438 | 2.10M | { |
439 | 2.10M | byte_stream_copy_to_uint32_little_endian( |
440 | 2.10M | ( (pff_index_node_branch_entry_32bit_t *) node_entry_data )->identifier, |
441 | 2.10M | entry_identifier ); |
442 | 2.10M | } |
443 | 699k | else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) |
444 | 699k | || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) ) |
445 | 699k | { |
446 | 699k | byte_stream_copy_to_uint64_little_endian( |
447 | 699k | ( (pff_index_node_branch_entry_64bit_t *) node_entry_data )->identifier, |
448 | 699k | entry_identifier ); |
449 | 699k | } |
450 | | #if defined( HAVE_DEBUG_OUTPUT ) |
451 | | if( libcnotify_verbose != 0 ) |
452 | | { |
453 | | libcnotify_printf( |
454 | | "%s: node entry: %" PRIu16 " identifier\t: 0x%08" PRIx64 " (%" PRIu64 ").\n", |
455 | | function, |
456 | | entry_index, |
457 | | entry_identifier, |
458 | | entry_identifier ); |
459 | | } |
460 | | #endif |
461 | | /* Ignore the upper 32-bit of descriptor identifiers |
462 | | */ |
463 | 2.80M | if( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR ) |
464 | 2.05M | { |
465 | 2.05M | entry_identifier &= 0xffffffffUL; |
466 | 2.05M | } |
467 | 2.80M | if( index_node->level != LIBPFF_INDEX_NODE_LEVEL_LEAF ) |
468 | 1.49M | { |
469 | 1.49M | if( ( entry_index == 0 ) |
470 | 1.49M | || ( identifier >= entry_identifier ) ) |
471 | 1.42M | { |
472 | 1.42M | if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT ) |
473 | 1.14M | { |
474 | 1.14M | byte_stream_copy_to_uint32_little_endian( |
475 | 1.14M | ( (pff_index_node_branch_entry_32bit_t *) node_entry_data )->file_offset, |
476 | 1.14M | sub_node_offset ); |
477 | | |
478 | 1.14M | byte_stream_copy_to_uint32_little_endian( |
479 | 1.14M | ( (pff_index_node_branch_entry_32bit_t *) node_entry_data )->back_pointer, |
480 | 1.14M | sub_node_back_pointer ); |
481 | 1.14M | } |
482 | 280k | else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) |
483 | 280k | || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) ) |
484 | 280k | { |
485 | 280k | byte_stream_copy_to_uint64_little_endian( |
486 | 280k | ( (pff_index_node_branch_entry_64bit_t *) node_entry_data )->file_offset, |
487 | 280k | sub_node_offset ); |
488 | | |
489 | 280k | byte_stream_copy_to_uint64_little_endian( |
490 | 280k | ( (pff_index_node_branch_entry_64bit_t *) node_entry_data )->back_pointer, |
491 | 280k | sub_node_back_pointer ); |
492 | 280k | } |
493 | 1.42M | } |
494 | 1.49M | } |
495 | 1.31M | else if( identifier == entry_identifier ) |
496 | 47.9k | { |
497 | 47.9k | *leaf_node = index_node; |
498 | 47.9k | *leaf_node_entry_index = entry_index; |
499 | | |
500 | 47.9k | result = 1; |
501 | 47.9k | } |
502 | | /* A branch node contains the identifier of its first sub node |
503 | | */ |
504 | 2.80M | if( identifier <= entry_identifier ) |
505 | 302k | { |
506 | 302k | break; |
507 | 302k | } |
508 | 2.80M | } |
509 | 396k | if( index_node->level != LIBPFF_INDEX_NODE_LEVEL_LEAF ) |
510 | 177k | { |
511 | 177k | if( sub_node_offset > (uint64_t) INT64_MAX ) |
512 | 139 | { |
513 | 139 | libcerror_error_set( |
514 | 139 | error, |
515 | 139 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
516 | 139 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
517 | 139 | "%s: invalid sub node offset value out of bounds.", |
518 | 139 | function ); |
519 | | |
520 | 139 | goto on_error; |
521 | 139 | } |
522 | 176k | result = libpff_index_get_leaf_node_from_node_by_identifier( |
523 | 176k | index, |
524 | 176k | io_handle, |
525 | 176k | file_io_handle, |
526 | 176k | node_block_tree, |
527 | 176k | sub_node_offset, |
528 | 176k | sub_node_back_pointer, |
529 | 176k | identifier, |
530 | 176k | leaf_node, |
531 | 176k | leaf_node_entry_index, |
532 | 176k | error ); |
533 | | |
534 | 176k | if( result == -1 ) |
535 | 1.00k | { |
536 | 1.00k | libcerror_error_set( |
537 | 1.00k | error, |
538 | 1.00k | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
539 | 1.00k | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
540 | 1.00k | "%s: unable to retrieve leaf node by identifier: 0x%08" PRIx64 " (%" PRIu64 ") from node at offset: %" PRIi64 " (0x%08" PRIx64 ").", |
541 | 1.00k | function, |
542 | 1.00k | identifier, |
543 | 1.00k | identifier, |
544 | 1.00k | node_offset, |
545 | 1.00k | node_offset ); |
546 | | |
547 | 1.00k | goto on_error; |
548 | 1.00k | } |
549 | 176k | } |
550 | 395k | if( ( index_node != NULL ) |
551 | 395k | && ( index_node != *leaf_node ) ) |
552 | 347k | { |
553 | 347k | if( libpff_index_node_free( |
554 | 347k | &index_node, |
555 | 347k | error ) != 1 ) |
556 | 0 | { |
557 | 0 | libcerror_error_set( |
558 | 0 | error, |
559 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
560 | 0 | LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, |
561 | 0 | "%s: unable to free index node.", |
562 | 0 | function ); |
563 | |
|
564 | 0 | goto on_error; |
565 | 0 | } |
566 | 347k | } |
567 | 395k | return( result ); |
568 | | |
569 | 2.21k | on_error: |
570 | 2.21k | if( index_node != NULL ) |
571 | 1.84k | { |
572 | 1.84k | libpff_index_node_free( |
573 | 1.84k | &index_node, |
574 | 1.84k | NULL ); |
575 | 1.84k | } |
576 | 2.21k | return( -1 ); |
577 | 395k | } |
578 | | |
579 | | /* Retrieves the value for the specific identifier |
580 | | * Returns 1 if successful, 0 if no value was found or -1 on error |
581 | | */ |
582 | | int libpff_index_get_value_by_identifier( |
583 | | libpff_index_t *index, |
584 | | libpff_io_handle_t *io_handle, |
585 | | libbfio_handle_t *file_io_handle, |
586 | | uint64_t identifier, |
587 | | libpff_index_value_t **index_value, |
588 | | libcerror_error_t **error ) |
589 | 220k | { |
590 | 220k | libpff_block_tree_t *node_block_tree = NULL; |
591 | 220k | libpff_index_node_t *leaf_node = NULL; |
592 | 220k | libpff_index_value_t *safe_index_value = NULL; |
593 | 220k | uint8_t *node_entry_data = NULL; |
594 | 220k | static char *function = "libpff_index_get_value_by_identifier"; |
595 | 220k | size_t index_node_size = 0; |
596 | 220k | uint16_t leaf_node_entry_index = 0; |
597 | 220k | int result = 0; |
598 | | |
599 | 220k | if( index == NULL ) |
600 | 0 | { |
601 | 0 | libcerror_error_set( |
602 | 0 | error, |
603 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
604 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
605 | 0 | "%s: invalid index.", |
606 | 0 | function ); |
607 | |
|
608 | 0 | return( -1 ); |
609 | 0 | } |
610 | 220k | if( io_handle == NULL ) |
611 | 0 | { |
612 | 0 | libcerror_error_set( |
613 | 0 | error, |
614 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
615 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
616 | 0 | "%s: invalid IO handle.", |
617 | 0 | function ); |
618 | |
|
619 | 0 | return( -1 ); |
620 | 0 | } |
621 | 220k | if( index_value == NULL ) |
622 | 0 | { |
623 | 0 | libcerror_error_set( |
624 | 0 | error, |
625 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
626 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
627 | 0 | "%s: invalid index value.", |
628 | 0 | function ); |
629 | |
|
630 | 0 | return( -1 ); |
631 | 0 | } |
632 | 220k | if( ( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT ) |
633 | 220k | || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) ) |
634 | 219k | { |
635 | 219k | index_node_size = 512; |
636 | 219k | } |
637 | 673 | else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) |
638 | 673 | { |
639 | 673 | index_node_size = 4096; |
640 | 673 | } |
641 | 220k | if( libpff_block_tree_initialize( |
642 | 220k | &node_block_tree, |
643 | 220k | io_handle->file_size, |
644 | 220k | index_node_size, |
645 | 220k | error ) != 1 ) |
646 | 19 | { |
647 | 19 | libcerror_error_set( |
648 | 19 | error, |
649 | 19 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
650 | 19 | LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, |
651 | 19 | "%s: unable to create index node block tree.", |
652 | 19 | function ); |
653 | | |
654 | 19 | goto on_error; |
655 | 19 | } |
656 | | #if defined( HAVE_DEBUG_OUTPUT ) |
657 | | if( libcnotify_verbose != 0 ) |
658 | | { |
659 | | libcnotify_printf( |
660 | | "%s: requested identifier\t\t: 0x%08" PRIx64 " (%" PRIu64 ").\n", |
661 | | function, |
662 | | identifier, |
663 | | identifier ); |
664 | | } |
665 | | #endif |
666 | 220k | result = libpff_index_get_leaf_node_from_node_by_identifier( |
667 | 220k | index, |
668 | 220k | io_handle, |
669 | 220k | file_io_handle, |
670 | 220k | node_block_tree, |
671 | 220k | index->root_node_offset, |
672 | 220k | index->root_node_back_pointer, |
673 | 220k | identifier, |
674 | 220k | &leaf_node, |
675 | 220k | &leaf_node_entry_index, |
676 | 220k | error ); |
677 | | |
678 | 220k | if( result == -1 ) |
679 | 1.20k | { |
680 | 1.20k | libcerror_error_set( |
681 | 1.20k | error, |
682 | 1.20k | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
683 | 1.20k | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
684 | 1.20k | "%s: unable to retrieve leaf node by identifier: 0x%08" PRIx64 " (%" PRIu64 ") from root node.", |
685 | 1.20k | function, |
686 | 1.20k | identifier, |
687 | 1.20k | identifier ); |
688 | | |
689 | 1.20k | goto on_error; |
690 | 1.20k | } |
691 | 219k | else if( result != 0 ) |
692 | 47.9k | { |
693 | 47.9k | if( libpff_index_node_get_entry_data( |
694 | 47.9k | leaf_node, |
695 | 47.9k | leaf_node_entry_index, |
696 | 47.9k | &node_entry_data, |
697 | 47.9k | error ) != 1 ) |
698 | 0 | { |
699 | 0 | libcerror_error_set( |
700 | 0 | error, |
701 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
702 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
703 | 0 | "%s: unable to retrieve node entry: %" PRIu16 " data.", |
704 | 0 | function, |
705 | 0 | leaf_node_entry_index ); |
706 | |
|
707 | 0 | goto on_error; |
708 | 0 | } |
709 | 47.9k | if( node_entry_data == NULL ) |
710 | 0 | { |
711 | 0 | libcerror_error_set( |
712 | 0 | error, |
713 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
714 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, |
715 | 0 | "%s: missing node entry: %" PRIu16 " data.", |
716 | 0 | function, |
717 | 0 | leaf_node_entry_index ); |
718 | |
|
719 | 0 | goto on_error; |
720 | 0 | } |
721 | 47.9k | if( libpff_index_value_initialize( |
722 | 47.9k | &safe_index_value, |
723 | 47.9k | error ) != 1 ) |
724 | 0 | { |
725 | 0 | libcerror_error_set( |
726 | 0 | error, |
727 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
728 | 0 | LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, |
729 | 0 | "%s: unable to create index value.", |
730 | 0 | function ); |
731 | |
|
732 | 0 | goto on_error; |
733 | 0 | } |
734 | 47.9k | if( libpff_index_value_read_data( |
735 | 47.9k | safe_index_value, |
736 | 47.9k | io_handle, |
737 | 47.9k | index->type, |
738 | 47.9k | node_entry_data, |
739 | 47.9k | (size_t) leaf_node->entry_size, |
740 | 47.9k | error ) != 1 ) |
741 | 230 | { |
742 | 230 | libcerror_error_set( |
743 | 230 | error, |
744 | 230 | LIBCERROR_ERROR_DOMAIN_IO, |
745 | 230 | LIBCERROR_IO_ERROR_READ_FAILED, |
746 | 230 | "%s: unable to read index value.", |
747 | 230 | function ); |
748 | | |
749 | 230 | goto on_error; |
750 | 230 | } |
751 | 47.6k | if( libpff_index_node_free( |
752 | 47.6k | &leaf_node, |
753 | 47.6k | error ) != 1 ) |
754 | 0 | { |
755 | 0 | libcerror_error_set( |
756 | 0 | error, |
757 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
758 | 0 | LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, |
759 | 0 | "%s: unable to free leaf node.", |
760 | 0 | function ); |
761 | |
|
762 | 0 | goto on_error; |
763 | 0 | } |
764 | 47.6k | } |
765 | 218k | if( libpff_block_tree_free( |
766 | 218k | &node_block_tree, |
767 | 218k | (int (*)(intptr_t **, libcerror_error_t **)) &libpff_block_descriptor_free, |
768 | 218k | error ) != 1 ) |
769 | 0 | { |
770 | 0 | libcerror_error_set( |
771 | 0 | error, |
772 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
773 | 0 | LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, |
774 | 0 | "%s: unable to free index node block tree.", |
775 | 0 | function ); |
776 | |
|
777 | 0 | goto on_error; |
778 | 0 | } |
779 | 218k | *index_value = safe_index_value; |
780 | | |
781 | 218k | return( result ); |
782 | | |
783 | 1.45k | on_error: |
784 | 1.45k | if( safe_index_value != NULL ) |
785 | 230 | { |
786 | 230 | libpff_index_value_free( |
787 | 230 | &safe_index_value, |
788 | 230 | NULL ); |
789 | 230 | } |
790 | 1.45k | if( leaf_node != NULL ) |
791 | 230 | { |
792 | 230 | libpff_index_node_free( |
793 | 230 | &leaf_node, |
794 | 230 | NULL ); |
795 | 230 | } |
796 | 1.45k | if( node_block_tree != NULL ) |
797 | 1.43k | { |
798 | 1.43k | libpff_block_tree_free( |
799 | 1.43k | &node_block_tree, |
800 | 1.43k | (int (*)(intptr_t **, libcerror_error_t **)) &libpff_block_descriptor_free, |
801 | 1.43k | NULL ); |
802 | 1.43k | } |
803 | 1.45k | return( -1 ); |
804 | 218k | } |
805 | | |