Пример #1
0
/* Appends a checksum error
 * Returns 1 if successful or -1 on error
 */
int libewf_chunk_table_append_checksum_error(
     libewf_chunk_table_t *chunk_table,
     uint64_t start_sector,
     uint64_t number_of_sectors,
     libcerror_error_t **error )
{
	static char *function = "libewf_chunk_table_append_checksum_error";

	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( 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 );
}
Пример #2
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 );
}
Пример #3
0
/* Reads an free map
 * Returns 1 if successful or -1 on error
 */
int libpff_free_map_read(
     libcdata_range_list_t *unallocated_block_list,
     libbfio_handle_t *file_io_handle,
     off64_t free_map_offset,
     uint8_t file_type,
     libcerror_error_t **error )
{
	uint8_t *free_map_data       = NULL;
	uint8_t *table_data          = NULL;
	static char *function        = "libpff_free_map_read";
	off64_t back_pointer_offset  = 0;
	off64_t unallocated_offset   = 0;
	size_t read_size             = 0;
	size_t unallocated_size      = 0;
	size_t allocation_block_size = 0;
	ssize_t read_count           = 0;
	uint32_t stored_checksum     = 0;
	uint32_t calculated_checksum = 0;
	uint16_t table_iterator      = 0;
	uint8_t bit_iterator         = 0;
	uint8_t free_map_entry       = 0;
	uint8_t free_map_type        = 0;
	uint8_t free_map_type_copy   = 0;
	int result                   = 0;

#if defined( HAVE_DEBUG_OUTPUT )
	uint16_t value_16bit         = 0;
#endif

	if( unallocated_block_list == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid unallocated block list.",
		 function );

		return( -1 );
	}
	if( file_io_handle == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid file IO handle.",
		 function );

		return( -1 );
	}
	if( ( file_type != LIBPFF_FILE_TYPE_32BIT )
	 && ( file_type != LIBPFF_FILE_TYPE_64BIT ) )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
		 "%s: unsupported file type.",
		 function );

		return( -1 );
	}
	if( libbfio_handle_seek_offset(
	     file_io_handle,
	     free_map_offset,
	     SEEK_SET,
	     error ) == -1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_IO,
		 LIBCERROR_IO_ERROR_SEEK_FAILED,
		 "%s: unable to seek free map offset: %" PRIi64 ".",
		 function,
		 free_map_offset );

		goto on_error;
	}
	if( file_type == LIBPFF_FILE_TYPE_32BIT )
	{
		read_size = sizeof( pff_free_map_32bit_t );
	}
	else if( file_type == LIBPFF_FILE_TYPE_64BIT )
	{
		read_size = sizeof( pff_free_map_64bit_t );
	}
	free_map_data = (uint8_t *) memory_allocate(
	                             sizeof( uint8_t ) * read_size );

	if( free_map_data == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_MEMORY,
		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
		 "%s: unable to create alloction table data.",
		 function );

		goto on_error;
	}
	read_count = libbfio_handle_read_buffer(
	              file_io_handle,
	              free_map_data,
	              read_size,
	              error );

	if( read_count != (ssize_t) read_size )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_IO,
		 LIBCERROR_IO_ERROR_READ_FAILED,
		 "%s: unable to read free map.",
		 function );

		goto on_error;
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: free map:\n",
		 function );
		libcnotify_print_data(
		 free_map_data,
		 read_size,
		 0 );
	}
