1 /*
2 * Local descriptor node functions
3 *
4 * Copyright (C) 2008-2018, Joachim Metz <joachim.metz@gmail.com>
5 *
6 * Refer to AUTHORS for acknowledgements.
7 *
8 * This software 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 software 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 software. If not, see <http://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_data_block.h"
28 #include "libpff_definitions.h"
29 #include "libpff_io_handle.h"
30 #include "libpff_libbfio.h"
31 #include "libpff_libcerror.h"
32 #include "libpff_libcnotify.h"
33 #include "libpff_libfmapi.h"
34 #include "libpff_local_descriptor_node.h"
35 #include "libpff_unused.h"
36
37 #include "pff_local_descriptor_node.h"
38
39 /* Creates a local descriptor node
40 * Make sure the value local_descriptor_node is referencing, is set to NULL
41 * Returns 1 if successful or -1 on error
42 */
libpff_local_descriptor_node_initialize(libpff_local_descriptor_node_t ** local_descriptor_node,libcerror_error_t ** error)43 int libpff_local_descriptor_node_initialize(
44 libpff_local_descriptor_node_t **local_descriptor_node,
45 libcerror_error_t **error )
46 {
47 static char *function = "libpff_local_descriptor_node_initialize";
48
49 if( local_descriptor_node == NULL )
50 {
51 libcerror_error_set(
52 error,
53 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
54 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
55 "%s: invalid local descriptor node.",
56 function );
57
58 return( -1 );
59 }
60 if( *local_descriptor_node != NULL )
61 {
62 libcerror_error_set(
63 error,
64 LIBCERROR_ERROR_DOMAIN_RUNTIME,
65 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
66 "%s: invalid local descriptor node value already set.",
67 function );
68
69 return( -1 );
70 }
71 *local_descriptor_node = memory_allocate_structure(
72 libpff_local_descriptor_node_t );
73
74 if( *local_descriptor_node == NULL )
75 {
76 libcerror_error_set(
77 error,
78 LIBCERROR_ERROR_DOMAIN_MEMORY,
79 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
80 "%s: unable to create local descriptor node.",
81 function );
82
83 goto on_error;
84 }
85 if( memory_set(
86 *local_descriptor_node,
87 0,
88 sizeof( libpff_local_descriptor_node_t ) ) == NULL )
89 {
90 libcerror_error_set(
91 error,
92 LIBCERROR_ERROR_DOMAIN_MEMORY,
93 LIBCERROR_MEMORY_ERROR_SET_FAILED,
94 "%s: unable to clear local descriptor node.",
95 function );
96
97 goto on_error;
98 }
99 return( 1 );
100
101 on_error:
102 if( *local_descriptor_node != NULL )
103 {
104 memory_free(
105 *local_descriptor_node );
106
107 *local_descriptor_node = NULL;
108 }
109 return( -1 );
110 }
111
112 /* Frees a local descriptor node
113 * Returns 1 if successful or -1 on error
114 */
libpff_local_descriptor_node_free(libpff_local_descriptor_node_t ** local_descriptor_node,libcerror_error_t ** error)115 int libpff_local_descriptor_node_free(
116 libpff_local_descriptor_node_t **local_descriptor_node,
117 libcerror_error_t **error )
118 {
119 static char *function = "libpff_local_descriptor_node_free";
120
121 if( local_descriptor_node == NULL )
122 {
123 libcerror_error_set(
124 error,
125 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
126 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
127 "%s: invalid local descriptor node.",
128 function );
129
130 return( -1 );
131 }
132 if( *local_descriptor_node != NULL )
133 {
134 if( ( *local_descriptor_node )->entries_data != NULL )
135 {
136 memory_free(
137 ( *local_descriptor_node )->entries_data );
138 }
139 memory_free(
140 *local_descriptor_node );
141
142 *local_descriptor_node = NULL;
143 }
144 return( 1 );
145 }
146
147 /* Retrieves the data of a specific entry
148 * Returns 1 if successful or -1 on error
149 */
libpff_local_descriptor_node_get_entry_data(libpff_local_descriptor_node_t * local_descriptor_node,uint16_t entry_index,uint8_t ** entry_data,libcerror_error_t ** error)150 int libpff_local_descriptor_node_get_entry_data(
151 libpff_local_descriptor_node_t *local_descriptor_node,
152 uint16_t entry_index,
153 uint8_t **entry_data,
154 libcerror_error_t **error )
155 {
156 static char *function = "libpff_local_descriptor_node_get_entry_data";
157 size_t entry_offset = 0;
158
159 if( local_descriptor_node == NULL )
160 {
161 libcerror_error_set(
162 error,
163 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
164 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
165 "%s: invalid local descriptor node.",
166 function );
167
168 return( -1 );
169 }
170 if( local_descriptor_node->entries_data == NULL )
171 {
172 libcerror_error_set(
173 error,
174 LIBCERROR_ERROR_DOMAIN_RUNTIME,
175 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
176 "%s: invalid local descriptor node - missing entries data.",
177 function );
178
179 return( -1 );
180 }
181 if( entry_data == NULL )
182 {
183 libcerror_error_set(
184 error,
185 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
186 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
187 "%s: invalid entry data.",
188 function );
189
190 return( -1 );
191 }
192 entry_offset = (size_t) ( local_descriptor_node->entry_size * entry_index );
193
194 if( entry_offset > local_descriptor_node->entries_data_size )
195 {
196 libcerror_error_set(
197 error,
198 LIBCERROR_ERROR_DOMAIN_RUNTIME,
199 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
200 "%s: entry index value exceeds maximum.",
201 function );
202
203 return( -1 );
204 }
205 *entry_data = &( local_descriptor_node->entries_data[ entry_offset ] );
206
207 return( 1 );
208 }
209
210 /* Retrieves the identifier of a specific entry
211 * Returns 1 if successful or -1 on error
212 */
libpff_local_descriptor_node_get_entry_identifier(libpff_local_descriptor_node_t * local_descriptor_node,libpff_io_handle_t * io_handle,uint16_t entry_index,uint64_t * entry_identifier,libcerror_error_t ** error)213 int libpff_local_descriptor_node_get_entry_identifier(
214 libpff_local_descriptor_node_t *local_descriptor_node,
215 libpff_io_handle_t *io_handle,
216 uint16_t entry_index,
217 uint64_t *entry_identifier,
218 libcerror_error_t **error )
219 {
220 uint8_t *node_entry_data = NULL;
221 static char *function = "libpff_local_descriptor_node_get_entry_identifier";
222 size_t entry_offset = 0;
223
224 if( local_descriptor_node == NULL )
225 {
226 libcerror_error_set(
227 error,
228 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
229 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
230 "%s: invalid local descriptor node.",
231 function );
232
233 return( -1 );
234 }
235 if( local_descriptor_node->entries_data == NULL )
236 {
237 libcerror_error_set(
238 error,
239 LIBCERROR_ERROR_DOMAIN_RUNTIME,
240 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
241 "%s: invalid local descriptor node - missing entries data.",
242 function );
243
244 return( -1 );
245 }
246 if( io_handle == NULL )
247 {
248 libcerror_error_set(
249 error,
250 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
251 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
252 "%s: invalid IO handle.",
253 function );
254
255 return( -1 );
256 }
257 if( ( io_handle->file_type != LIBPFF_FILE_TYPE_32BIT )
258 && ( io_handle->file_type != LIBPFF_FILE_TYPE_64BIT )
259 && ( io_handle->file_type != LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
260 {
261 libcerror_error_set(
262 error,
263 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
264 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
265 "%s: invalid IO handle - unsupported file type.",
266 function );
267
268 return( -1 );
269 }
270 if( entry_identifier == NULL )
271 {
272 libcerror_error_set(
273 error,
274 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
275 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
276 "%s: invalid entry identifier.",
277 function );
278
279 return( -1 );
280 }
281 entry_offset = (size_t) ( local_descriptor_node->entry_size * entry_index );
282
283 if( entry_offset > local_descriptor_node->entries_data_size )
284 {
285 libcerror_error_set(
286 error,
287 LIBCERROR_ERROR_DOMAIN_RUNTIME,
288 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
289 "%s: entry index value exceeds maximum.",
290 function );
291
292 return( -1 );
293 }
294 node_entry_data = &( local_descriptor_node->entries_data[ entry_offset ] );
295
296 if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
297 {
298 byte_stream_copy_to_uint32_little_endian(
299 node_entry_data,
300 *entry_identifier );
301 }
302 else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
303 || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
304 {
305 byte_stream_copy_to_uint64_little_endian(
306 node_entry_data,
307 *entry_identifier );
308 }
309 return( 1 );
310 }
311
312 /* Retrieves the sub node identifier of a specific entry
313 * Returns 1 if successful or -1 on error
314 */
libpff_local_descriptor_node_get_entry_sub_node_identifier(libpff_local_descriptor_node_t * local_descriptor_node,libpff_io_handle_t * io_handle,uint16_t entry_index,uint64_t * entry_sub_node_identifier,libcerror_error_t ** error)315 int libpff_local_descriptor_node_get_entry_sub_node_identifier(
316 libpff_local_descriptor_node_t *local_descriptor_node,
317 libpff_io_handle_t *io_handle,
318 uint16_t entry_index,
319 uint64_t *entry_sub_node_identifier,
320 libcerror_error_t **error )
321 {
322 uint8_t *node_entry_data = NULL;
323 static char *function = "libpff_local_descriptor_node_get_entry_sub_node_identifier";
324 size_t entry_offset = 0;
325
326 if( local_descriptor_node == NULL )
327 {
328 libcerror_error_set(
329 error,
330 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
331 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
332 "%s: invalid local descriptor node.",
333 function );
334
335 return( -1 );
336 }
337 if( local_descriptor_node->entries_data == NULL )
338 {
339 libcerror_error_set(
340 error,
341 LIBCERROR_ERROR_DOMAIN_RUNTIME,
342 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
343 "%s: invalid local descriptor node - missing entries data.",
344 function );
345
346 return( -1 );
347 }
348 if( io_handle == NULL )
349 {
350 libcerror_error_set(
351 error,
352 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
353 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
354 "%s: invalid IO handle.",
355 function );
356
357 return( -1 );
358 }
359 if( ( io_handle->file_type != LIBPFF_FILE_TYPE_32BIT )
360 && ( io_handle->file_type != LIBPFF_FILE_TYPE_64BIT )
361 && ( io_handle->file_type != LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
362 {
363 libcerror_error_set(
364 error,
365 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
366 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
367 "%s: invalid IO handle - unsupported file type.",
368 function );
369
370 return( -1 );
371 }
372 if( entry_sub_node_identifier == NULL )
373 {
374 libcerror_error_set(
375 error,
376 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
377 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
378 "%s: invalid entry sub node identifier.",
379 function );
380
381 return( -1 );
382 }
383 entry_offset = (size_t) ( local_descriptor_node->entry_size * entry_index );
384
385 if( entry_offset > local_descriptor_node->entries_data_size )
386 {
387 libcerror_error_set(
388 error,
389 LIBCERROR_ERROR_DOMAIN_RUNTIME,
390 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
391 "%s: entry index value exceeds maximum.",
392 function );
393
394 return( -1 );
395 }
396 node_entry_data = &( local_descriptor_node->entries_data[ entry_offset ] );
397
398 if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
399 {
400 byte_stream_copy_to_uint32_little_endian(
401 ( (pff_local_descriptor_branch_node_entry_type_32bit_t *) node_entry_data )->sub_node_identifier,
402 *entry_sub_node_identifier );
403 }
404 else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
405 || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
406 {
407 byte_stream_copy_to_uint64_little_endian(
408 ( (pff_local_descriptor_branch_node_entry_type_64bit_t *) node_entry_data )->sub_node_identifier,
409 *entry_sub_node_identifier );
410 }
411 return( 1 );
412 }
413
414 /* Reads an local descriptor node
415 * Returns 1 if successful or -1 on error
416 */
libpff_local_descriptor_node_read(libpff_local_descriptor_node_t * local_descriptor_node,libpff_io_handle_t * io_handle,libbfio_handle_t * file_io_handle,uint32_t descriptor_identifier,uint64_t data_identifier,off64_t node_offset,size32_t node_size,libcerror_error_t ** error)417 int libpff_local_descriptor_node_read(
418 libpff_local_descriptor_node_t *local_descriptor_node,
419 libpff_io_handle_t *io_handle,
420 libbfio_handle_t *file_io_handle,
421 uint32_t descriptor_identifier,
422 uint64_t data_identifier,
423 off64_t node_offset,
424 size32_t node_size,
425 libcerror_error_t **error )
426 {
427 libpff_data_block_t *data_block = NULL;
428 static char *function = "libpff_local_descriptor_node_read";
429 size_t local_descriptor_node_header_size = 0;
430 uint8_t node_signature = 0;
431
432 #if defined( HAVE_DEBUG_OUTPUT )
433 uint8_t *local_descriptor_node_entry_data = NULL;
434 uint64_t value_64bit = 0;
435 uint16_t entry_index = 0;
436 #endif
437
438 if( local_descriptor_node == NULL )
439 {
440 libcerror_error_set(
441 error,
442 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
443 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
444 "%s: invalid local descriptor node.",
445 function );
446
447 return( -1 );
448 }
449 if( local_descriptor_node->entries_data != NULL )
450 {
451 libcerror_error_set(
452 error,
453 LIBCERROR_ERROR_DOMAIN_RUNTIME,
454 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
455 "%s: invalid local descriptor node - entries data value already set.",
456 function );
457
458 return( -1 );
459 }
460 if( io_handle == NULL )
461 {
462 libcerror_error_set(
463 error,
464 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
465 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
466 "%s: invalid IO handle.",
467 function );
468
469 return( -1 );
470 }
471 if( ( io_handle->file_type != LIBPFF_FILE_TYPE_32BIT )
472 && ( io_handle->file_type != LIBPFF_FILE_TYPE_64BIT )
473 && ( io_handle->file_type != LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
474 {
475 libcerror_error_set(
476 error,
477 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
478 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
479 "%s: invalid IO handle - unsupported file type.",
480 function );
481
482 return( -1 );
483 }
484 if( node_offset < 0 )
485 {
486 libcerror_error_set(
487 error,
488 LIBCERROR_ERROR_DOMAIN_RUNTIME,
489 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
490 "%s: invalid node offset value out of bounds.",
491 function );
492
493 return( -1 );
494 }
495 if( node_size > (size32_t) SSIZE_MAX )
496 {
497 libcerror_error_set(
498 error,
499 LIBCERROR_ERROR_DOMAIN_RUNTIME,
500 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
501 "%s: node size value exceeds maximum.",
502 function );
503
504 return( -1 );
505 }
506 if( libpff_data_block_initialize(
507 &data_block,
508 io_handle,
509 descriptor_identifier,
510 data_identifier,
511 error ) != 1 )
512 {
513 libcerror_error_set(
514 error,
515 LIBCERROR_ERROR_DOMAIN_RUNTIME,
516 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
517 "%s: unable to create data block.",
518 function );
519
520 goto on_error;
521 }
522 if( libpff_data_block_read_file_io_handle(
523 data_block,
524 file_io_handle,
525 node_offset,
526 node_size,
527 io_handle->file_type,
528 error ) != 1 )
529 {
530 libcerror_error_set(
531 error,
532 LIBCERROR_ERROR_DOMAIN_IO,
533 LIBCERROR_IO_ERROR_READ_FAILED,
534 "%s: unable to read data block at offset: %" PRIi64 ".",
535 function,
536 node_offset );
537
538 goto on_error;
539 }
540 if( data_block->data == NULL )
541 {
542 libcerror_error_set(
543 error,
544 LIBCERROR_ERROR_DOMAIN_RUNTIME,
545 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
546 "%s: invalid data block - missing data.",
547 function );
548
549 goto on_error;
550 }
551 #if defined( HAVE_DEBUG_OUTPUT )
552 if( libcnotify_verbose != 0 )
553 {
554 libcnotify_printf(
555 "%s: local descriptor node data:\n",
556 function );
557 libcnotify_print_data(
558 data_block->data,
559 data_block->uncompressed_data_size,
560 0 );
561 }
562 #endif
563 /* Parse the local descriptors node data
564 */
565 if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
566 {
567 node_signature = ( (pff_local_descriptor_node_32bit_t *) data_block->data )->signature;
568 local_descriptor_node->level = ( (pff_local_descriptor_node_32bit_t *) data_block->data )->level;
569
570 byte_stream_copy_to_uint16_little_endian(
571 ( (pff_local_descriptor_node_32bit_t *) data_block->data )->number_of_entries,
572 local_descriptor_node->number_of_entries );
573 }
574 else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
575 || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
576 {
577 node_signature = ( (pff_local_descriptor_node_64bit_t *) data_block->data )->signature;
578 local_descriptor_node->level = ( (pff_local_descriptor_node_64bit_t *) data_block->data )->level;
579
580 byte_stream_copy_to_uint16_little_endian(
581 ( (pff_local_descriptor_node_64bit_t *) data_block->data )->number_of_entries,
582 local_descriptor_node->number_of_entries );
583 }
584 #if defined( HAVE_DEBUG_OUTPUT )
585 if( libcnotify_verbose != 0 )
586 {
587 libcnotify_printf(
588 "%s: local descriptors node signature\t\t: 0x%02" PRIx8 "\n",
589 function,
590 node_signature );
591 libcnotify_printf(
592 "%s: local descriptors node level\t\t\t: %" PRIu8 "\n",
593 function,
594 local_descriptor_node->level );
595 libcnotify_printf(
596 "%s: number of entries\t\t\t\t: %" PRIu16 "\n",
597 function,
598 local_descriptor_node->number_of_entries );
599
600 if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
601 || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
602 {
603 libcnotify_printf(
604 "%s: padding1:\n",
605 function );
606 libcnotify_print_data(
607 ( (pff_local_descriptor_node_64bit_t *) data_block->data )->padding1,
608 4,
609 0 );
610 }
611 }
612 #endif
613 if( node_signature != 0x02 )
614 {
615 libcerror_error_set(
616 error,
617 LIBCERROR_ERROR_DOMAIN_RUNTIME,
618 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
619 "%s: unsupported local descriptors node signature: 0x%02" PRIx8 ".",
620 function,
621 node_signature );
622
623 goto on_error;
624 }
625 if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
626 {
627 local_descriptor_node_header_size = sizeof( pff_local_descriptor_node_32bit_t );
628
629 if( local_descriptor_node->level == LIBPFF_LOCAL_DESCRIPTOR_NODE_LEVEL_LEAF )
630 {
631 local_descriptor_node->entry_size = sizeof( pff_local_descriptor_leaf_node_entry_type_32bit_t );
632 }
633 else
634 {
635 local_descriptor_node->entry_size = sizeof( pff_local_descriptor_branch_node_entry_type_32bit_t );
636 }
637 }
638 else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
639 || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
640 {
641 local_descriptor_node_header_size = sizeof( pff_local_descriptor_node_64bit_t );
642
643 if( local_descriptor_node->level == LIBPFF_LOCAL_DESCRIPTOR_NODE_LEVEL_LEAF )
644 {
645 local_descriptor_node->entry_size = sizeof( pff_local_descriptor_leaf_node_entry_type_64bit_t );
646 }
647 else
648 {
649 local_descriptor_node->entry_size = sizeof( pff_local_descriptor_branch_node_entry_type_64bit_t );
650 }
651 }
652 /* TODO additional sanity checks */
653
654 if( local_descriptor_node->number_of_entries == 0 )
655 {
656 libcerror_error_set(
657 error,
658 LIBCERROR_ERROR_DOMAIN_RUNTIME,
659 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
660 "%s: invalid number of entries.",
661 function );
662
663 /* TODO implement error tollerance */
664 goto on_error;
665 }
666 local_descriptor_node->entries_data_size = local_descriptor_node->number_of_entries * local_descriptor_node->entry_size;
667
668 if( local_descriptor_node->entries_data_size != ( data_block->uncompressed_data_size - local_descriptor_node_header_size ) )
669 {
670 libcerror_error_set(
671 error,
672 LIBCERROR_ERROR_DOMAIN_RUNTIME,
673 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
674 "%s: mismatch in total size of the entries data and the size of the entries.",
675 function );
676
677 /* TODO implement error tollerance */
678 goto on_error;
679 }
680 if( local_descriptor_node->entries_data_size > (size32_t) SSIZE_MAX )
681 {
682 libcerror_error_set(
683 error,
684 LIBCERROR_ERROR_DOMAIN_RUNTIME,
685 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
686 "%s: entries data size value exceeds maximum.",
687 function );
688
689 return( -1 );
690 }
691 /* Copy the entries data to the local descriptor node
692 * to prevent loosing it when the data block is cached out.
693 */
694 local_descriptor_node->entries_data = (uint8_t *) memory_allocate(
695 sizeof( uint8_t ) * local_descriptor_node->entries_data_size );
696
697 if( local_descriptor_node->entries_data == NULL )
698 {
699 libcerror_error_set(
700 error,
701 LIBCERROR_ERROR_DOMAIN_MEMORY,
702 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
703 "%s: unable to create entries data.",
704 function );
705
706 goto on_error;
707 }
708 if( memory_copy(
709 local_descriptor_node->entries_data,
710 &( data_block->data[ local_descriptor_node_header_size ] ),
711 local_descriptor_node->entries_data_size ) == NULL )
712 {
713 libcerror_error_set(
714 error,
715 LIBCERROR_ERROR_DOMAIN_MEMORY,
716 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
717 "%s: unable to copy data array entry.",
718 function );
719
720 goto on_error;
721 }
722 #if defined( HAVE_DEBUG_OUTPUT )
723 if( libcnotify_verbose != 0 )
724 {
725 local_descriptor_node_entry_data = local_descriptor_node->entries_data;
726
727 for( entry_index = 0;
728 entry_index < local_descriptor_node->number_of_entries;
729 entry_index++ )
730 {
731 if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
732 {
733 byte_stream_copy_to_uint32_little_endian(
734 local_descriptor_node_entry_data,
735 value_64bit );
736
737 local_descriptor_node_entry_data += 4;
738 }
739 else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
740 || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
741 {
742 byte_stream_copy_to_uint64_little_endian(
743 local_descriptor_node_entry_data,
744 value_64bit );
745
746 local_descriptor_node_entry_data += 8;
747 }
748 libcnotify_printf(
749 "%s: entry: %03d identifier\t\t\t: 0x%08" PRIx64 " (%" PRIu64 ")\n",
750 function,
751 entry_index,
752 value_64bit,
753 value_64bit );
754
755 if( local_descriptor_node->level == LIBPFF_LOCAL_DESCRIPTOR_NODE_LEVEL_LEAF )
756 {
757 if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
758 {
759 byte_stream_copy_to_uint32_little_endian(
760 local_descriptor_node_entry_data,
761 value_64bit );
762
763 local_descriptor_node_entry_data += 4;
764 }
765 else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
766 || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
767 {
768 byte_stream_copy_to_uint64_little_endian(
769 local_descriptor_node_entry_data,
770 value_64bit );
771
772 local_descriptor_node_entry_data += 8;
773 }
774 libcnotify_printf(
775 "%s: entry: %03d data identifier\t\t\t: 0x%08" PRIx64 " (%" PRIu64 ")\n",
776 function,
777 entry_index,
778 value_64bit,
779 value_64bit );
780 }
781 if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
782 {
783 byte_stream_copy_to_uint32_little_endian(
784 local_descriptor_node_entry_data,
785 value_64bit );
786
787 local_descriptor_node_entry_data += 4;
788 }
789 else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
790 || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
791 {
792 byte_stream_copy_to_uint64_little_endian(
793 local_descriptor_node_entry_data,
794 value_64bit );
795
796 local_descriptor_node_entry_data += 8;
797 }
798 if( local_descriptor_node->level == LIBPFF_LOCAL_DESCRIPTOR_NODE_LEVEL_LEAF )
799 {
800 libcnotify_printf(
801 "%s: entry: %03d local descriptors identifier\t: 0x%08" PRIx64 " (%" PRIu64 ")\n",
802 function,
803 entry_index,
804 value_64bit,
805 value_64bit );
806 }
807 else
808 {
809 libcnotify_printf(
810 "%s: entry: %03d sub node identifier\t\t: 0x%08" PRIx64 " (%" PRIu64 ")\n",
811 function,
812 entry_index,
813 value_64bit,
814 value_64bit );
815 }
816 }
817 libcnotify_printf(
818 "\n" );
819 }
820 #endif
821 if( libpff_data_block_free(
822 &data_block,
823 error ) != 1 )
824 {
825 libcerror_error_set(
826 error,
827 LIBCERROR_ERROR_DOMAIN_RUNTIME,
828 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
829 "%s: unable to free data block.",
830 function );
831
832 goto on_error;
833 }
834 return( 1 );
835
836 on_error:
837 if( local_descriptor_node->entries_data != NULL )
838 {
839 memory_free(
840 local_descriptor_node->entries_data );
841
842 local_descriptor_node->entries_data = NULL;
843 }
844 local_descriptor_node->entries_data_size = 0;
845
846 if( data_block != NULL )
847 {
848 libpff_data_block_free(
849 &data_block,
850 NULL );
851 }
852 return( -1 );
853 }
854
855 /* Reads a local descriptor node
856 * Callback for the local descriptor nodes list
857 * Returns 1 if successful or -1 on error
858 */
libpff_local_descriptor_node_read_element_data(libpff_io_handle_t * io_handle,libbfio_handle_t * file_io_handle,libfdata_list_element_t * list_element,libfcache_cache_t * cache,int data_range_file_index LIBPFF_ATTRIBUTE_UNUSED,off64_t data_range_offset,size64_t data_range_size,uint32_t data_range_flags LIBPFF_ATTRIBUTE_UNUSED,uint8_t read_flags LIBPFF_ATTRIBUTE_UNUSED,libcerror_error_t ** error)859 int libpff_local_descriptor_node_read_element_data(
860 libpff_io_handle_t *io_handle,
861 libbfio_handle_t *file_io_handle,
862 libfdata_list_element_t *list_element,
863 libfcache_cache_t *cache,
864 int data_range_file_index LIBPFF_ATTRIBUTE_UNUSED,
865 off64_t data_range_offset,
866 size64_t data_range_size,
867 uint32_t data_range_flags LIBPFF_ATTRIBUTE_UNUSED,
868 uint8_t read_flags LIBPFF_ATTRIBUTE_UNUSED,
869 libcerror_error_t **error )
870 {
871 libpff_local_descriptor_node_t *local_descriptor_node = NULL;
872 static char *function = "libpff_local_descriptor_node_read_element_data";
873
874 LIBPFF_UNREFERENCED_PARAMETER( data_range_file_index )
875 LIBPFF_UNREFERENCED_PARAMETER( data_range_flags )
876 LIBPFF_UNREFERENCED_PARAMETER( read_flags )
877
878 if( io_handle == NULL )
879 {
880 libcerror_error_set(
881 error,
882 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
883 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
884 "%s: invalid IO handle.",
885 function );
886
887 return( -1 );
888 }
889 if( data_range_size > (size64_t) UINT32_MAX )
890 {
891 libcerror_error_set(
892 error,
893 LIBCERROR_ERROR_DOMAIN_RUNTIME,
894 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
895 "%s: data range size value exceeds maximum.",
896 function );
897
898 return( -1 );
899 }
900 if( libpff_local_descriptor_node_initialize(
901 &local_descriptor_node,
902 error ) != 1 )
903 {
904 libcerror_error_set(
905 error,
906 LIBCERROR_ERROR_DOMAIN_RUNTIME,
907 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
908 "%s: unable to create local descriptor node.",
909 function );
910
911 goto on_error;
912 }
913 if( libpff_local_descriptor_node_read(
914 local_descriptor_node,
915 io_handle,
916 file_io_handle,
917 0,
918 0,
919 data_range_offset,
920 (size32_t) data_range_size,
921 error ) != 1 )
922 {
923 libcerror_error_set(
924 error,
925 LIBCERROR_ERROR_DOMAIN_IO,
926 LIBCERROR_IO_ERROR_READ_FAILED,
927 "%s: unable to read local descriptor node at offset: 0x%08" PRIx64 ".",
928 function,
929 data_range_offset );
930
931 goto on_error;
932 }
933 if( libfdata_list_element_set_element_value(
934 list_element,
935 (intptr_t *) file_io_handle,
936 cache,
937 (intptr_t *) local_descriptor_node,
938 (int (*)(intptr_t **, libcerror_error_t **)) &libpff_local_descriptor_node_free,
939 LIBFDATA_LIST_ELEMENT_VALUE_FLAG_MANAGED,
940 error ) != 1 )
941 {
942 libcerror_error_set(
943 error,
944 LIBCERROR_ERROR_DOMAIN_RUNTIME,
945 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
946 "%s: unable to set local descriptor node as element value.",
947 function );
948
949 goto on_error;
950 }
951 return( 1 );
952
953 on_error:
954 if( local_descriptor_node != NULL )
955 {
956 libpff_local_descriptor_node_free(
957 &local_descriptor_node,
958 NULL );
959 }
960 return( -1 );
961 }
962
963