Example #1
0
/* Retrieves the chunk data of a chunk at a specific offset
 * Adds a checksum error if the data is corrupted
 * Returns 1 if successful or -1 on error
 */
int libewf_chunk_table_get_chunk_data_by_offset(
     libewf_chunk_table_t *chunk_table,
     uint64_t chunk_index,
     libewf_io_handle_t *io_handle,
     libbfio_pool_t *file_io_pool,
     libewf_media_values_t *media_values,
     libewf_segment_table_t *segment_table,
     libfdata_range_list_t *delta_chunks_range_list,
     libfcache_cache_t *chunk_groups_cache,
     libfcache_cache_t *chunks_cache,
     off64_t offset,
     libewf_chunk_data_t **chunk_data,
     off64_t *chunk_data_offset,
     libcerror_error_t **error )
{
	libewf_segment_file_t *segment_file = NULL;
	libfdata_list_t *chunks_list        = NULL;
	static char *function               = "libewf_chunk_table_get_chunk_data_by_offset";
	off64_t chunk_offset                = 0;
	off64_t chunk_group_data_offset     = 0;
	off64_t segment_file_data_offset    = 0;
	size_t chunk_data_size              = 0;
	uint64_t start_sector               = 0;
	uint64_t number_of_sectors          = 0;
	uint32_t segment_number             = 0;
	int chunk_groups_list_index         = 0;
	int chunks_list_index               = 0;
	int result                          = 0;

	if( chunk_table == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid chunk table.",
		 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( media_values == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid media values.",
		 function );

		return( -1 );
	}
	if( chunk_data == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid chunk data.",
		 function );

		return( -1 );
	}
	if( chunk_data_offset == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid chunk data offset.",
		 function );

		return( -1 );
	}
	if( delta_chunks_range_list != NULL )
	{
		result = libfdata_range_list_get_element_value_at_offset(
			  delta_chunks_range_list,
			  (intptr_t *) file_io_pool,
			  chunks_cache,
			  offset,
			  chunk_data_offset,
			  (intptr_t **) chunk_data,
			  0,
			  error );

		if( result == -1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
			 "%s: unable to retrieve chunk: %" PRIu64 " from delta chunks range list.",
			 function,
			 chunk_index );

			return( -1 );
		}
	}
	if( result == 0 )
	{
		result = libewf_chunk_table_get_segment_file_chunk_group_by_offset(
			  chunk_table,
			  file_io_pool,
			  segment_table,
			  chunk_groups_cache,
			  offset,
			  &segment_number,
			  &segment_file_data_offset,
			  &segment_file,
			  &chunk_groups_list_index,
			  &chunk_group_data_offset,
			  &chunks_list,
			  error );

		if( result == -1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
			 "%s: unable to retrieve segment file chunk group at offset: %" PRIi64 ".",
			 function,
			 offset );

			return( -1 );
		}
		if( result != 0 )
		{
			if( chunks_list == NULL )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
				 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
				 "%s: missing chunks list: %d.",
				 function,
				 chunk_groups_list_index );

				return( -1 );
			}
			result = libfdata_list_get_element_value_at_offset(
				  chunks_list,
				  (intptr_t *) file_io_pool,
				  chunks_cache,
				  chunk_group_data_offset,
				  &chunks_list_index,
				  chunk_data_offset,
				  (intptr_t **) chunk_data,
				  0,
				  error );

			if( result == -1 )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
				 "%s: unable to retrieve chunk: %" PRIu64 " data from chunk group: %d in segment file: %" PRIu32 " at offset: %" PRIi64 ".",
				 function,
				 chunk_index,
				 chunk_groups_list_index,
				 segment_number,
				 segment_file_data_offset );

				return( -1 );
			}
		}
	}
	if( result != 0 )
	{
		if( *chunk_data == NULL )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
			 "%s: missing chunk: %" PRIu64 " data.",
			 function,
			 chunk_index );

			return( -1 );
		}
		if( libewf_chunk_data_unpack(
		     *chunk_data,
		     media_values->chunk_size,
		     io_handle->compression_method,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_GENERIC,
			 "%s: unable to unpack chunk: %" PRIu64 " data.",
			 function,
			 chunk_index );

			return( -1 );
		}
		if( ( ( *chunk_data )->range_flags & LIBEWF_RANGE_FLAG_IS_CORRUPTED ) != 0 )
		{
			if( io_handle->zero_on_error != 0 )
			{
				if( memory_set(
				     ( *chunk_data )->data,
				     0,
				     ( *chunk_data )->data_size ) == NULL )
				{
					libcerror_error_set(
					 error,
					 LIBCERROR_ERROR_DOMAIN_MEMORY,
					 LIBCERROR_MEMORY_ERROR_SET_FAILED,
					 "%s: unable to zero chunk: %" PRIu64 " data.",
					 function,
					 chunk_index );

					return( -1 );
				}
			}
			chunk_offset = offset - *chunk_data_offset;
		}
	}
	else
	{
		chunk_offset    = (off64_t) chunk_index * media_values->chunk_size;
		chunk_data_size = media_values->chunk_size;

		if( (size64_t) ( chunk_offset + chunk_data_size ) > media_values->media_size )
		{
			chunk_data_size = (size_t) ( media_values->media_size - chunk_offset );
		}
		if( libewf_chunk_data_initialize_clear_data(
		     chunk_data,
		     chunk_data_size,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
			 "%s: unable to create chunk: %" PRIu64 " data.",
			 function,
			 chunk_index );

			return( -1 );
		}
		if( *chunk_data == NULL )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
			 "%s: missing chunk data: %" PRIu64 ".",
			 function,
			 chunk_index );

			return( -1 );
		}
		( *chunk_data )->data_size    = chunk_data_size;
		( *chunk_data )->range_flags |= LIBEWF_RANGE_FLAG_IS_CORRUPTED;
	}
	if( ( ( *chunk_data )->range_flags & LIBEWF_RANGE_FLAG_IS_CORRUPTED ) != 0 )
	{
		/* Add checksum error
		 */
		start_sector      = chunk_offset / media_values->bytes_per_sector;
		number_of_sectors = media_values->sectors_per_chunk;

		if( ( start_sector + number_of_sectors ) > (uint64_t) media_values->number_of_sectors )
		{
			number_of_sectors = (uint64_t) media_values->number_of_sectors - start_sector;
		}
		if( libcdata_range_list_insert_range(
		     chunk_table->checksum_errors,
		     start_sector,
		     number_of_sectors,
		     NULL,
		     NULL,
		     NULL,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
			 "%s: unable to insert checksum error in range list.",
			 function );

			return( -1 );
		}
	}
	return( 1 );
}
Example #2
0
/* Reads a buffer from the data chunk
 * It applies decompression if necessary and validates the chunk checksum
 * This function should be used after libewf_handle_read_data_chunk
 * Returns the number of bytes read, 0 when no longer data can be read or -1 on error
 */