#endif
	if( file_type == LIBPFF_FILE_TYPE_32BIT )
	{
		table_data         = ( (pff_free_map_32bit_t *) free_map_data )->data;
		free_map_type      = ( (pff_free_map_32bit_t *) free_map_data )->type;
		free_map_type_copy = ( (pff_free_map_32bit_t *) free_map_data )->type_copy;

		byte_stream_copy_to_uint32_little_endian(
		 ( (pff_free_map_32bit_t *) free_map_data )->back_pointer,
		 back_pointer_offset );
		byte_stream_copy_to_uint32_little_endian(
		 ( (pff_free_map_32bit_t *) free_map_data )->checksum,
		 stored_checksum );
	}
	else if( file_type == LIBPFF_FILE_TYPE_64BIT )
	{
		table_data         = ( (pff_free_map_64bit_t *) free_map_data )->data;
		free_map_type      = ( (pff_free_map_64bit_t *) free_map_data )->type;
		free_map_type_copy = ( (pff_free_map_64bit_t *) free_map_data )->type_copy;

		byte_stream_copy_to_uint32_little_endian(
		 ( (pff_free_map_64bit_t *) free_map_data )->checksum,
		 stored_checksum );
		byte_stream_copy_to_uint64_little_endian(
		 ( (pff_free_map_64bit_t *) free_map_data )->back_pointer,
		 back_pointer_offset );
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: type\t\t: 0x%02" PRIx8 "\n",
		 function,
		 free_map_type );
		libcnotify_printf(
		 "%s: type copy\t: 0x%02" PRIx8 "\n",
		 function,
		 free_map_type_copy );

		if( file_type == LIBPFF_FILE_TYPE_32BIT )
		{
			byte_stream_copy_to_uint16_little_endian(
			 ( (pff_free_map_32bit_t *) free_map_data )->signature,
			 value_16bit );
			libcnotify_printf(
			 "%s: signature\t: 0x%04" PRIx16 "\n",
			 function,
			 value_16bit );

			libcnotify_printf(
			 "%s: back pointer\t: %" PRIu64 "\n",
			 function,
			 back_pointer_offset );

			libcnotify_printf(
			 "%s: checksum\t: 0x%" PRIx32 "\n",
			 function,
			 stored_checksum );
		}
		else if( file_type == LIBPFF_FILE_TYPE_64BIT )
		{
			byte_stream_copy_to_uint16_little_endian(
			 ( (pff_free_map_64bit_t *) free_map_data )->signature,
			 value_16bit );
			libcnotify_printf(
			 "%s: signature\t: 0x%04" PRIx16 "\n",
			 function,
			 value_16bit );

			libcnotify_printf(
			 "%s: checksum\t\t: 0x%" PRIx32 "\n",
			 function,
			 stored_checksum );

			libcnotify_printf(
			 "%s: back pointer\t: %" PRIu64 "\n",
			 function,
			 back_pointer_offset );
		}
		libcnotify_printf(
		 "\n" );
	}
#endif

	if( libfmapi_checksum_calculate_weak_crc32(
	     &calculated_checksum,
	     table_data,
	     496,
	     0,
	     error ) != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
		 "%s: unable to calculate weak CRC-32.",
		 function );

		goto on_error;
	}
	if( stored_checksum != calculated_checksum )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_INPUT,
		 LIBCERROR_INPUT_ERROR_CHECKSUM_MISMATCH,
		 "%s: mismatch in checksum ( %" PRIu32 " != %" PRIu32 " ).",
		 function,
		 stored_checksum,
		 calculated_checksum );

		/* TODO implement error tollerance
		 */
		goto on_error;
	}
	if( free_map_type != free_map_type_copy )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_INPUT,
		 LIBCERROR_INPUT_ERROR_CHECKSUM_MISMATCH,
		 "%s: mismatch in allocation table type ( 0x%02" PRIx8 " != 0x%02" PRIx8 " ).",
		 function,
		 free_map_type,
		 free_map_type_copy );

		/* TODO implement error tollerance
		 */
		goto on_error;
	}
	if( ( free_map_type != LIBPFF_FREE_MAP_TYPE_DATA )
	 && ( free_map_type != LIBPFF_FREE_MAP_TYPE_PAGE ) )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
		 "%s: unsupported allocation table type: 0x%08" PRIx32 "",
		 function,
		 free_map_type );

		/* TODO implement error tollerance
		 */
		goto on_error;
	}
	/* TODO */
	if( free_map_type == LIBPFF_FREE_MAP_TYPE_PAGE )
	{
		allocation_block_size = 512;
		back_pointer_offset  -= 0x200;
	}
	else if( free_map_type == LIBPFF_FREE_MAP_TYPE_DATA )
	{
		allocation_block_size = 64;
	}
	for( table_iterator = 0;
	     table_iterator < 496;
	     table_iterator++ )
	{
		free_map_entry = table_data[ table_iterator ];

		for( bit_iterator = 0;
		     bit_iterator < 8;
		     bit_iterator++ )
		{
			if( ( free_map_entry & 0x80 ) == 0 )
			{
				if( unallocated_size == 0 )
				{
					unallocated_offset = back_pointer_offset;
				}
				unallocated_size += allocation_block_size;
			}
			else if( unallocated_size > 0 )
			{
				result = libcdata_range_list_insert_range(
				          unallocated_block_list,
				          unallocated_offset,
				          unallocated_size,
				          NULL,
				          NULL,
				          NULL,
				          error );

				if( result == -1 )
				{
					libcerror_error_set(
					 error,
					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
					 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
					 "%s: unable to append unallocated block to list.",
					 function );

					goto on_error;
				}
				unallocated_size = 0;
			}
			free_map_entry <<= 1;

			back_pointer_offset += allocation_block_size;
		}
	}
	if( unallocated_size > 0 )
	{
		result = libcdata_range_list_insert_range(
		          unallocated_block_list,
		          unallocated_offset,
		          unallocated_size,
		          NULL,
		          NULL,
		          NULL,
		          error );

		if( result == -1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
			 "%s: unable to append unallocated block to list.",
			 function );

			goto on_error;
		}
		unallocated_size = 0;
	}
	memory_free(
	 free_map_data );

	return( 1 );

