/src/libpff/libpff/libpff_local_descriptors.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Local descriptors 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_definitions.h" |
28 | | #include "libpff_io_handle.h" |
29 | | #include "libpff_libbfio.h" |
30 | | #include "libpff_libcerror.h" |
31 | | #include "libpff_libcnotify.h" |
32 | | #include "libpff_libfcache.h" |
33 | | #include "libpff_libfdata.h" |
34 | | #include "libpff_local_descriptors_node.h" |
35 | | #include "libpff_local_descriptor_value.h" |
36 | | #include "libpff_local_descriptors.h" |
37 | | #include "libpff_offsets_index.h" |
38 | | #include "libpff_unused.h" |
39 | | |
40 | | #include "pff_local_descriptors_node.h" |
41 | | |
42 | | /* Creates local descriptors |
43 | | * Make sure the value local_descriptors is referencing, is set to NULL |
44 | | * Returns 1 if successful or -1 on error |
45 | | */ |
46 | | int libpff_local_descriptors_initialize( |
47 | | libpff_local_descriptors_t **local_descriptors, |
48 | | libpff_io_handle_t *io_handle, |
49 | | libpff_offsets_index_t *offsets_index, |
50 | | uint32_t descriptor_identifier, |
51 | | uint64_t root_node_data_identifier, |
52 | | uint8_t recovered, |
53 | | libcerror_error_t **error ) |
54 | 5.83k | { |
55 | 5.83k | static char *function = "libpff_local_descriptors_initialize"; |
56 | | |
57 | 5.83k | if( local_descriptors == 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 local descriptors.", |
64 | 0 | function ); |
65 | |
|
66 | 0 | return( -1 ); |
67 | 0 | } |
68 | 5.83k | if( *local_descriptors != 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 local descriptors value already set.", |
75 | 0 | function ); |
76 | |
|
77 | 0 | return( -1 ); |
78 | 0 | } |
79 | 5.83k | if( io_handle == NULL ) |
80 | 0 | { |
81 | 0 | libcerror_error_set( |
82 | 0 | error, |
83 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
84 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
85 | 0 | "%s: invalid IO handle.", |
86 | 0 | function ); |
87 | |
|
88 | 0 | return( -1 ); |
89 | 0 | } |
90 | 5.83k | if( offsets_index == NULL ) |
91 | 0 | { |
92 | 0 | libcerror_error_set( |
93 | 0 | error, |
94 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
95 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
96 | 0 | "%s: invalid offsets index.", |
97 | 0 | function ); |
98 | |
|
99 | 0 | return( -1 ); |
100 | 0 | } |
101 | 5.83k | *local_descriptors = memory_allocate_structure( |
102 | 5.83k | libpff_local_descriptors_t ); |
103 | | |
104 | 5.83k | if( *local_descriptors == NULL ) |
105 | 0 | { |
106 | 0 | libcerror_error_set( |
107 | 0 | error, |
108 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
109 | 0 | LIBCERROR_MEMORY_ERROR_INSUFFICIENT, |
110 | 0 | "%s: unable to create local descriptors.", |
111 | 0 | function ); |
112 | |
|
113 | 0 | goto on_error; |
114 | 0 | } |
115 | 5.83k | if( memory_set( |
116 | 5.83k | *local_descriptors, |
117 | 5.83k | 0, |
118 | 5.83k | sizeof( libpff_local_descriptors_t ) ) == NULL ) |
119 | 0 | { |
120 | 0 | libcerror_error_set( |
121 | 0 | error, |
122 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
123 | 0 | LIBCERROR_MEMORY_ERROR_SET_FAILED, |
124 | 0 | "%s: unable to clear local descriptors.", |
125 | 0 | function ); |
126 | |
|
127 | 0 | memory_free( |
128 | 0 | *local_descriptors ); |
129 | |
|
130 | 0 | *local_descriptors = NULL; |
131 | |
|
132 | 0 | return( -1 ); |
133 | 0 | } |
134 | 5.83k | if( libfcache_cache_initialize( |
135 | 5.83k | &( ( *local_descriptors )->local_descriptors_nodes_cache ), |
136 | 5.83k | LIBPFF_MAXIMUM_CACHE_ENTRIES_LOCAL_DESCRIPTORS_NODES, |
137 | 5.83k | error ) != 1 ) |
138 | 0 | { |
139 | 0 | libcerror_error_set( |
140 | 0 | error, |
141 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
142 | 0 | LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, |
143 | 0 | "%s: unable to create local descriptors nodes cache.", |
144 | 0 | function ); |
145 | |
|
146 | 0 | goto on_error; |
147 | 0 | } |
148 | 5.83k | ( *local_descriptors )->io_handle = io_handle; |
149 | 5.83k | ( *local_descriptors )->offsets_index = offsets_index; |
150 | 5.83k | ( *local_descriptors )->descriptor_identifier = descriptor_identifier; |
151 | 5.83k | ( *local_descriptors )->root_node_data_identifier = root_node_data_identifier; |
152 | 5.83k | ( *local_descriptors )->recovered = recovered; |
153 | | |
154 | 5.83k | return( 1 ); |
155 | | |
156 | 0 | on_error: |
157 | 0 | if( *local_descriptors != NULL ) |
158 | 0 | { |
159 | 0 | memory_free( |
160 | 0 | *local_descriptors ); |
161 | |
|
162 | 0 | *local_descriptors = NULL; |
163 | 0 | } |
164 | 0 | return( -1 ); |
165 | 5.83k | } |
166 | | |
167 | | /* Frees local descriptors |
168 | | * Returns 1 if successful or -1 on error |
169 | | */ |
170 | | int libpff_local_descriptors_free( |
171 | | libpff_local_descriptors_t **local_descriptors, |
172 | | libcerror_error_t **error ) |
173 | 5.83k | { |
174 | 5.83k | static char *function = "libpff_local_descriptors_free"; |
175 | 5.83k | int result = 1; |
176 | | |
177 | 5.83k | if( local_descriptors == 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 local descriptors.", |
184 | 0 | function ); |
185 | |
|
186 | 0 | return( -1 ); |
187 | 0 | } |
188 | 5.83k | if( *local_descriptors != NULL ) |
189 | 5.83k | { |
190 | 5.83k | if( libfcache_cache_free( |
191 | 5.83k | &( ( *local_descriptors )->local_descriptors_nodes_cache ), |
192 | 5.83k | error ) != 1 ) |
193 | 0 | { |
194 | 0 | libcerror_error_set( |
195 | 0 | error, |
196 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
197 | 0 | LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, |
198 | 0 | "%s: unable to free local descriptors nodes cache.", |
199 | 0 | function ); |
200 | |
|
201 | 0 | result = -1; |
202 | 0 | } |
203 | 5.83k | memory_free( |
204 | 5.83k | *local_descriptors ); |
205 | | |
206 | 5.83k | *local_descriptors = NULL; |
207 | 5.83k | } |
208 | 5.83k | return( result ); |
209 | 5.83k | } |
210 | | |
211 | | /* Clones the local descriptors |
212 | | * Returns 1 if successful or -1 on error |
213 | | */ |
214 | | int libpff_local_descriptors_clone( |
215 | | libpff_local_descriptors_t **destination_local_descriptors, |
216 | | libpff_local_descriptors_t *source_local_descriptors, |
217 | | libcerror_error_t **error ) |
218 | 0 | { |
219 | 0 | static char *function = "libpff_local_descriptors_clone"; |
220 | |
|
221 | 0 | if( destination_local_descriptors == NULL ) |
222 | 0 | { |
223 | 0 | libcerror_error_set( |
224 | 0 | error, |
225 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
226 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
227 | 0 | "%s: invalid destination local descriptors.", |
228 | 0 | function ); |
229 | |
|
230 | 0 | return( -1 ); |
231 | 0 | } |
232 | 0 | if( *destination_local_descriptors != NULL ) |
233 | 0 | { |
234 | 0 | libcerror_error_set( |
235 | 0 | error, |
236 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
237 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, |
238 | 0 | "%s: invalid destination local descriptors already set.", |
239 | 0 | function ); |
240 | |
|
241 | 0 | return( -1 ); |
242 | 0 | } |
243 | 0 | if( source_local_descriptors == NULL ) |
244 | 0 | { |
245 | 0 | *destination_local_descriptors = NULL; |
246 | |
|
247 | 0 | return( 1 ); |
248 | 0 | } |
249 | 0 | if( libpff_local_descriptors_initialize( |
250 | 0 | destination_local_descriptors, |
251 | 0 | source_local_descriptors->io_handle, |
252 | 0 | source_local_descriptors->offsets_index, |
253 | 0 | source_local_descriptors->descriptor_identifier, |
254 | 0 | source_local_descriptors->root_node_data_identifier, |
255 | 0 | source_local_descriptors->recovered, |
256 | 0 | error ) != 1 ) |
257 | 0 | { |
258 | 0 | libcerror_error_set( |
259 | 0 | error, |
260 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
261 | 0 | LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, |
262 | 0 | "%s: unable to create destination local descriptors.", |
263 | 0 | function ); |
264 | |
|
265 | 0 | return( -1 ); |
266 | 0 | } |
267 | 0 | return( 1 ); |
268 | 0 | } |
269 | | |
270 | | /* Retrieves the leaf node from an local descriptors node for the specific identifier |
271 | | * Returns 1 if successful, 0 if no leaf node was found or -1 on error |
272 | | */ |
273 | | int libpff_local_descriptors_get_leaf_node_from_node_by_identifier( |
274 | | libpff_local_descriptors_t *local_descriptors, |
275 | | libpff_io_handle_t *io_handle, |
276 | | libbfio_handle_t *file_io_handle, |
277 | | uint64_t identifier, |
278 | | uint64_t data_identifier, |
279 | | libpff_local_descriptors_node_t **leaf_node, |
280 | | uint16_t *leaf_node_entry_index, |
281 | | libcerror_error_t **error ) |
282 | 13.6k | { |
283 | 13.6k | libpff_index_value_t *offsets_index_value = NULL; |
284 | 13.6k | libpff_local_descriptors_node_t *local_descriptors_node = NULL; |
285 | 13.6k | uint8_t *node_entry_data = NULL; |
286 | 13.6k | static char *function = "libpff_local_descriptors_get_leaf_node_from_node_by_identifier"; |
287 | 13.6k | uint64_t entry_identifier = 0; |
288 | 13.6k | uint64_t sub_node_identifier = 0; |
289 | 13.6k | uint16_t entry_index = 0; |
290 | 13.6k | int result = 0; |
291 | | |
292 | 13.6k | if( local_descriptors == NULL ) |
293 | 0 | { |
294 | 0 | libcerror_error_set( |
295 | 0 | error, |
296 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
297 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
298 | 0 | "%s: invalid local descriptors.", |
299 | 0 | function ); |
300 | |
|
301 | 0 | return( -1 ); |
302 | 0 | } |
303 | 13.6k | if( io_handle == NULL ) |
304 | 0 | { |
305 | 0 | libcerror_error_set( |
306 | 0 | error, |
307 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
308 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
309 | 0 | "%s: invalid IO handle.", |
310 | 0 | function ); |
311 | |
|
312 | 0 | return( -1 ); |
313 | 0 | } |
314 | 13.6k | if( leaf_node == NULL ) |
315 | 0 | { |
316 | 0 | libcerror_error_set( |
317 | 0 | error, |
318 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
319 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
320 | 0 | "%s: invalid leaf node.", |
321 | 0 | function ); |
322 | |
|
323 | 0 | return( -1 ); |
324 | 0 | } |
325 | 13.6k | if( leaf_node_entry_index == NULL ) |
326 | 0 | { |
327 | 0 | libcerror_error_set( |
328 | 0 | error, |
329 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
330 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
331 | 0 | "%s: invalid leaf node entry index.", |
332 | 0 | function ); |
333 | |
|
334 | 0 | return( -1 ); |
335 | 0 | } |
336 | | #if defined( HAVE_DEBUG_OUTPUT ) |
337 | | if( libcnotify_verbose != 0 ) |
338 | | { |
339 | | libcnotify_printf( |
340 | | "%s: requested identifier\t: 0x%08" PRIx64 " (%" PRIu64 ").\n", |
341 | | function, |
342 | | data_identifier, |
343 | | data_identifier ); |
344 | | } |
345 | | #endif |
346 | | /* TODO handle multiple recovered offsets index values */ |
347 | 13.6k | result = libpff_offsets_index_get_index_value_by_identifier( |
348 | 13.6k | local_descriptors->offsets_index, |
349 | 13.6k | io_handle, |
350 | 13.6k | file_io_handle, |
351 | 13.6k | data_identifier, |
352 | 13.6k | local_descriptors->recovered, |
353 | 13.6k | 0, |
354 | 13.6k | &offsets_index_value, |
355 | 13.6k | error ); |
356 | | |
357 | 13.6k | if( result == -1 ) |
358 | 7 | { |
359 | 7 | libcerror_error_set( |
360 | 7 | error, |
361 | 7 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
362 | 7 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
363 | 7 | "%s: unable to find offsets index value: 0x%08" PRIx64 " (%" PRIu64 ").", |
364 | 7 | function, |
365 | 7 | data_identifier, |
366 | 7 | data_identifier ); |
367 | | |
368 | 7 | goto on_error; |
369 | 7 | } |
370 | 13.6k | else if( result == 0 ) |
371 | 3.32k | { |
372 | 3.32k | return( 0 ); |
373 | 3.32k | } |
374 | 10.2k | if( offsets_index_value == NULL ) |
375 | 0 | { |
376 | 0 | libcerror_error_set( |
377 | 0 | error, |
378 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
379 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, |
380 | 0 | "%s: missing offsets index value: 0x%08" PRIx64 " (%" PRIu64 ").", |
381 | 0 | function, |
382 | 0 | data_identifier, |
383 | 0 | data_identifier ); |
384 | |
|
385 | 0 | goto on_error; |
386 | 0 | } |
387 | | #if defined( HAVE_DEBUG_OUTPUT ) |
388 | | if( libcnotify_verbose != 0 ) |
389 | | { |
390 | | libcnotify_printf( |
391 | | "%s: local descriptors node: identifier: %" PRIu64 " (%s) at offset: 0x%08" PRIx64 " of size: %" PRIu32 "\n", |
392 | | function, |
393 | | offsets_index_value->identifier, |
394 | | ( ( offsets_index_value->identifier & LIBPFF_OFFSET_INDEX_IDENTIFIER_FLAG_INTERNAL ) ? "internal" : "external" ), |
395 | | offsets_index_value->file_offset, |
396 | | offsets_index_value->data_size ); |
397 | | } |
398 | | #endif |
399 | 10.2k | if( libpff_local_descriptors_node_initialize( |
400 | 10.2k | &local_descriptors_node, |
401 | 10.2k | error ) != 1 ) |
402 | 0 | { |
403 | 0 | libcerror_error_set( |
404 | 0 | error, |
405 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
406 | 0 | LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, |
407 | 0 | "%s: unable to create local descriptors node.", |
408 | 0 | function ); |
409 | |
|
410 | 0 | goto on_error; |
411 | 0 | } |
412 | 10.2k | if( libpff_local_descriptors_node_read_file_io_handle( |
413 | 10.2k | local_descriptors_node, |
414 | 10.2k | io_handle, |
415 | 10.2k | file_io_handle, |
416 | 10.2k | local_descriptors->descriptor_identifier, |
417 | 10.2k | data_identifier, |
418 | 10.2k | offsets_index_value->file_offset, |
419 | 10.2k | offsets_index_value->data_size, |
420 | 10.2k | error ) != 1 ) |
421 | 299 | { |
422 | 299 | libcerror_error_set( |
423 | 299 | error, |
424 | 299 | LIBCERROR_ERROR_DOMAIN_IO, |
425 | 299 | LIBCERROR_IO_ERROR_READ_FAILED, |
426 | 299 | "%s: unable to read local descriptors node at offset: %" PRIi64 " (0x%08" PRIx64 ").", |
427 | 299 | function, |
428 | 299 | offsets_index_value->file_offset, |
429 | 299 | offsets_index_value->file_offset ); |
430 | | |
431 | 299 | goto on_error; |
432 | 299 | } |
433 | 9.98k | for( entry_index = 0; |
434 | 11.3k | entry_index < local_descriptors_node->number_of_entries; |
435 | 9.98k | entry_index++ ) |
436 | 11.2k | { |
437 | 11.2k | if( libpff_local_descriptors_node_get_entry_data( |
438 | 11.2k | local_descriptors_node, |
439 | 11.2k | entry_index, |
440 | 11.2k | &node_entry_data, |
441 | 11.2k | error ) != 1 ) |
442 | 0 | { |
443 | 0 | libcerror_error_set( |
444 | 0 | error, |
445 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
446 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
447 | 0 | "%s: unable to retrieve node entry: %" PRIu16 " data.", |
448 | 0 | function, |
449 | 0 | entry_index ); |
450 | |
|
451 | 0 | goto on_error; |
452 | 0 | } |
453 | 11.2k | if( node_entry_data == NULL ) |
454 | 0 | { |
455 | 0 | libcerror_error_set( |
456 | 0 | error, |
457 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
458 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, |
459 | 0 | "%s: missing node entry: %" PRIu16 " data.", |
460 | 0 | function, |
461 | 0 | entry_index ); |
462 | |
|
463 | 0 | goto on_error; |
464 | 0 | } |
465 | 11.2k | if( local_descriptors->io_handle->file_type == LIBPFF_FILE_TYPE_32BIT ) |
466 | 236 | { |
467 | 236 | byte_stream_copy_to_uint32_little_endian( |
468 | 236 | ( (pff_local_descriptor_branch_node_entry_type_32bit_t *) node_entry_data )->identifier, |
469 | 236 | entry_identifier ); |
470 | 236 | } |
471 | 11.0k | else if( ( local_descriptors->io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) |
472 | 11.0k | || ( local_descriptors->io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) ) |
473 | 11.0k | { |
474 | 11.0k | byte_stream_copy_to_uint64_little_endian( |
475 | 11.0k | ( (pff_local_descriptor_branch_node_entry_type_64bit_t *) node_entry_data )->identifier, |
476 | 11.0k | entry_identifier ); |
477 | 11.0k | } |
478 | | /* Ignore the upper 32-bit of local descriptor identifiers |
479 | | */ |
480 | 11.2k | entry_identifier &= 0xffffffffUL; |
481 | | |
482 | 11.2k | if( local_descriptors_node->level != LIBPFF_LOCAL_DESCRIPTOR_NODE_LEVEL_LEAF ) |
483 | 236 | { |
484 | 236 | if( ( entry_index == 0 ) |
485 | 236 | || ( identifier >= entry_identifier ) ) |
486 | 191 | { |
487 | 191 | if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT ) |
488 | 191 | { |
489 | 191 | byte_stream_copy_to_uint32_little_endian( |
490 | 191 | ( (pff_local_descriptor_branch_node_entry_type_32bit_t *) node_entry_data )->sub_node_identifier, |
491 | 191 | sub_node_identifier ); |
492 | 191 | } |
493 | 0 | else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) |
494 | 0 | || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) ) |
495 | 0 | { |
496 | 0 | byte_stream_copy_to_uint64_little_endian( |
497 | 0 | ( (pff_local_descriptor_branch_node_entry_type_64bit_t *) node_entry_data )->sub_node_identifier, |
498 | 0 | sub_node_identifier ); |
499 | 0 | } |
500 | 191 | } |
501 | 236 | } |
502 | 11.0k | else if( identifier == entry_identifier ) |
503 | 9.57k | { |
504 | 9.57k | *leaf_node = local_descriptors_node; |
505 | 9.57k | *leaf_node_entry_index = entry_index; |
506 | | |
507 | 9.57k | result = 1; |
508 | 9.57k | } |
509 | | /* A branch node contains the identifier of its first sub node |
510 | | */ |
511 | 11.2k | if( identifier <= entry_identifier ) |
512 | 9.84k | { |
513 | 9.84k | break; |
514 | 9.84k | } |
515 | 11.2k | } |
516 | 9.98k | if( local_descriptors_node->level != LIBPFF_INDEX_NODE_LEVEL_LEAF ) |
517 | 97 | { |
518 | 97 | result = libpff_local_descriptors_get_leaf_node_from_node_by_identifier( |
519 | 97 | local_descriptors, |
520 | 97 | io_handle, |
521 | 97 | file_io_handle, |
522 | 97 | identifier, |
523 | 97 | sub_node_identifier, |
524 | 97 | leaf_node, |
525 | 97 | leaf_node_entry_index, |
526 | 97 | error ); |
527 | | |
528 | 97 | if( result == -1 ) |
529 | 10 | { |
530 | 10 | libcerror_error_set( |
531 | 10 | error, |
532 | 10 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
533 | 10 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
534 | 10 | "%s: unable to retrieve leaf node by identifier: 0x%08" PRIx64 " (%" PRIu64 ") from node at offset: %" PRIi64 " (0x%08" PRIx64 ").", |
535 | 10 | function, |
536 | 10 | identifier, |
537 | 10 | identifier, |
538 | 10 | offsets_index_value->file_offset, |
539 | 10 | offsets_index_value->file_offset ); |
540 | | |
541 | 10 | goto on_error; |
542 | 10 | } |
543 | 97 | } |
544 | 9.97k | if( ( local_descriptors_node != NULL ) |
545 | 9.97k | && ( local_descriptors_node != *leaf_node ) ) |
546 | 396 | { |
547 | 396 | if( libpff_local_descriptors_node_free( |
548 | 396 | &local_descriptors_node, |
549 | 396 | error ) != 1 ) |
550 | 0 | { |
551 | 0 | libcerror_error_set( |
552 | 0 | error, |
553 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
554 | 0 | LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, |
555 | 0 | "%s: unable to free local descriptors node.", |
556 | 0 | function ); |
557 | |
|
558 | 0 | goto on_error; |
559 | 0 | } |
560 | 396 | } |
561 | 9.97k | if( libpff_index_value_free( |
562 | 9.97k | &offsets_index_value, |
563 | 9.97k | error ) != 1 ) |
564 | 0 | { |
565 | 0 | libcerror_error_set( |
566 | 0 | error, |
567 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
568 | 0 | LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, |
569 | 0 | "%s: unable to free offsets index value.", |
570 | 0 | function ); |
571 | |
|
572 | 0 | goto on_error; |
573 | 0 | } |
574 | 9.97k | return( result ); |
575 | | |
576 | 316 | on_error: |
577 | 316 | if( local_descriptors_node != NULL ) |
578 | 309 | { |
579 | 309 | libpff_local_descriptors_node_free( |
580 | 309 | &local_descriptors_node, |
581 | 309 | NULL ); |
582 | 309 | } |
583 | 316 | if( offsets_index_value != NULL ) |
584 | 309 | { |
585 | 309 | libpff_index_value_free( |
586 | 309 | &offsets_index_value, |
587 | 309 | NULL ); |
588 | 309 | } |
589 | 316 | return( -1 ); |
590 | 9.97k | } |
591 | | |
592 | | /* Retrieves the value for the specific identifier |
593 | | * Returns 1 if successful, 0 if no value was found or -1 on error |
594 | | */ |
595 | | int libpff_local_descriptors_get_value_by_identifier( |
596 | | libpff_local_descriptors_t *local_descriptors, |
597 | | libpff_io_handle_t *io_handle, |
598 | | libbfio_handle_t *file_io_handle, |
599 | | uint64_t identifier, |
600 | | libpff_local_descriptor_value_t **local_descriptor_value, |
601 | | libcerror_error_t **error ) |
602 | 13.5k | { |
603 | 13.5k | libpff_local_descriptor_value_t *safe_local_descriptor_value = NULL; |
604 | 13.5k | libpff_local_descriptors_node_t *leaf_node = NULL; |
605 | 13.5k | uint8_t *node_entry_data = NULL; |
606 | 13.5k | static char *function = "libpff_local_descriptors_get_value_by_identifier"; |
607 | 13.5k | uint16_t leaf_node_entry_index = 0; |
608 | 13.5k | int result = 0; |
609 | | |
610 | 13.5k | if( local_descriptors == 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 local descriptors.", |
617 | 0 | function ); |
618 | |
|
619 | 0 | return( -1 ); |
620 | 0 | } |
621 | 13.5k | if( local_descriptor_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 local descriptor value.", |
628 | 0 | function ); |
629 | |
|
630 | 0 | return( -1 ); |
631 | 0 | } |
632 | | #if defined( HAVE_DEBUG_OUTPUT ) |
633 | | if( libcnotify_verbose != 0 ) |
634 | | { |
635 | | libcnotify_printf( |
636 | | "%s: requested identifier\t\t: 0x%08" PRIx64 " (%" PRIu64 ").\n", |
637 | | function, |
638 | | identifier, |
639 | | identifier ); |
640 | | } |
641 | | #endif |
642 | 13.5k | result = libpff_local_descriptors_get_leaf_node_from_node_by_identifier( |
643 | 13.5k | local_descriptors, |
644 | 13.5k | io_handle, |
645 | 13.5k | file_io_handle, |
646 | 13.5k | identifier, |
647 | 13.5k | local_descriptors->root_node_data_identifier, |
648 | 13.5k | &leaf_node, |
649 | 13.5k | &leaf_node_entry_index, |
650 | 13.5k | error ); |
651 | | |
652 | 13.5k | if( result == -1 ) |
653 | 306 | { |
654 | 306 | libcerror_error_set( |
655 | 306 | error, |
656 | 306 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
657 | 306 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
658 | 306 | "%s: unable to retrieve leaf node by identifier: 0x%08" PRIx64 " (%" PRIu64 ") from root node.", |
659 | 306 | function, |
660 | 306 | identifier, |
661 | 306 | identifier ); |
662 | | |
663 | 306 | goto on_error; |
664 | 306 | } |
665 | 13.2k | else if( result != 0 ) |
666 | 9.88k | { |
667 | 9.88k | if( libpff_local_descriptors_node_get_entry_data( |
668 | 9.88k | leaf_node, |
669 | 9.88k | leaf_node_entry_index, |
670 | 9.88k | &node_entry_data, |
671 | 9.88k | error ) != 1 ) |
672 | 309 | { |
673 | 309 | libcerror_error_set( |
674 | 309 | error, |
675 | 309 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
676 | 309 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
677 | 309 | "%s: unable to retrieve node entry: %" PRIu16 " data.", |
678 | 309 | function, |
679 | 309 | leaf_node_entry_index ); |
680 | | |
681 | 309 | goto on_error; |
682 | 309 | } |
683 | 9.57k | if( node_entry_data == NULL ) |
684 | 0 | { |
685 | 0 | libcerror_error_set( |
686 | 0 | error, |
687 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
688 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, |
689 | 0 | "%s: missing node entry: %" PRIu16 " data.", |
690 | 0 | function, |
691 | 0 | leaf_node_entry_index ); |
692 | |
|
693 | 0 | goto on_error; |
694 | 0 | } |
695 | 9.57k | if( libpff_local_descriptor_value_initialize( |
696 | 9.57k | &safe_local_descriptor_value, |
697 | 9.57k | error ) != 1 ) |
698 | 0 | { |
699 | 0 | libcerror_error_set( |
700 | 0 | error, |
701 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
702 | 0 | LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, |
703 | 0 | "%s: unable to create local descriptor value.", |
704 | 0 | function ); |
705 | |
|
706 | 0 | goto on_error; |
707 | 0 | } |
708 | 9.57k | if( libpff_local_descriptor_value_read_data( |
709 | 9.57k | safe_local_descriptor_value, |
710 | 9.57k | io_handle, |
711 | 9.57k | node_entry_data, |
712 | 9.57k | (size_t) leaf_node->entry_size, |
713 | 9.57k | error ) != 1 ) |
714 | 0 | { |
715 | 0 | libcerror_error_set( |
716 | 0 | error, |
717 | 0 | LIBCERROR_ERROR_DOMAIN_IO, |
718 | 0 | LIBCERROR_IO_ERROR_READ_FAILED, |
719 | 0 | "%s: unable to read local descriptor value.", |
720 | 0 | function ); |
721 | |
|
722 | 0 | goto on_error; |
723 | 0 | } |
724 | 9.57k | if( libpff_local_descriptors_node_free( |
725 | 9.57k | &leaf_node, |
726 | 9.57k | error ) != 1 ) |
727 | 0 | { |
728 | 0 | libcerror_error_set( |
729 | 0 | error, |
730 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
731 | 0 | LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, |
732 | 0 | "%s: unable to free leaf node.", |
733 | 0 | function ); |
734 | |
|
735 | 0 | goto on_error; |
736 | 0 | } |
737 | 9.57k | } |
738 | 12.9k | *local_descriptor_value = safe_local_descriptor_value; |
739 | | |
740 | 12.9k | return( result ); |
741 | | |
742 | 615 | on_error: |
743 | 615 | if( safe_local_descriptor_value != NULL ) |
744 | 0 | { |
745 | 0 | libpff_local_descriptor_value_free( |
746 | 0 | &safe_local_descriptor_value, |
747 | 0 | NULL ); |
748 | 0 | } |
749 | 615 | if( leaf_node != NULL ) |
750 | 0 | { |
751 | 0 | libpff_local_descriptors_node_free( |
752 | 0 | &leaf_node, |
753 | 0 | NULL ); |
754 | 0 | } |
755 | 615 | return( -1 ); |
756 | 13.5k | } |
757 | | |