/* Sets the node value of the node * * If the flag LIBFDATA_TREE_NODE_VALUE_FLAG_MANAGED is set the tree * takes over management of the value and the value is freed when * no longer needed. * * Returns 1 if successful or -1 on error */ int libfdata_tree_set_node_value( libfdata_tree_t *tree, libfcache_cache_t *cache, libfdata_tree_node_t *node, intptr_t *node_value, int (*free_node_value)( intptr_t **node_value, libcerror_error_t **error ), uint8_t flags, libcerror_error_t **error ) { static char *function = "libfdata_tree_set_node_value"; off64_t node_offset = 0; size64_t node_size = 0; time_t node_timestamp = 0; uint32_t node_flags = 0; int cache_entry_index = -1; int node_file_index = -1; int number_of_cache_entries = 0; if( tree == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid tree.", function ); return( -1 ); } if( libfdata_tree_node_get_data_range( node, &node_file_index, &node_offset, &node_size, &node_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data range from tree node.", function ); return( -1 ); } if( libfdata_tree_node_get_timestamp( node, &node_timestamp, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve timestamp from tree node.", function ); return( -1 ); } if( libfcache_cache_get_number_of_entries( cache, &number_of_cache_entries, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of cache entries.", function ); return( -1 ); } if( number_of_cache_entries <= 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid number of cache entries value out of bounds.", function ); return( -1 ); } if( ( ( ( (libfdata_internal_tree_node_t *) node )->flags & LIBFDATA_TREE_NODE_FLAG_IS_VIRTUAL ) == 0 ) && ( ( ( (libfdata_internal_tree_node_t *) node )->flags & LIBFDATA_TREE_NODE_FLAG_IS_LEAF ) != 0 ) ) { cache_entry_index = libfdata_tree_node_calculate_leaf_node_cache_entry_index( node_offset, number_of_cache_entries ); } else { cache_entry_index = libfdata_tree_node_calculate_branch_node_cache_entry_index( node_offset, number_of_cache_entries ); } if( libfcache_cache_set_value_by_index( cache, cache_entry_index, node_file_index, node_offset, node_timestamp, node_value, free_node_value, flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set value in cache entry: %d.", function, cache_entry_index ); return( -1 ); } return( 1 ); }
/* Retrieves the value an element at a specific offset * Returns 1 if successful or -1 on error */ int libfdata_area_get_element_value_at_offset( libfdata_area_t *area, intptr_t *file_io_handle, libfdata_cache_t *cache, off64_t element_value_offset, intptr_t **element_value, uint8_t read_flags, libcerror_error_t **error ) { libfcache_cache_value_t *cache_value = NULL; libfdata_internal_area_t *internal_area = NULL; libfdata_range_t *segment_data_range = NULL; static char *function = "libfdata_area_get_element_value_at_offset"; off64_t cache_value_offset = (off64_t) -1; off64_t element_data_offset = (off64_t) -1; int64_t cache_value_timestamp = 0; uint32_t element_data_flags = 0; int cache_entry_index = -1; int cache_value_file_index = -1; int element_data_file_index = -1; int element_index = -1; int number_of_cache_entries = 0; int result = 0; if( area == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid area.", function ); return( -1 ); } internal_area = (libfdata_internal_area_t *) area; if( internal_area->read_element_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid area - missing read element data function.", function ); return( -1 ); } if( internal_area->element_data_size == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid area - element data size value out of bounds.", function ); return( -1 ); } if( ( internal_area->size == 0 ) || ( internal_area->size > (off64_t) INT64_MAX ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid area - size value out of bounds.", function ); return( -1 ); } if( ( (size64_t) element_value_offset > internal_area->size ) || ( (size64_t) element_value_offset > ( internal_area->size - internal_area->element_data_size ) ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid element value offset value out of bounds.", function ); return( -1 ); } if( libfdata_segments_array_get_data_range_at_offset( internal_area->segments_array, element_value_offset, &element_data_offset, &segment_data_range, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve segment data range for offset: 0x%08" PRIx64 ".", function, element_value_offset ); return( -1 ); } if( segment_data_range == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing segment data range.", function ); return( -1 ); } element_data_file_index = segment_data_range->file_index; element_data_offset += segment_data_range->offset; element_data_flags = segment_data_range->flags; if( libfcache_cache_get_number_of_entries( (libfcache_cache_t *) cache, &number_of_cache_entries, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of cache entries.", function ); return( -1 ); } if( number_of_cache_entries <= 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid number of cache entries value out of bounds.", function ); return( -1 ); } element_index = (int) ( element_value_offset / internal_area->element_data_size ); if( ( read_flags & LIBFDATA_READ_FLAG_IGNORE_CACHE ) == 0 ) { if( internal_area->calculate_cache_entry_index == NULL ) { cache_entry_index = element_index % number_of_cache_entries; } else { cache_entry_index = internal_area->calculate_cache_entry_index( element_index, element_data_file_index, element_data_offset, internal_area->element_data_size, element_data_flags, number_of_cache_entries ); } if( libfcache_cache_get_value_by_index( (libfcache_cache_t *) cache, cache_entry_index, &cache_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve cache entry: %d from cache.", function, cache_entry_index ); return( -1 ); } if( cache_value != NULL ) { if( libfcache_cache_value_get_identifier( cache_value, &cache_value_file_index, &cache_value_offset, &cache_value_timestamp, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve cache value identifier.", function ); return( -1 ); } } if( ( element_data_file_index == cache_value_file_index ) && ( element_data_offset == cache_value_offset ) && ( internal_area->timestamp == cache_value_timestamp ) ) { result = 1; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( result == 0 ) { libcnotify_printf( "%s: cache: 0x%08" PRIjx " miss (%d out of %d)\n", function, (intptr_t) cache, cache_entry_index, number_of_cache_entries ); } else { libcnotify_printf( "%s: cache: 0x%08" PRIjx " hit (%d out of %d)\n", function, (intptr_t) cache, cache_entry_index, number_of_cache_entries ); } } #endif } if( result == 0 ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading element data at offset: %" PRIi64 " (0x%08" PRIx64 ") of size: %" PRIu64 "\n", function, element_data_offset, element_data_offset, internal_area->element_data_size ); } #endif if( internal_area->read_element_data( internal_area->data_handle, file_io_handle, area, cache, element_value_offset, element_data_file_index, element_data_offset, internal_area->element_data_size, element_data_flags, read_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read element data at offset: 0x%08" PRIx64 ".", function, element_data_offset ); return( -1 ); } if( internal_area->calculate_cache_entry_index == NULL ) { cache_entry_index = element_index % number_of_cache_entries; } else { cache_entry_index = internal_area->calculate_cache_entry_index( element_index, element_data_file_index, element_data_offset, internal_area->element_data_size, element_data_flags, number_of_cache_entries ); } if( libfcache_cache_get_value_by_index( (libfcache_cache_t *) cache, cache_entry_index, &cache_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve cache entry: %d from cache.", function, cache_entry_index ); return( -1 ); } if( cache_value != NULL ) { if( libfcache_cache_value_get_identifier( cache_value, &cache_value_file_index, &cache_value_offset, &cache_value_timestamp, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve cache value identifier.", function ); return( -1 ); } } if( ( element_data_file_index != cache_value_file_index ) || ( element_data_offset != cache_value_offset ) || ( internal_area->timestamp != cache_value_timestamp ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing cache value.", function ); return( -1 ); } } if( libfcache_cache_value_get_value( cache_value, element_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve element value.", function ); return( -1 ); } return( 1 ); }
/* Retrieves the node value of the node * Returns 1 if successful or -1 on error */ int libfdata_tree_get_node_value( libfdata_tree_t *tree, intptr_t *file_io_handle, libfcache_cache_t *cache, libfdata_tree_node_t *node, intptr_t **node_value, uint8_t read_flags, libcerror_error_t **error ) { libfcache_cache_value_t *cache_value = NULL; libfdata_internal_tree_t *internal_tree = NULL; static char *function = "libfdata_tree_get_node_value"; off64_t cache_value_offset = (off64_t) -1; off64_t node_offset = 0; size64_t node_size = 0; time_t cache_value_timestamp = 0; time_t node_timestamp = 0; uint32_t node_flags = 0; int cache_entry_index = -1; int cache_value_file_index = -1; int number_of_cache_entries = 0; int node_file_index = -1; int result = 0; if( tree == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid tree.", function ); return( -1 ); } internal_tree = (libfdata_internal_tree_t *) tree; if( internal_tree->read_node == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid tree - missing read node function.", function ); return( -1 ); } if( libfdata_tree_node_get_data_range( node, &node_file_index, &node_offset, &node_size, &node_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data range from tree node.", function ); return( -1 ); } if( libfcache_cache_get_number_of_entries( cache, &number_of_cache_entries, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of cache entries.", function ); return( -1 ); } if( number_of_cache_entries <= 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid number of cache entries value out of bounds.", function ); return( -1 ); } if( ( read_flags & LIBFDATA_READ_FLAG_IGNORE_CACHE ) == 0 ) { if( ( ( ( (libfdata_internal_tree_node_t *) node )->flags & LIBFDATA_TREE_NODE_FLAG_IS_VIRTUAL ) == 0 ) && ( ( ( (libfdata_internal_tree_node_t *) node )->flags & LIBFDATA_TREE_NODE_FLAG_IS_LEAF ) != 0 ) ) { cache_entry_index = libfdata_tree_node_calculate_leaf_node_cache_entry_index( node_offset, number_of_cache_entries ); } else { cache_entry_index = libfdata_tree_node_calculate_branch_node_cache_entry_index( node_offset, number_of_cache_entries ); } if( libfcache_cache_get_value_by_index( cache, cache_entry_index, &cache_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve cache entry: %d from cache.", function, cache_entry_index ); return( -1 ); } if( cache_value != NULL ) { if( libfdata_tree_node_get_timestamp( node, &node_timestamp, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve time stamp from tree node.", function ); return( -1 ); } if( libfcache_cache_value_get_identifier( cache_value, &cache_value_file_index, &cache_value_offset, &cache_value_timestamp, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve cache value identifier.", function ); return( -1 ); } } if( ( node_file_index == cache_value_file_index ) && ( node_offset == cache_value_offset ) && ( node_timestamp == cache_value_timestamp ) ) { result = 1; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( result == 0 ) { libcnotify_printf( "%s: cache: 0x%08" PRIjx " miss (entry: %d, want: %" PRIi64 ", got: %" PRIi64 ")\n", function, (intptr_t) cache, cache_entry_index, node_offset, cache_value_offset ); } else { libcnotify_printf( "%s: cache: 0x%08" PRIjx " hit (entry: %d)\n", function, (intptr_t) cache, cache_entry_index ); } } #endif } if( result == 0 ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading node at offset: %" PRIi64 " (0x%08" PRIx64 ") of size: %" PRIu64 "\n", function, node_offset, node_offset, node_size ); } #endif if( internal_tree->read_node( internal_tree->data_handle, file_io_handle, node, cache, node_file_index, node_offset, node_size, node_flags, read_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read node at offset: 0x%08" PRIx64 ".", function, node_offset ); return( -1 ); } if( ( ( ( (libfdata_internal_tree_node_t *) node )->flags & LIBFDATA_TREE_NODE_FLAG_IS_VIRTUAL ) == 0 ) && ( ( ( (libfdata_internal_tree_node_t *) node )->flags & LIBFDATA_TREE_NODE_FLAG_IS_LEAF ) != 0 ) ) { cache_entry_index = libfdata_tree_node_calculate_leaf_node_cache_entry_index( node_offset, number_of_cache_entries ); } else { cache_entry_index = libfdata_tree_node_calculate_branch_node_cache_entry_index( node_offset, number_of_cache_entries ); } if( libfcache_cache_get_value_by_index( cache, cache_entry_index, &cache_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve cache entry: %d from cache.", function, cache_entry_index ); return( -1 ); } if( cache_value != NULL ) { if( libfdata_tree_node_get_timestamp( node, &node_timestamp, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve time stamp from tree node.", function ); return( -1 ); } if( libfcache_cache_value_get_identifier( cache_value, &cache_value_file_index, &cache_value_offset, &cache_value_timestamp, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve cache value identifier.", function ); return( -1 ); } } if( ( node_file_index != cache_value_file_index ) || ( node_offset != cache_value_offset ) || ( node_timestamp != cache_value_timestamp ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing cache value.", function ); return( -1 ); } } if( libfcache_cache_value_get_value( cache_value, node_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve node value.", function ); return( -1 ); } return( 1 ); }