on_error:
	if( free_map_data != NULL )
	{
		memory_free(
		 free_map_data );
	}
	return( -1 );
}
/* Reads an allocation table
 * Returns 1 if successful or -1 on error
 */
int libpff_allocation_table_read(
     libcdata_range_list_t *unallocated_block_list,
     libbfio_handle_t *file_io_handle,
     off64_t allocation_table_offset,
     uint8_t file_type,
     libcerror_error_t **error )
{
	uint8_t *allocation_table_data     = NULL;
	uint8_t *table_data                = NULL;
	static char *function              = "libpff_allocation_table_read";
	off64_t back_pointer_offset        = 0;
	off64_t unallocated_offset         = 0;
	size_t read_size                   = 0;
	size_t unallocated_size            = 0;
	size_t allocation_block_size       = 0;
	ssize_t read_count                 = 0;
	uint32_t stored_checksum           = 0;
	uint32_t calculated_checksum       = 0;
	uint16_t table_data_index          = 0;
	uint16_t table_data_size           = 0;
	uint8_t allocation_table_entry     = 0;
	uint8_t allocation_table_type      = 0;
	uint8_t allocation_table_type_copy = 0;
	uint8_t bit_index                  = 0;

#if defined( HAVE_DEBUG_OUTPUT )
	uint64_t value_64bit               = 0;
	uint16_t value_16bit               = 0;
#endif

	if( unallocated_block_list == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid unallocated block list.",
		 function );

		return( -1 );
	}
	if( file_io_handle == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid file IO handle.",
		 function );

		return( -1 );
	}
	if( ( file_type != LIBPFF_FILE_TYPE_32BIT )
	 && ( file_type != LIBPFF_FILE_TYPE_64BIT )
	 && ( file_type != LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
		 "%s: unsupported file type.",
		 function );

		return( -1 );
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: reading allocation table at offset: 0x%08" PRIx64 "\n",
		 function,
		 allocation_table_offset );
	}
#endif
	if( libbfio_handle_seek_offset(
	     file_io_handle,
	     allocation_table_offset,
	     SEEK_SET,
	     error ) == -1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_IO,
		 LIBCERROR_IO_ERROR_SEEK_FAILED,
		 "%s: unable to seek allocation table offset: 0x%08" PRIx64 ".",
		 function,
		 allocation_table_offset );

		goto on_error;
	}
	if( file_type == LIBPFF_FILE_TYPE_32BIT )
	{
		read_size       = sizeof( pff_allocation_table_32bit_t );
		table_data_size = 496;
	}
	else if( file_type == LIBPFF_FILE_TYPE_64BIT )
	{
		read_size       = sizeof( pff_allocation_table_64bit_t );
		table_data_size = 496;
	}
	else if( file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE )
	{
		read_size       = sizeof( pff_allocation_table_64bit_4k_page_t );
		table_data_size = 4072;
	}
	allocation_table_data = (uint8_t *) memory_allocate(
	                                     sizeof( uint8_t ) * read_size );

	if( allocation_table_data == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_MEMORY,
		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
		 "%s: unable to create alloction table data.",
		 function );

		goto on_error;
	}
	read_count = libbfio_handle_read_buffer(
	              file_io_handle,
	              allocation_table_data,
	              read_size,
	              error );

	if( read_count != (ssize_t) read_size )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_IO,
		 LIBCERROR_IO_ERROR_READ_FAILED,
		 "%s: unable to read allocation table.",
		 function );

		goto on_error;
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: allocation table:\n",
		 function );
		libcnotify_print_data(
		 allocation_table_data,
		 read_size,
		 LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
	}