ssize_t libewf_data_chunk_read_buffer(
         libewf_data_chunk_t *data_chunk,
         void *buffer,
         size_t buffer_size,
         libcerror_error_t **error )
{
	libewf_internal_data_chunk_t *internal_data_chunk = NULL;
	static char *function                             = "libewf_data_chunk_read_buffer";
	ssize_t read_count                                = 0;

	if( data_chunk == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid data chunk.",
		 function );

		return( -1 );
	}
	internal_data_chunk = (libewf_internal_data_chunk_t *) data_chunk;

	if( internal_data_chunk->chunk_data == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
		 "%s: invalid data chunk - missing chunk data.",
		 function );

		return( -1 );
	}
#if defined( HAVE_LIBEWF_MULTI_THREAD_SUPPORT )
	if( libcthreads_read_write_lock_grab_for_write(
	     internal_data_chunk->read_write_lock,
	     error ) != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
		 "%s: unable to grab read/write lock for writing.",
		 function );

		return( -1 );
	}
#endif
	if( ( internal_data_chunk->chunk_data->range_flags & LIBEWF_RANGE_FLAG_IS_PACKED ) != 0 )
	{
/* TODO optimize to unpack directly to buffer */
		if( libewf_chunk_data_unpack(
		     internal_data_chunk->chunk_data,
		     internal_data_chunk->io_handle,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_GENERIC,
			 "%s: unable to unpack chunk: %" PRIu64 " data.",
			 function,
			 internal_data_chunk->chunk_index );

			goto on_error;
		}
	}
	read_count = libewf_chunk_data_read_buffer(
	              internal_data_chunk->chunk_data,
	              buffer,
	              buffer_size,
	              error );

	if( read_count < 0 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_IO,
		 LIBCERROR_IO_ERROR_READ_FAILED,
		 "%s: unable to read chunk: %" PRIu64 " data.",
		 function,
		 internal_data_chunk->chunk_index );

		goto on_error;
	}
#if defined( HAVE_LIBEWF_MULTI_THREAD_SUPPORT )
	if( libcthreads_read_write_lock_release_for_write(
	     internal_data_chunk->read_write_lock,
	     error ) != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
		 "%s: unable to release read/write lock for writing.",
		 function );

		return( -1 );
	}
#endif
	return( read_count );

on_error:
#if defined( HAVE_LIBEWF_MULTI_THREAD_SUPPORT )
	libcthreads_read_write_lock_release_for_write(
	 internal_data_chunk->read_write_lock,
	 NULL );
#endif
	return( -1 );
}