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