#endif
	if( file_type == LIBPFF_FILE_TYPE_32BIT )
	{
		table_data                 = ( (pff_allocation_table_32bit_t *) allocation_table_data )->data;
		allocation_table_type      = ( (pff_allocation_table_32bit_t *) allocation_table_data )->type;
		allocation_table_type_copy = ( (pff_allocation_table_32bit_t *) allocation_table_data )->type_copy;

		byte_stream_copy_to_uint32_little_endian(
		 ( (pff_allocation_table_32bit_t *) allocation_table_data )->back_pointer,
		 back_pointer_offset );
		byte_stream_copy_to_uint32_little_endian(
		 ( (pff_allocation_table_32bit_t *) allocation_table_data )->checksum,
		 stored_checksum );
	}
	else if( file_type == LIBPFF_FILE_TYPE_64BIT )
	{
		table_data                 = ( (pff_allocation_table_64bit_t *) allocation_table_data )->data;
		allocation_table_type      = ( (pff_allocation_table_64bit_t *) allocation_table_data )->type;
		allocation_table_type_copy = ( (pff_allocation_table_64bit_t *) allocation_table_data )->type_copy;

		byte_stream_copy_to_uint32_little_endian(
		 ( (pff_allocation_table_64bit_t *) allocation_table_data )->checksum,
		 stored_checksum );
		byte_stream_copy_to_uint64_little_endian(
		 ( (pff_allocation_table_64bit_t *) allocation_table_data )->back_pointer,
		 back_pointer_offset );
	}
	else if( file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE )
	{
		table_data                 = ( (pff_allocation_table_64bit_4k_page_t *) allocation_table_data )->data;
		allocation_table_type      = ( (pff_allocation_table_64bit_4k_page_t *) allocation_table_data )->type;
		allocation_table_type_copy = ( (pff_allocation_table_64bit_4k_page_t *) allocation_table_data )->type_copy;

		byte_stream_copy_to_uint32_little_endian(
		 ( (pff_allocation_table_64bit_4k_page_t *) allocation_table_data )->checksum,
		 stored_checksum );
		byte_stream_copy_to_uint64_little_endian(
		 ( (pff_allocation_table_64bit_4k_page_t *) allocation_table_data )->back_pointer,
		 back_pointer_offset );
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: type\t\t: 0x%02" PRIx8 "\n",
		 function,
		 allocation_table_type );
		libcnotify_printf(
		 "%s: type copy\t\t: 0x%02" PRIx8 "\n",
		 function,
		 allocation_table_type_copy );

		if( file_type == LIBPFF_FILE_TYPE_32BIT )
		{
			byte_stream_copy_to_uint16_little_endian(
			 ( (pff_allocation_table_32bit_t *) allocation_table_data )->signature,
			 value_16bit );
			libcnotify_printf(
			 "%s: signature\t\t: 0x%04" PRIx16 "\n",
			 function,
			 value_16bit );

			libcnotify_printf(
			 "%s: back pointer\t: %" PRIu64 "\n",
			 function,
			 back_pointer_offset );

			libcnotify_printf(
			 "%s: checksum\t\t: 0x%" PRIx32 "\n",
			 function,
			 stored_checksum );
		}
		else if( ( file_type == LIBPFF_FILE_TYPE_64BIT )
		      || ( file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
		{
			if( file_type == LIBPFF_FILE_TYPE_64BIT )
			{
				byte_stream_copy_to_uint16_little_endian(
				 ( (pff_allocation_table_64bit_t *) allocation_table_data )->signature,
				 value_16bit );
			}
			else
			{
				byte_stream_copy_to_uint16_little_endian(
				 ( (pff_allocation_table_64bit_4k_page_t *) allocation_table_data )->signature,
				 value_16bit );
			}
			libcnotify_printf(
			 "%s: signature\t\t: 0x%04" PRIx16 "\n",
			 function,
			 value_16bit );

			libcnotify_printf(
			 "%s: checksum\t\t: 0x%" PRIx32 "\n",
			 function,
			 stored_checksum );

			libcnotify_printf(
			 "%s: back pointer\t: %" PRIu64 "\n",
			 function,
			 back_pointer_offset );

			if( file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE )
			{
				byte_stream_copy_to_uint64_little_endian(
				 ( (pff_allocation_table_64bit_4k_page_t *) allocation_table_data )->unknown1,
				 value_64bit );
				libcnotify_printf(
				 "%s: unknown1\t\t: 0x%08" PRIx64 "\n",
				 function,
				 value_64bit );
			}
		}
		libcnotify_printf(
		 "\n" );
	}
#endif
	if( libfmapi_checksum_calculate_weak_crc32(
	     &calculated_checksum,
	     table_data,
	     (size_t) table_data_size,
	     0,
	     error ) != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
		 "%s: unable to calculate weak CRC-32.",
		 function );

		goto on_error;
	}
	if( stored_checksum != calculated_checksum )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_INPUT,
		 LIBCERROR_INPUT_ERROR_CHECKSUM_MISMATCH,
		 "%s: mismatch in checksum ( %" PRIu32 " != %" PRIu32 " ).",
		 function,
		 stored_checksum,
		 calculated_checksum );

