/* Clones the list and its elements * * The values are cloned using the value_clone_function * On error the values are freed using the value_free_function * * Returns 1 if successful or -1 on error */ int libcdata_list_clone( libcdata_list_t **destination_list, libcdata_list_t *source_list, int (*value_free_function)( intptr_t **value, libcerror_error_t **error ), int (*value_clone_function)( intptr_t **destination, intptr_t *source, libcerror_error_t **error ), libcerror_error_t **error ) { libcdata_internal_list_t *internal_source_list = NULL; libcdata_list_element_t *source_list_element = NULL; intptr_t *destination_value = NULL; intptr_t *source_value = NULL; static char *function = "libcdata_list_clone"; int element_index = 0; if( destination_list == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid destination list.", function ); return( -1 ); } if( *destination_list != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid destination list already set.", function ); return( -1 ); } if( value_free_function == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid value free function.", function ); return( -1 ); } if( value_clone_function == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid value clone function.", function ); return( -1 ); } if( source_list == NULL ) { *destination_list = NULL; return( 1 ); } internal_source_list = (libcdata_internal_list_t *) source_list; if( libcdata_list_initialize( destination_list, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create destination list.", function ); goto on_error; } if( *destination_list == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing destination list.", function ); goto on_error; } source_list_element = internal_source_list->first_element; for( element_index = 0; element_index < internal_source_list->number_of_elements; element_index++ ) { if( libcdata_list_element_get_value( source_list_element, &source_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve value from source list element: %d.", function, element_index ); goto on_error; } if( value_clone_function( &destination_value, source_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to clone value of source list element: %d.", function, element_index ); goto on_error; } if( libcdata_list_append_value( *destination_list, destination_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append value of list element: %d.", function, element_index ); goto on_error; } destination_value = NULL; if( libcdata_list_element_get_next_element( source_list_element, &source_list_element, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve next element from source list element: %d.", function, element_index ); goto on_error; } } return( 1 ); on_error: if( destination_value != NULL ) { value_free_function( &destination_value, NULL ); } if( *destination_list != NULL ) { libcdata_list_free( destination_list, value_free_function, error ); } return( -1 ); }
/* Read the name to id map * Returns 1 if successful, 0 if not available or -1 on error */ int libpff_name_to_id_map_read( libcdata_list_t *name_to_id_map_list, libpff_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, libpff_descriptors_index_t *descriptors_index, libpff_offsets_index_t *offsets_index, libcerror_error_t **error ) { libpff_index_value_t *descriptor_index_value = NULL; libpff_item_values_t *item_values = NULL; libpff_name_to_id_map_entry_t *name_to_id_map_entry = NULL; libpff_record_entry_t *name_to_id_map_class_identifiers_record_entry = NULL; libpff_record_entry_t *name_to_id_map_entries_record_entry = NULL; libpff_record_entry_t *name_to_id_map_strings_record_entry = NULL; uint8_t *name_to_id_map_class_identifiers_data = NULL; uint8_t *name_to_id_map_entries_data = NULL; uint8_t *name_to_id_map_entry_data = NULL; uint8_t *name_to_id_map_strings_record_data = NULL; static char *function = "libpff_name_to_id_map_read"; size_t name_to_id_map_class_identifiers_data_size = 0; size_t name_to_id_map_entries_data_size = 0; size_t name_to_id_map_strings_record_data_size = 0; uint32_t number_of_name_to_id_map_entries = 0; uint32_t name_to_id_map_entry_index = 0; int result = 0; if( name_to_id_map_list == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid name to id map list.", function ); return( -1 ); } result = libpff_descriptors_index_get_index_value_by_identifier( descriptors_index, file_io_handle, (uint32_t) LIBPFF_DESCRIPTOR_IDENTIFIER_NAME_TO_ID_MAP, 0, &descriptor_index_value, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve descriptor index value: %" PRIu32 ".", function, (uint32_t) LIBPFF_DESCRIPTOR_IDENTIFIER_NAME_TO_ID_MAP ); #if defined( HAVE_DEBUG_OUTPUT ) if( ( libcnotify_verbose != 0 ) && ( error != NULL ) && ( *error != NULL ) ) { libcnotify_print_error_backtrace( *error ); } #endif libcerror_error_free( error ); return( 0 ); } else if( result == 0 ) { return( 0 ); } if( descriptor_index_value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid descriptor index value.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: descriptor identifier: %" PRIu64 " (%s), data: %" PRIu64 ", local descriptors: %" PRIu64 ", parent: %" PRIu32 "\n", function, descriptor_index_value->identifier, libpff_debug_get_node_identifier_type( (uint8_t) ( descriptor_index_value->identifier & 0x0000001fUL ) ), descriptor_index_value->data_identifier, descriptor_index_value->local_descriptors_identifier, descriptor_index_value->parent_identifier ); } #endif if( libpff_item_values_initialize( &item_values, LIBPFF_DESCRIPTOR_IDENTIFIER_NAME_TO_ID_MAP, descriptor_index_value->data_identifier, descriptor_index_value->local_descriptors_identifier, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create item values.", function ); goto on_error; } if( libpff_item_values_read( item_values, NULL, io_handle, file_io_handle, offsets_index, LIBPFF_DEBUG_ITEM_TYPE_NAME_TO_ID_MAP, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read name to id map item values.", function ); goto on_error; } if( item_values->table == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid item values - missing table.", function ); goto on_error; } if( libpff_table_get_record_entry_by_type( item_values->table, 0, LIBPFF_ENTRY_TYPE_NAME_TO_ID_MAP_ENTRIES, LIBPFF_VALUE_TYPE_BINARY_DATA, &name_to_id_map_entries_record_entry, LIBPFF_ENTRY_VALUE_FLAG_IGNORE_NAME_TO_ID_MAP, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve name to id map entries record entry.", function ); goto on_error; } if( libpff_record_entry_get_value_data( name_to_id_map_entries_record_entry, &name_to_id_map_entries_data, &name_to_id_map_entries_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve name to id map entries data.", function ); goto on_error; } if( name_to_id_map_entries_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing name to id map entries data.", function ); goto on_error; } if( ( name_to_id_map_entries_data_size == 0 ) || ( name_to_id_map_entries_data_size > (size_t) SSIZE_MAX ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid name to id map entries data size value out of bounds.", function ); goto on_error; } if( ( name_to_id_map_entries_data_size % 8 ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported name to id map entries size.", function ); goto on_error; } number_of_name_to_id_map_entries = (uint32_t) ( name_to_id_map_entries_data_size / 8 ); if( libpff_table_get_record_entry_by_type( item_values->table, 0, LIBPFF_ENTRY_TYPE_NAME_TO_ID_MAP_STRINGS, LIBPFF_VALUE_TYPE_BINARY_DATA, &name_to_id_map_strings_record_entry, LIBPFF_ENTRY_VALUE_FLAG_IGNORE_NAME_TO_ID_MAP, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve name to id map strings record entry.", function ); goto on_error; } if( libpff_table_get_record_entry_by_type( item_values->table, 0, LIBPFF_ENTRY_TYPE_NAME_TO_ID_MAP_CLASS_IDENTIFIERS, LIBPFF_VALUE_TYPE_BINARY_DATA, &name_to_id_map_class_identifiers_record_entry, LIBPFF_ENTRY_VALUE_FLAG_IGNORE_NAME_TO_ID_MAP, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve name to id map class identifiers record entry.", function ); goto on_error; } if( libpff_record_entry_get_value_data( name_to_id_map_class_identifiers_record_entry, &name_to_id_map_class_identifiers_data, &name_to_id_map_class_identifiers_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve name to id map class identifiers data.", function ); goto on_error; } if( name_to_id_map_class_identifiers_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing name to id map class identifiers data.", function ); goto on_error; } if( ( name_to_id_map_class_identifiers_data_size == 0 ) || ( name_to_id_map_class_identifiers_data_size > (size64_t) SSIZE_MAX ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid name to id map class identifiers data size value out of bounds.", function ); goto on_error; } name_to_id_map_entry_data = name_to_id_map_entries_data; for( name_to_id_map_entry_index = 0; name_to_id_map_entry_index < number_of_name_to_id_map_entries; name_to_id_map_entry_index++ ) { if( libpff_record_entry_get_value_data( name_to_id_map_strings_record_entry, &name_to_id_map_strings_record_data, &name_to_id_map_strings_record_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve name to id map strings record data.", function ); goto on_error; } if( libpff_name_to_id_map_entry_initialize( &name_to_id_map_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create name to id map entry.", function ); goto on_error; } if( libpff_name_to_id_map_entry_read( name_to_id_map_entry, name_to_id_map_entry_data, sizeof( pff_name_to_id_map_entry_t ), name_to_id_map_class_identifiers_data, name_to_id_map_class_identifiers_data_size, name_to_id_map_strings_record_data, name_to_id_map_strings_record_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read name to id map entry.", function ); goto on_error; } name_to_id_map_entry_data += sizeof( pff_name_to_id_map_entry_t ); if( ( ( (libpff_internal_name_to_id_map_entry_t *) name_to_id_map_entry )->flags & LIBPFF_NAME_TO_ID_MAP_ENTRY_FLAG_IS_CORRUPTED ) != 0 ) { io_handle->flags |= LIBPFF_IO_HANDLE_FLAG_IS_CORRUPTED; } if( libcdata_list_append_value( name_to_id_map_list, (intptr_t *) name_to_id_map_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append name to id map entry to list.", function ); goto on_error; } name_to_id_map_entry = NULL; } if( libpff_item_values_free( &item_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free item values.", function ); goto on_error; } return( 1 ); on_error: if( name_to_id_map_entry != NULL ) { libpff_name_to_id_map_entry_free( &name_to_id_map_entry, NULL ); } if( item_values != NULL ) { libpff_item_values_free( &item_values, NULL ); } libcdata_list_empty( name_to_id_map_list, (int (*)(intptr_t **, libcerror_error_t **)) &libpff_name_to_id_map_entry_free, NULL ); return( -1 ); }
/* Creates an item tree node from the descriptor index * * If a descriptor index value has no existing parent it is added to the orphan node list * and the function will return 0 * * Returns 1 if successful, 0 if the item tree node could not be created or -1 on error */ int libpff_item_tree_create_node( libcdata_tree_node_t *item_tree_root_node, libbfio_handle_t *file_io_handle, libfdata_tree_t *descriptor_index_tree, libfdata_tree_node_t *descriptor_index_tree_node, libfcache_cache_t *index_tree_cache, libcdata_list_t *orphan_node_list, libcdata_tree_node_t **root_folder_item_tree_node, libcerror_error_t **error ) { libcdata_tree_node_t *item_tree_node = NULL; libcdata_tree_node_t *parent_node = NULL; libfdata_tree_node_t *descriptor_index_tree_parent_node = NULL; libfdata_tree_node_t *descriptor_index_tree_sub_node = NULL; libpff_index_value_t *descriptor_index_value = NULL; libpff_item_descriptor_t *item_descriptor = NULL; static char *function = "libpff_item_tree_create_node"; int leaf_node_index = 0; int number_of_sub_nodes = 0; int result = 0; int sub_node_index = 0; if( item_tree_root_node == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid item tree root node.", function ); return( -1 ); } if( orphan_node_list == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid orphan node list.", function ); return( -1 ); } if( root_folder_item_tree_node == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid root folder item tree node.", function ); return( -1 ); } /* Check if the index node can be read */ if( libfdata_tree_node_get_number_of_sub_nodes( descriptor_index_tree_node, (intptr_t *) file_io_handle, index_tree_cache, &number_of_sub_nodes, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of sub nodes from descriptor index tree node.", function ); #if defined( HAVE_DEBUG_OUTPUT ) if( ( libcnotify_verbose != 0 ) && ( error != NULL ) && ( *error != NULL ) ) { libcnotify_print_error_backtrace( *error ); } #endif libcerror_error_free( error ); /* TODO flag corrupt item tree */ return( 0 ); } result = libfdata_tree_node_is_deleted( descriptor_index_tree_node, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if descriptor index tree sub node: %d is deleted.", function, sub_node_index ); return( -1 ); } else if( result != 0 ) { return( 0 ); } result = libfdata_tree_node_is_leaf( descriptor_index_tree_node, (intptr_t *) file_io_handle, index_tree_cache, 0, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if descriptor index tree sub node: %d is a leaf node.", function, sub_node_index ); return( -1 ); } else if( result == 0 ) { for( sub_node_index = 0; sub_node_index < number_of_sub_nodes; sub_node_index++ ) { if( libfdata_tree_node_get_sub_node_by_index( descriptor_index_tree_node, (intptr_t *) file_io_handle, index_tree_cache, sub_node_index, &descriptor_index_tree_sub_node, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve sub node: %d from descriptor index tree node.", function, sub_node_index ); return( -1 ); } result = libpff_item_tree_create_node( item_tree_root_node, file_io_handle, descriptor_index_tree, descriptor_index_tree_sub_node, index_tree_cache, orphan_node_list, root_folder_item_tree_node, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create index tree from descriptor index tree sub node: %d.", function, sub_node_index ); return( -1 ); } } } else { if( libfdata_tree_node_get_node_value( descriptor_index_tree_node, (intptr_t *) file_io_handle, index_tree_cache, (intptr_t **) &descriptor_index_value, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve descriptor index tree sub node value.", function ); return( -1 ); } if( descriptor_index_value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing descriptor index tree sub node value.", function ); return( -1 ); } if( descriptor_index_value->identifier > (uint64_t) UINT32_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: descriptor index identifier value exceeds maximum.", function ); return( -1 ); } /* Create a new item descriptor */ if( libpff_item_descriptor_initialize( &item_descriptor, (uint32_t) descriptor_index_value->identifier, descriptor_index_value->data_identifier, descriptor_index_value->local_descriptors_identifier, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create item descriptor.", function ); return( -1 ); } if( item_descriptor == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing item descriptor.", function ); return( -1 ); } /* The root folder index descriptor points to itself as its parent */ if( descriptor_index_value->identifier == descriptor_index_value->parent_identifier ) { if( *root_folder_item_tree_node != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: root folder item tree node already set.", function ); libpff_item_descriptor_free( &item_descriptor, NULL ); return( -1 ); } if( libcdata_tree_node_initialize( root_folder_item_tree_node, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create root folder item tree node.", function ); libpff_item_descriptor_free( &item_descriptor, NULL ); return( -1 ); } if( libcdata_tree_node_set_value( *root_folder_item_tree_node, (intptr_t *) item_descriptor, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set item descriptor in root folder item tree node.", function ); libcdata_tree_node_free( root_folder_item_tree_node, NULL, NULL ); libpff_item_descriptor_free( &item_descriptor, NULL ); return( -1 ); } result = libcdata_tree_node_insert_node( item_tree_root_node, *root_folder_item_tree_node, (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libpff_item_descriptor_compare, LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES, NULL ); /* Free the node if it could not be inserted */ if( result != 1 ) { libcdata_tree_node_free( root_folder_item_tree_node, (int (*)(intptr_t **, libcerror_error_t **)) &libpff_item_descriptor_free, NULL ); } if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to insert item descriptor in item tree node.", function ); return( -1 ); } } else { result = libpff_item_tree_get_tree_node_by_identifier( item_tree_root_node, descriptor_index_value->parent_identifier, &parent_node, error ); if( result == 0 ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading ahead for descriptor: %" PRIu64 " parent %" PRIu32 ".\n", function, descriptor_index_value->identifier, descriptor_index_value->parent_identifier ); } #endif result = libpff_index_tree_get_leaf_node_by_identifier( descriptor_index_tree, file_io_handle, index_tree_cache, descriptor_index_value->parent_identifier, &leaf_node_index, &descriptor_index_tree_parent_node, error ); if( result == 1 ) { if( descriptor_index_tree_parent_node == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid descriptor index tree parent node.", function ); libpff_item_descriptor_free( &item_descriptor, NULL ); return( -1 ); } result = libpff_item_tree_create_node( item_tree_root_node, file_io_handle, descriptor_index_tree, descriptor_index_tree_parent_node, index_tree_cache, orphan_node_list, root_folder_item_tree_node, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create index tree from descriptor index tree parent node: %" PRIu32 ".", function, descriptor_index_value->parent_identifier ); libpff_item_descriptor_free( &item_descriptor, NULL ); return( -1 ); } parent_node = NULL; result = libpff_item_tree_get_tree_node_by_identifier( item_tree_root_node, descriptor_index_value->parent_identifier, &parent_node, error ); } } if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to find parent node: %" PRIu32 ".", function, descriptor_index_value->parent_identifier ); libpff_item_descriptor_free( &item_descriptor, NULL ); return( -1 ); } else if( result == 0 ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: parent node: %" PRIu32 " missing - found orphan node: %" PRIu64 ".\n", function, descriptor_index_value->parent_identifier, descriptor_index_value->identifier ); } #endif if( libcdata_tree_node_initialize( &item_tree_node, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create item tree node.", function ); libpff_item_descriptor_free( &item_descriptor, NULL ); return( -1 ); } if( libcdata_tree_node_set_value( item_tree_node, (intptr_t *) item_descriptor, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set item descriptor in item tree root node.", function ); libcdata_tree_node_free( &item_tree_node, NULL, NULL ); libpff_item_descriptor_free( &item_descriptor, NULL ); return( -1 ); } item_descriptor = NULL; if( libcdata_list_append_value( orphan_node_list, (intptr_t *) item_tree_node, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append orphan node in orphan node list.", function ); libcdata_tree_node_free( &item_tree_node, (int (*)(intptr_t **, libcerror_error_t **)) &libpff_item_descriptor_free, NULL ); return( -1 ); } return( 0 ); } if( parent_node == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid parent node.", function ); libpff_item_descriptor_free( &item_descriptor, NULL ); return( -1 ); } result = libcdata_tree_node_insert_value( parent_node, (intptr_t *) item_descriptor, (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libpff_item_descriptor_compare, LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES, error ); /* Free the node if it could not be inserted */ if( result != 1 ) { libpff_item_descriptor_free( &item_descriptor, NULL ); } if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to insert item descriptor in item tree node.", function ); return( -1 ); } } } return( 1 ); }
/* Reads the catalog * Returns 1 if successful or -1 on error */ int libesedb_catalog_read( libesedb_catalog_t *catalog, libbfio_handle_t *file_io_handle, libesedb_io_handle_t *io_handle, uint32_t page_number, libfdata_vector_t *pages_vector, libfcache_cache_t *pages_cache, libcerror_error_t **error ) { libesedb_catalog_definition_t *catalog_definition = NULL; libesedb_data_definition_t *data_definition = NULL; libesedb_page_tree_t *catalog_page_tree = NULL; libesedb_table_definition_t *table_definition = NULL; libfcache_cache_t *catalog_values_cache = NULL; libfdata_btree_t *catalog_values_tree = NULL; uint8_t *catalog_definition_data = NULL; static char *function = "libesedb_catalog_read"; off64_t node_data_offset = 0; size_t catalog_definition_data_size = 0; int leaf_value_index = 0; int number_of_leaf_values = 0; if( catalog == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid catalog.", function ); return( -1 ); } if( io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid IO handle.", function ); return( -1 ); } if( page_number == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS, "%s: invalid page number value zero or less.", function ); return( -1 ); } if( libesedb_page_tree_initialize( &catalog_page_tree, io_handle, pages_vector, pages_cache, LIBESEDB_FDP_OBJECT_IDENTIFIER_CATALOG, NULL, NULL, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create catalog page tree.", function ); goto on_error; } /* TODO add clone function */ if( libfdata_btree_initialize( &catalog_values_tree, (intptr_t *) catalog_page_tree, (int (*)(intptr_t **, libcerror_error_t **)) &libesedb_page_tree_free, NULL, (int (*)(intptr_t *, intptr_t *, libfdata_btree_node_t *, int, off64_t, size64_t, uint32_t, intptr_t *, uint8_t, libcerror_error_t **)) &libesedb_page_tree_read_node, (int (*)(intptr_t *, intptr_t *, libfdata_btree_t *, libfcache_cache_t *, int, int, off64_t, size64_t, uint32_t, intptr_t *, uint8_t, libcerror_error_t **)) &libesedb_page_tree_read_leaf_value, LIBFDATA_DATA_HANDLE_FLAG_MANAGED, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create catalog values tree.", function ); goto on_error; } catalog_page_tree = NULL; if( libfcache_cache_initialize( &catalog_values_cache, LIBESEDB_MAXIMUM_CACHE_ENTRIES_TREE_VALUES, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create catalog values cache.", function ); goto on_error; } node_data_offset = ( (off64_t) page_number - 1 ) * io_handle->page_size; if( libfdata_btree_set_root_node( catalog_values_tree, 0, node_data_offset, 0, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set root node in catalog values tree.", function ); goto on_error; } if( libfdata_btree_get_number_of_leaf_values( catalog_values_tree, (intptr_t *) file_io_handle, catalog_values_cache, &number_of_leaf_values, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of leaf values from catalog values tree.", function ); goto on_error; } for( leaf_value_index = 0; leaf_value_index < number_of_leaf_values; leaf_value_index++ ) { if( libfdata_btree_get_leaf_value_by_index( catalog_values_tree, (intptr_t *) file_io_handle, catalog_values_cache, leaf_value_index, (intptr_t **) &data_definition, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve leaf value: %d from catalog values tree.", function, leaf_value_index ); goto on_error; } if( libesedb_data_definition_read_data( data_definition, file_io_handle, io_handle, pages_vector, pages_cache, &catalog_definition_data, &catalog_definition_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read data definition data.", function ); goto on_error; } if( libesedb_catalog_definition_initialize( &catalog_definition, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create catalog definition.", function ); goto on_error; } if( libesedb_catalog_definition_read( catalog_definition, catalog_definition_data, catalog_definition_data_size, io_handle->ascii_codepage, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read catalog definition.", function ); goto on_error; } if( ( catalog_definition->type != LIBESEDB_CATALOG_DEFINITION_TYPE_TABLE ) && ( table_definition == NULL ) ) { /* TODO add build-in table 1 support */ #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: missing table definition for catalog definition type: %" PRIu16 ".\n", function, catalog_definition->type ); } #endif if( libesedb_catalog_definition_free( &catalog_definition, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free catalog definition.", function ); goto on_error; } catalog_definition = NULL; } else switch( catalog_definition->type ) { case LIBESEDB_CATALOG_DEFINITION_TYPE_TABLE: table_definition = NULL; if( libesedb_table_definition_initialize( &table_definition, catalog_definition, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create table definition.", function ); libesedb_table_definition_free( &table_definition, NULL ); goto on_error; } catalog_definition = NULL; if( libcdata_list_append_value( catalog->table_definition_list, (intptr_t *) table_definition, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append table definition to table definition list.", function ); libesedb_table_definition_free( &table_definition, NULL ); goto on_error; } break; case LIBESEDB_CATALOG_DEFINITION_TYPE_COLUMN: if( libesedb_table_definition_append_column_catalog_definition( table_definition, catalog_definition, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append column catalog definition to table definition.", function ); goto on_error; } catalog_definition = NULL; break; case LIBESEDB_CATALOG_DEFINITION_TYPE_INDEX: if( libesedb_table_definition_append_index_catalog_definition( table_definition, catalog_definition, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append index catalog definition to table definition.", function ); goto on_error; } catalog_definition = NULL; break; case LIBESEDB_CATALOG_DEFINITION_TYPE_LONG_VALUE: if( libesedb_table_definition_set_long_value_catalog_definition( table_definition, catalog_definition, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set long value catalog definition in table definition.", function ); goto on_error; } catalog_definition = NULL; break; case LIBESEDB_CATALOG_DEFINITION_TYPE_CALLBACK: if( libesedb_table_definition_set_callback_catalog_definition( table_definition, catalog_definition, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set callback catalog definition in table definition.", function ); goto on_error; } catalog_definition = NULL; break; default: #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: unsupported catalog definition type: %" PRIu16 ".\n", function, catalog_definition->type ); } #endif if( libesedb_catalog_definition_free( &catalog_definition, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free catalog definition.", function ); goto on_error; } catalog_definition = NULL; break; } } if( libfcache_cache_free( &catalog_values_cache, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free catalog values cache.", function ); goto on_error; } if( libfdata_btree_free( &catalog_values_tree, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free catalog values tree.", function ); goto on_error; } return( 1 ); on_error: if( catalog_definition != NULL ) { libesedb_catalog_definition_free( &catalog_definition, NULL ); } if( catalog_values_cache != NULL ) { libfcache_cache_free( &catalog_values_cache, NULL ); } if( catalog_values_tree != NULL ) { libfdata_btree_free( &catalog_values_tree, NULL ); } if( catalog_page_tree != NULL ) { libesedb_page_tree_free( &catalog_page_tree, NULL ); } return( -1 ); }