Пример #1
0
/* 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 );
}
Пример #2
0
/* 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 );
}
Пример #3
0
/* 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 );
}