/* TODO implement error tollerance */
		goto on_error;
	}
	if( allocation_table_type != allocation_table_type_copy )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_INPUT,
		 LIBCERROR_INPUT_ERROR_CHECKSUM_MISMATCH,
		 "%s: mismatch in allocation table type ( 0x%02" PRIx8 " != 0x%02" PRIx8 " ).",
		 function,
		 allocation_table_type,
		 allocation_table_type_copy );

/* TODO implement error tollerance */
		goto on_error;
	}
	if( ( allocation_table_type != LIBPFF_ALLOCATION_TABLE_TYPE_DATA )
	 && ( allocation_table_type != LIBPFF_ALLOCATION_TABLE_TYPE_PAGE ) )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
		 "%s: unsupported allocation table type: 0x%08" PRIx32 "",
		 function,
		 allocation_table_type );

/* TODO implement error tollerance */
		goto on_error;
	}
	if( allocation_table_type == LIBPFF_ALLOCATION_TABLE_TYPE_PAGE )
	{
		/* The page type allocation has not yet been seen i.c.w. 4k pages */
		if( file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
			 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
			 "%s: unsupported file type.",
			 function );

			goto on_error;
		}
		allocation_block_size = 512;
		back_pointer_offset  -= 0x200;
	}
	else if( allocation_table_type == LIBPFF_ALLOCATION_TABLE_TYPE_DATA )
	{
		allocation_block_size = 64;
	}
	for( table_data_index = 0;
	     table_data_index < table_data_size;
	     table_data_index++ )
	{
		allocation_table_entry = table_data[ table_data_index ];

		for( bit_index = 0;
		     bit_index < 8;
		     bit_index++ )
		{
			if( ( allocation_table_entry & 0x80 ) == 0 )
			{
				if( unallocated_size == 0 )
				{
					unallocated_offset = back_pointer_offset;
				}
				unallocated_size += allocation_block_size;
			}
			else if( unallocated_size > 0 )
			{
#if defined( HAVE_DEBUG_OUTPUT )
				if( libcnotify_verbose != 0 )
				{
					libcnotify_printf(
					 "%s: unallocated block: 0x%08" PRIx64 " - 0x%08" PRIx64 " (%" PRIu64 ")\n",
					 function,
					 unallocated_offset,
					 unallocated_offset + unallocated_size,
					 unallocated_size );
				}
#endif
				if( libcdata_range_list_insert_range(
				     unallocated_block_list,
				     unallocated_offset,
				     unallocated_size,
				     NULL,
				     NULL,
				     NULL,
				     error ) != 1 )
				{
					libcerror_error_set(
					 error,
					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
					 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
					 "%s: unable to append unallocated block to list.",
					 function );

					goto on_error;
				}
				unallocated_size = 0;
			}
			allocation_table_entry <<= 1;

			back_pointer_offset += allocation_block_size;
		}
	}
	if( unallocated_size > 0 )
	{
#if defined( HAVE_DEBUG_OUTPUT )
		if( libcnotify_verbose != 0 )
		{
			libcnotify_printf(
			 "%s: unallocated block: 0x%08" PRIx64 " - 0x%08" PRIx64 " (%" PRIu64 ")\n",
			 function,
			 unallocated_offset,
			 unallocated_offset + unallocated_size,
			 unallocated_size );
		}
#endif
		if( libcdata_range_list_insert_range(
		     unallocated_block_list,
		     unallocated_offset,
		     unallocated_size,
		     NULL,
		     NULL,
		     NULL,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
			 "%s: unable to append unallocated block to list.",
			 function );

			goto on_error;
		}
		unallocated_size = 0;
	}
	memory_free(
	 allocation_table_data );

	return( 1 );

on_error:
	if( allocation_table_data != NULL )
	{
		memory_free(
		 allocation_table_data );
	}
	return( -1 );
}