Пример #1
0
Файл: file.c Проект: anhkgg/temu
/* Opens an EWF file for reading
 */
LIBEWF_HANDLE *libewf_open_read( LIBEWF_HANDLE *handle, const char *filename )
{
	int file_descriptor;
	EWF_FILE_HEADER *file_header;
	uint16_t fields_segment;

	if( handle == NULL )
	{
		LIBEWF_FATAL_PRINT( "libewf_open_read: incorrect handle.\n" );
	}
	file_descriptor = open( filename, O_RDONLY );

	if( file_descriptor == -1 )
	{
		LIBEWF_FATAL_PRINT( "libewf_open: unable to open file: %s\n", filename );
	}
	file_header = ewf_file_header_read( file_descriptor );

	if( file_header == NULL )
	{
		LIBEWF_FATAL_PRINT( "libewf_open_read: incorrect file header in: %s.\n", filename );
	}
	fields_segment = convert_16bit( file_header->fields_segment );

	LIBEWF_VERBOSE_PRINT( "libewf_open_read: added segment file: %s with file descriptor: %d with segment number: %" PRIu16 ".\n", filename, file_descriptor, fields_segment );

	handle->segment_table = libewf_segment_table_set_values( handle->segment_table, fields_segment, filename, file_descriptor );

	ewf_file_header_free( file_header );

	LIBEWF_VERBOSE_PRINT( "libewf_open_read: open successful.\n" );

	return( handle );
}
Пример #2
0
Файл: file.c Проект: anhkgg/temu
/* Builds the index from the files
 */
LIBEWF_HANDLE *libewf_build_index( LIBEWF_HANDLE *handle )
{
	EWF_SECTION *last_section = NULL;
	uint32_t segment          = 0;

	if( handle == NULL )
	{
		LIBEWF_FATAL_PRINT( "libewf_build_index: incorrect handle\n" );
	}
	if( handle->index_build != 0 )
	{
		LIBEWF_FATAL_PRINT( "libewf_build_index: index has already been build\n" );
	}
	for( segment = 1; segment < handle->segment_table->amount; segment++ )
	{
		LIBEWF_VERBOSE_PRINT( "libewf_build_index: building index for segment: %" PRIu32 "\n", segment );

		last_section = libewf_sections_read_segment( handle, segment );
	}
	/* Check to see if we are done */
	if( ( last_section == NULL ) || ( !ewf_section_is_type_done( last_section ) ) )
	{
		LIBEWF_FATAL_PRINT( "libewf_build_index: no ending section, cannot find the last segment file\n" );
	}
	ewf_section_free( last_section );

	handle->index_build = 1;

	LIBEWF_VERBOSE_PRINT( "libewf_build_index: index successful build.\n" );

	return( handle );
}
Пример #3
0
Файл: file.c Проект: anhkgg/temu
/* Opens an EWF file
 * For reading files should contain all filenames that make up an EWF image
 * For writing files should contain the base of the filename, extentions like .e01 will be automatically added
 */
LIBEWF_HANDLE *libewf_open( const char **filenames, uint32_t file_amount, uint8_t flags )
{
	uint32_t iterator;
	LIBEWF_HANDLE *handle = NULL;

	if( flags == LIBEWF_OPEN_READ )
	{
		/* 1 additional entry required because
		 * entry [ 0 ] is not used for reading
		 */
		handle = libewf_handle_alloc( file_amount + 1 );

		for( iterator = 0; iterator < file_amount; iterator++ )
		{
			libewf_open_read( handle, filenames[ iterator ] );
		}
		handle = libewf_build_index( handle );
	}
	else if( flags == LIBEWF_OPEN_WRITE )
	{
		/* Allocate 2 entries
		 * entry [ 0 ] is used for the base filename
		 */
		handle = libewf_handle_alloc( 2 );

		libewf_open_write( handle, filenames[ 0 ] );
	}
	else
	{
		LIBEWF_FATAL_PRINT( "libewf_open: unsupported flags.\n" );
	}
	LIBEWF_VERBOSE_PRINT( "libewf_open: open successful.\n" );

	return( handle );
}
Пример #4
0
/* Creates a printable string of the stored md5 hash
 * Returns 1 if successful, 0 if no md5 hash is stored, -1 on error
 */
int8_t libewf_get_stored_md5_hash( LIBEWF_HANDLE *handle, LIBEWF_CHAR *string, size_t length )
{
	LIBEWF_INTERNAL_HANDLE *internal_handle = NULL;
	int8_t result                           = 0;

	if( handle == NULL )
	{
		LIBEWF_WARNING_PRINT( "libewf_get_stored_md5_hash: invalid handle.\n" );

		return( -1 );
	}
	internal_handle = (LIBEWF_INTERNAL_HANDLE *) handle;

	if( internal_handle->stored_md5_hash == NULL )
	{
		LIBEWF_VERBOSE_PRINT( "libewf_get_stored_md5_hash: MD5 hash was not set.\n" );

		return( 0 );
	}
	result = libewf_string_copy_from_digest_hash( string, length, internal_handle->stored_md5_hash, EWF_DIGEST_HASH_SIZE_MD5 );

	if( result == -1 )
	{
		LIBEWF_WARNING_PRINT( "libewf_get_stored_md5_hash: unable to create MD5 hash string.\n" );
	}
	return( result );
}
Пример #5
0
/* Converts the EWF digest hash to a printable string
 * Returns 1 if successful, 0 if hash was not set, or -1 on error
 */
int8_t libewf_string_copy_from_digest_hash( LIBEWF_CHAR *string, size_t size_string, EWF_DIGEST_HASH *digest_hash, size_t size_digest_hash )
{
	size_t string_iterator      = 0;
	size_t digest_hash_iterator = 0;
	uint8_t digest_digit        = 0;

	if( string == NULL )
	{
		LIBEWF_WARNING_PRINT( "libewf_string_copy_from_digest_hash: invalid string.\n" );

		return( -1 );
	}
	if( ( size_string > (size_t) SSIZE_MAX ) || ( size_digest_hash > (size_t) SSIZE_MAX ) )
	{
		LIBEWF_WARNING_PRINT( "libewf_string_copy_from_digest_hash: invalid size value exceeds maximum.\n" );

		return( -1 );
	}
	/* The string requires space for 2 characters per digest hash digit and a end of string
	 */
	if( size_string < ( ( 2 * size_digest_hash ) + 1 ) )
	{
		LIBEWF_WARNING_PRINT( "libewf_string_copy_from_digest_hash: string too small.\n" );

		return( -1 );
	}
	if( digest_hash == NULL )
	{
		LIBEWF_VERBOSE_PRINT( "libewf_string_copy_from_digest_hash: invalid digest hash.\n" );

		return( 0 );
	}
	for( digest_hash_iterator = 0; digest_hash_iterator < size_digest_hash; digest_hash_iterator++ )
	{
		digest_digit = digest_hash[ digest_hash_iterator ] / 16;

		if( digest_digit <= 9 )
		{
			string[ string_iterator++ ] = (LIBEWF_CHAR) ( (uint8_t) '0' + digest_digit );
		}
		else
		{
			string[ string_iterator++ ] = (LIBEWF_CHAR) ( (uint8_t) 'a' + ( digest_digit - 10 ) );
		}
		digest_digit = digest_hash[ digest_hash_iterator ] % 16;

		if( digest_digit <= 9 )
		{
			string[ string_iterator++ ] = (LIBEWF_CHAR) ( (uint8_t) '0' + digest_digit );
		}
		else
		{
			string[ string_iterator++ ] = (LIBEWF_CHAR) ( (uint8_t) 'a' + ( digest_digit - 10 ) );
		}
	}
	string[ string_iterator ] = (LIBEWF_CHAR) '\0';

	return( 1 );
}
Пример #6
0
/* Writes the ltree to a file descriptor
 * Returns the amount of bytes written, or -1 on error
 */
ssize_t ewf_ltree_write( EWF_LTREE *ltree, int file_descriptor )
{
	ssize_t count = 0;
	size_t size   = EWF_LTREE_SIZE;

	if( ltree == NULL )
	{
		LIBEWF_VERBOSE_PRINT( "ewf_ltree_write: invalid ltree.\n" );

		return( -1 );
	}
	count = libewf_common_write( file_descriptor, ltree, size );

	if( count < (ssize_t) size )
	{
		return( -1 );
	}
	return( count );
}
Пример #7
0
/* Writes the sectors to a file descriptor
 * Returns a -1 on error, the amount of bytes written on success
 */
ssize_t ewf_error2_sectors_write( EWF_ERROR2_SECTOR *sectors, int file_descriptor, uint32_t amount )
{
	ssize_t count;
	size_t size = EWF_ERROR2_SECTOR_SIZE * amount;

	if( sectors == NULL )
	{
		LIBEWF_VERBOSE_PRINT( "ewf_error2_sectors_write: invalid sectors.\n" );

		return( -1 );
	}
	count = write( file_descriptor, sectors, size );

	if( count < size )
	{
		return( -1 );
	}
	return( count );
}
Пример #8
0
/* Sets the values for a specific segment
 */
LIBEWF_SEGMENT_TABLE *libewf_segment_table_set_values( LIBEWF_SEGMENT_TABLE *segment_table, uint32_t segment, const char *filename, int file_descriptor )
{
	size_t filename_size;

	if( segment_table == NULL )
	{
		LIBEWF_FATAL_PRINT( "libewf_segment_table_set_values: invalid segment_table\n" );
	}
	/* Check if additional entries should be allocated
	 */
	if( segment > segment_table->amount )
	{
		LIBEWF_VERBOSE_PRINT( "libewf_segment_table_set_values: allocating additional segment_table entries\n" );

		/* Segment has an offset of 1 so an additional values entry is needed
		 */
		segment_table = libewf_segment_table_values_realloc( segment_table, ( segment + 1 ) );
	}
	if( segment_table->filename[ segment ] != NULL )
	{
		LIBEWF_FATAL_PRINT( "libewf_segment_table_set_values: duplicate segments not supported: segment %d in %s was already specified in %s.\n", segment, filename, segment_table->filename[ segment ] );
	}
	filename_size = strlen( filename );

	/* One additional byte for the end of string character is needed
	 */
	segment_table->filename[ segment ] = (char *) malloc( sizeof( char ) * ( filename_size + 1 ) );

	if( segment_table->filename[ segment ] == NULL )
	{
		LIBEWF_FATAL_PRINT( "libewf_segment_table_set_values: unable to allocate filename\n" );
	}
	memcpy( segment_table->filename[ segment ], filename, filename_size );

	/* Make sure the string is terminated
	 */
	segment_table->filename[ segment ][ filename_size ] = '\0';

	segment_table->file_descriptor[ segment ] = file_descriptor;

	return( segment_table );
}
Пример #9
0
/* Writes the table to a file descriptor
 * Returns a -1 on error, the amount of bytes written on success
 */
ssize_t ewf_table_write( EWF_TABLE *table, int file_descriptor )
{
	EWF_CRC crc;
	ssize_t count;
	size_t size = EWF_TABLE_SIZE;

	if( table == NULL )
	{
		LIBEWF_VERBOSE_PRINT( "ewf_table_write: invalid table.\n" );

		return( -1 );
	}
	crc = ewf_crc( (void *) table, ( size - EWF_CRC_SIZE ), 1 );

	revert_32bit( crc, table->crc );

	count = write( file_descriptor, table, size );

	if( count < size )
	{
		return( -1 );
	}
	return( count );
}
Пример #10
0
/* Writes the volume to a file descriptor
 * Returns a -1 on error, the amount of bytes written on success
 */
ssize_t ewf_volume_write( EWF_VOLUME *volume, int file_descriptor )
{
	EWF_CRC crc;
	ssize_t count;
	size_t size = EWF_VOLUME_SIZE;

	if( volume == NULL )
	{
		LIBEWF_VERBOSE_PRINT( "ewf_volume_write: invalid volume.\n" );

		return( -1 );
	}
	crc = ewf_crc( (void *) volume, ( size - EWF_CRC_SIZE ), 1 );

	revert_32bit( crc, volume->crc );

	count = write( file_descriptor, volume, size );

	if( count < size )
	{
		return( -1 );
	}
	return( count );
}
Пример #11
0
/* Writes the error2 to a file descriptor, without the first sector
 * this should be written by the sectors write function
 * Returns a -1 on error, the amount of bytes written on success
 */
ssize_t ewf_error2_write( EWF_ERROR2 *error2, int file_descriptor )
{
	EWF_CRC crc;
	ssize_t count;
	size_t size = EWF_ERROR2_SIZE;

	if( error2 == NULL )
	{
		LIBEWF_VERBOSE_PRINT( "ewf_error2_write: invalid error2.\n" );

		return( -1 );
	}
	crc = ewf_crc( (void *) error2, ( size - EWF_CRC_SIZE ), 1 );

	revert_32bit( crc, error2->crc );

	count = write( file_descriptor, error2, size );

	if( count < size )
	{
		return( -1 );
	}
	return( count );
}
Пример #12
0
/* Writes the hash to a file descriptor
 * Returns a -1 on error, the amount of bytes written on success
 */
ssize_t ewf_hash_write( EWF_HASH *hash, int file_descriptor )
{
	EWF_CRC crc;
	ssize_t count;
	size_t size = EWF_HASH_SIZE;

	if( hash == NULL )
	{
		LIBEWF_VERBOSE_PRINT( "ewf_hash_write: invalid hash.\n" );

		return( -1 );
	}
	crc = ewf_crc( (void *) hash, ( size - EWF_CRC_SIZE ), 1 );

	revert_32bit( crc, hash->crc );

	count = write( file_descriptor, hash, size );

	if( count < size )
	{
		return( -1 );
	}
	return( count );
}
Пример #13
0
/* Writes the offsets to a file descriptor
 * Returns a -1 on error, the amount of bytes written on success
 */
ssize_t ewf_table_offsets_write( EWF_TABLE_OFFSET *offsets, int file_descriptor, uint32_t amount )
{
	EWF_CRC crc;
	ssize_t count;
	ssize_t crc_count;
	size_t size = EWF_TABLE_OFFSET_SIZE * amount;

	if( offsets == NULL )
	{
		LIBEWF_VERBOSE_PRINT( "ewf_table_offsets_write: invalid offsets.\n" );

		return( -1 );
	}
	count = write( file_descriptor, offsets, size );

	if( count < size )
	{
		return( -1 );
	}
	crc       = ewf_crc( offsets, size, 1 );
	crc_count = ewf_crc_write( crc, file_descriptor );

	return( count + crc_count );
}
Пример #14
0
/* Calculates the MD5 hash and creates a printable string of the calculated md5 hash
 * Returns 1 if successful, -1 on error
 */
int8_t libewf_calculate_md5_hash( LIBEWF_HANDLE *handle, LIBEWF_CHAR *string, size_t length )
{
	LIBEWF_INTERNAL_HANDLE *internal_handle = NULL;
	uint8_t *data                           = NULL;
	off_t offset                            = 0;
	ssize_t count                           = 0;
	uint32_t iterator                       = 0;

	if( handle == NULL )
	{
		LIBEWF_WARNING_PRINT( "libewf_calculate_md5_hash: invalid handle.\n" );

		return( -1 );
	}
	internal_handle = (LIBEWF_INTERNAL_HANDLE *) internal_handle;

	if( internal_handle->media == NULL )
	{
		LIBEWF_WARNING_PRINT( "libewf_calculate_md5_hash: invalid handle - missing subhandle media.\n" );

		return( -1 );
	}
	if( string == NULL )
	{
		LIBEWF_VERBOSE_PRINT( "libewf_calculate_md5_hash: invalid string.\n" );

		return( -1 );
	}
	if( length < LIBEWF_STRING_DIGEST_HASH_LENGTH_MD5 )
	{
		LIBEWF_VERBOSE_PRINT( "libewf_calculate_md5_hash: string too small.\n" );

		return( -1 );
	}
	if( internal_handle->index_build == 0 )
	{
		LIBEWF_WARNING_PRINT( "libewf_calculate_md5_hash: index was not build.\n" );

		return( -1 );
	}
	if( internal_handle->calculated_md5_hash == NULL )
	{
		data = (uint8_t *) libewf_common_alloc( internal_handle->media->chunk_size * sizeof( uint8_t ) );

		if( data == NULL )
		{
			LIBEWF_WARNING_PRINT( "libewf_calculate_md5_hash: unable to allocate data.\n" );

			return( -1 );
		}
		for( iterator = 0; iterator <= internal_handle->offset_table->last; iterator++ )
		{
			offset = iterator * internal_handle->media->chunk_size;
			count  = libewf_read_random( handle, data, internal_handle->media->chunk_size, offset );

			if( count == -1 )
			{
				LIBEWF_WARNING_PRINT( "libewf_calculate_md5_hash: unable to read chunk.\n" );

				libewf_common_free( data );

				return( -1 );
			}
			if( count > (ssize_t) INT32_MAX )
			{
				LIBEWF_WARNING_PRINT( "libewf_calculate_md5_hash: invalid count - only values below 2^32 supported.\n" );

				libewf_common_free( data );

				return( -1 );
			}
		}
		libewf_common_free( data ) ;
	}
	else
	{
		LIBEWF_VERBOSE_PRINT( "libewf_calculate_md5_hash: MD5 hash already calculated.\n" );
	}
	if( libewf_string_copy_from_digest_hash( string, length, internal_handle->calculated_md5_hash, EWF_DIGEST_HASH_SIZE_MD5 ) != 1 )
	{
		LIBEWF_WARNING_PRINT( "libewf_calculate_md5_hash: unable to set MD5 hash string.\n" );

		return( -1 );
	}
	return( 1 );
}
Пример #15
0
/* Seeks a certain chunk offset within the EWF file(s)
 * Returns the segment file offset if seek is successful, or -1 on error
 */
off_t libewf_seek_chunk( LIBEWF_INTERNAL_HANDLE *internal_handle, uint32_t chunk )
{
	off_t offset            = 0;
	uint16_t segment_number = 0;
	int file_descriptor     = 0;

	if( internal_handle == NULL )
	{
		LIBEWF_WARNING_PRINT( "libewf_seek_chunk: invalid handle.\n" );

		return( -1 );
	}
	if( internal_handle->segment_table == NULL )
	{
		LIBEWF_WARNING_PRINT( "libewf_seek_chunk: invalid handle - missing segment table.\n" );

		return( -1 );
	}
	if( internal_handle->offset_table == NULL )
	{
		LIBEWF_WARNING_PRINT( "libewf_seek_chunk: invalid handle - missing offset table.\n" );

		return( -1 );
	}
	if( internal_handle->chunk_cache == NULL )
	{
		LIBEWF_WARNING_PRINT( "libewf_seek_chunk: invalid handle - missing chunk cache.\n" );

		return( -1 );
	}
	if( internal_handle->index_build == 0 )
	{
		LIBEWF_WARNING_PRINT( "libewf_seek_chunk: index was not build.\n" );

		return( -1 );
	}
	if( chunk >= internal_handle->offset_table->amount )
	{
		LIBEWF_WARNING_PRINT( "libewf_seek_chunk: chunk: %" PRIu32 " not in offset table.\n", chunk );

		return( -1 );
	}
	file_descriptor = internal_handle->offset_table->file_descriptor[ chunk ];
	offset          = internal_handle->offset_table->offset[ chunk ];
	segment_number  = internal_handle->offset_table->segment_number[ chunk ];

	LIBEWF_VERBOSE_PRINT( "libewf_seek_chunk: seek file descriptor: %d, for segment: %" PRIu16 " for offset: %jd.\n",
	                      file_descriptor, segment_number, offset );

	if( offset > (off_t) INT32_MAX )
	{
		LIBEWF_WARNING_PRINT( "libewf_seek_chunk: invalid chunk offset only values below 2^32 are supported.\n" );

		return( -1 );
	}
	if( internal_handle->segment_table->file_offset[ segment_number ] != offset )
	{
		if( libewf_common_lseek( file_descriptor, offset, SEEK_SET ) == -1 )
		{
			LIBEWF_WARNING_PRINT( "libewf_seek_chunk: cannot find offset: %jd.\n", offset );

			return( -1 );
		}
		internal_handle->segment_table->file_offset[ segment_number ] = offset;
	}
	internal_handle->current_chunk = chunk;

	return( offset );
}
Пример #16
0
/* Copies a multi byte UTF16 string to a single byte ASCII string
 * Returns 1 if successful, on -1 on error
 */
int8_t libewf_string_copy_utf16_to_ascii( LIBEWF_CHAR *utf16_string, size_t size_utf16, LIBEWF_CHAR* ascii_string, size_t size_ascii )
{
	size_t utf16_iterator = 2;
	size_t ascii_iterator = 0;
	uint8_t byte_order    = 0;

	if( utf16_string == NULL )
	{
		LIBEWF_WARNING_PRINT( "libewf_string_copy_utf16_to_ascii: invalid UTF16 string.\n" );

		return( -1 );
	}
	if( ascii_string == NULL )
	{
		LIBEWF_WARNING_PRINT( "libewf_string_copy_utf16_to_ascii: invalid ASCII string.\n" );

		return( -1 );
	}
	if( ( size_utf16 > (size_t) SSIZE_MAX ) || ( size_ascii > (size_t) SSIZE_MAX ) )
	{
		LIBEWF_WARNING_PRINT( "libewf_string_copy_utf16_to_ascii: invalid size value exceeds maximum.\n" );

		return( -1 );
	}
	/* The UTF16 string contains twice as much bytes needed for the ASCII string
	 * with two additional bytes representing byte order
	 */
	if( size_ascii < ( ( size_utf16 - 2 ) / 2 ) )
	{
		LIBEWF_WARNING_PRINT( "libewf_string_copy_utf16_to_ascii: ASCII string too small.\n" );

		return( -1 );
	}
	/* Check if UTF16 string is in big or little endian
	 */
	if( ( (uint8_t) utf16_string[ 0 ] == 0xff ) && ( (uint8_t) utf16_string[ 1 ] == 0xfe ) )
	{
		byte_order = LIBEWF_STRING_LITTLE_ENDIAN;
	}
	else if( ( (uint8_t) utf16_string[ 0 ] == 0xfe ) && ( (uint8_t) utf16_string[ 1 ] == 0xff ) )
	{
		byte_order = LIBEWF_STRING_BIG_ENDIAN;
	}
	else
	{
		LIBEWF_VERBOSE_PRINT( "libewf_string_copy_utf16_to_ascii: no byte order in UTF16 string.\n" );

		if( ( utf16_string[ 0 ] == (LIBEWF_CHAR) '\0' ) && ( utf16_string[ 1 ] != (LIBEWF_CHAR) '\0' ) )
		{
			byte_order = LIBEWF_STRING_LITTLE_ENDIAN;
		}
		else if( ( utf16_string[ 0 ] != (LIBEWF_CHAR) '\0' ) && ( utf16_string[ 1 ] == (LIBEWF_CHAR) '\0' ) )
		{
			byte_order = LIBEWF_STRING_LITTLE_ENDIAN;
		}
		else
		{
			LIBEWF_WARNING_PRINT( "libewf_string_copy_utf16_to_ascii: unable to determine byte order in UTF16 string.\n" );

			return( -1 );
		}
		utf16_iterator = 0;
	}
	/* Convert string
	 */
	while( utf16_iterator < size_utf16 )
	{
		if( byte_order == LIBEWF_STRING_BIG_ENDIAN )
		{
			if( utf16_string[ utf16_iterator ] == (LIBEWF_CHAR) '\0' )
			{
				ascii_string[ ascii_iterator ] = utf16_string[ utf16_iterator + 1 ];
			}
			else
			{
				/* Add a place holder character
				 */
				ascii_string[ ascii_iterator ] = '_';
			}
		}
		else if( byte_order == LIBEWF_STRING_LITTLE_ENDIAN )
		{
			if( utf16_string[ utf16_iterator + 1 ] == (LIBEWF_CHAR) '\0' )
			{
				ascii_string[ ascii_iterator ] = utf16_string[ utf16_iterator ];
			}
			else
			{
				/* Add a place holder character
				 */
				ascii_string[ ascii_iterator ] = '_';
			}
		}
		utf16_iterator += 2;
		ascii_iterator += 1;
	}
	ascii_string[ size_ascii - 1 ] = (LIBEWF_CHAR) '\0';

	return( 1 );
}
Пример #17
0
/* Opens EWF file(s)
 * For reading files should contain all filenames that make up an EWF image
 * For writing files should contain the base of the filename, extentions like .e01 will be automatically added
 * Returns a pointer to the new instance of handle, NULL on error
 */
LIBEWF_HANDLE *libewf_open( char * const filenames[], uint16_t file_amount, uint8_t flags )
{
	EWF_FILE_HEADER file_header;

	LIBEWF_INTERNAL_HANDLE *internal_handle = NULL;
	char *error_string                      = NULL;
	uint32_t iterator                       = 0;
	uint16_t fields_segment                 = 0;
	int file_descriptor                     = 0;

	if( ( flags == LIBEWF_OPEN_READ ) || ( flags == LIBEWF_OPEN_READ_WRITE ) )
	{
		/* 1 additional entry required because
		 * entry [ 0 ] is not used for reading
		 */
		internal_handle = libewf_internal_handle_alloc( ( file_amount + 1 ), flags );

		if( internal_handle == NULL )
		{
			LIBEWF_WARNING_PRINT( "libewf_open: unable to create handle.\n" );

			return( NULL );
		}
		if( internal_handle->segment_table == NULL )
		{
			LIBEWF_WARNING_PRINT( "libewf_open: invalid handle - missing segment table.\n" );

			libewf_internal_handle_free( internal_handle );

			return( NULL );
		}
		for( iterator = 0; iterator < file_amount; iterator++ )
		{
			file_descriptor = libewf_common_open( filenames[ iterator ], flags );

			if( file_descriptor == -1 )
			{
				error_string = libewf_common_strerror( errno );

				if( error_string == NULL )
				{
					LIBEWF_WARNING_PRINT( "libewf_open: unable to open file: %s.\n", filenames[ iterator ] );
				}
				else
				{
					LIBEWF_WARNING_PRINT( "libewf_open: unable to open file: %s with error: %s.\n", filenames[ iterator ], error_string );

					libewf_common_free( error_string );
				}
				libewf_internal_handle_free( internal_handle );

				return( NULL );
			}
			if( ewf_file_header_read( &file_header, file_descriptor ) <= -1 )
			{
				LIBEWF_WARNING_PRINT( "libewf_open: invalid file header in: %s.\n", filenames[ iterator ] );

				libewf_internal_handle_free( internal_handle );

				return( NULL );
			}
			if( ewf_file_header_check_signature( file_header.signature ) == 0 )
			{
				LIBEWF_WARNING_PRINT( "libewf_open: file signature does not match.\n" );

				libewf_internal_handle_free( internal_handle );

				return( NULL );
			}
			if( libewf_endian_convert_16bit( &fields_segment, file_header.fields_segment ) != 1 )
			{
				LIBEWF_WARNING_PRINT( "libewf_open: unable to convert fields segment value.\n" );

				libewf_internal_handle_free( internal_handle );

				return( NULL );
			}
			LIBEWF_VERBOSE_PRINT( "libewf_open: added segment file: %s with file descriptor: %d with segment number: %" PRIu16 ".\n",
				filenames[ iterator ], file_descriptor, fields_segment );

			if( libewf_segment_table_set_filename( internal_handle->segment_table, fields_segment, filenames[ iterator ], libewf_common_string_length( filenames[ iterator ] ) ) != 1 )
			{
				LIBEWF_WARNING_PRINT( "libewf_open: unable to set filename in segment table.\n" );

				libewf_internal_handle_free( internal_handle );

				return( NULL );
			}
			if( libewf_segment_table_set_file_descriptor( internal_handle->segment_table, fields_segment, file_descriptor ) != 1 )
			{
				LIBEWF_WARNING_PRINT( "libewf_open: unable to set file descriptor in segment table.\n" );

				libewf_internal_handle_free( internal_handle );

				return( NULL );
			}
		}
		if( libewf_read_build_index( internal_handle ) != 1 )
		{
			LIBEWF_WARNING_PRINT( "libewf_open: unable to create index.\n" );

			libewf_internal_handle_free( internal_handle );

			return( NULL );
		}
	}
	else if( flags == LIBEWF_OPEN_WRITE )
	{
		/* Allocate 2 entries
		 * entry [ 0 ] is used for the base filename
		 */
		internal_handle = libewf_internal_handle_alloc( 1, flags );

		if( internal_handle == NULL )
		{
			LIBEWF_WARNING_PRINT( "libewf_open: unable to create handle.\n" );

			return( NULL );
		}
		if( internal_handle->segment_table == NULL )
		{
			LIBEWF_WARNING_PRINT( "libewf_open: invalid handle - missing segment table.\n" );

			libewf_internal_handle_free( internal_handle );

			return( NULL );
		}
		if( libewf_segment_table_set_filename( internal_handle->segment_table, 0, filenames[ iterator ], libewf_common_string_length( filenames[ iterator ] ) ) != 1 )
		{
			LIBEWF_WARNING_PRINT( "libewf_open: unable to set filename in segment table.\n" );

			libewf_internal_handle_free( internal_handle );

			return( NULL );
		}
		if( libewf_segment_table_set_file_descriptor( internal_handle->segment_table, 0, -1 ) != 1 )
		{
			LIBEWF_WARNING_PRINT( "libewf_open: unable to set file descriptor in segment table.\n" );

			libewf_internal_handle_free( internal_handle );

			return( NULL );
		}
	}
	else
	{
		LIBEWF_WARNING_PRINT( "libewf_open: unsupported flags.\n" );

		return( NULL );
	}
	LIBEWF_VERBOSE_PRINT( "libewf_open: open successful.\n" );

	return( (LIBEWF_HANDLE *) internal_handle );
}
Пример #18
0
/* Reads media data from the last current into a buffer
 * This function swaps byte pairs if specified
 * Returns the amount of bytes read, or -1 on error
 */
ssize_t libewf_read_buffer( LIBEWF_HANDLE *handle, void *buffer, size_t size )
{
	LIBEWF_INTERNAL_HANDLE *internal_handle = NULL;
	ssize_t chunk_read_count                = 0;
	ssize_t total_read_count                = 0;
	size_t chunk_data_size                  = 0;
	int8_t chunk_cache_used                 = 0;

	if( handle == NULL )
	{
		LIBEWF_WARNING_PRINT( "libewf_read_buffer: invalid handle.\n" );

		return( -1 );
	}
	internal_handle = (LIBEWF_INTERNAL_HANDLE *) handle;

	if( internal_handle->chunk_cache == NULL )
	{
		LIBEWF_WARNING_PRINT( "libewf_read_buffer: invalid chunk cache.\n" );

		return( -1 );
	}
	if( internal_handle->index_build == 0 )
	{
		LIBEWF_WARNING_PRINT( "libewf_read_buffer: index was not build.\n" );

		return( -1 );
	}
	if( buffer == NULL )
	{
		LIBEWF_WARNING_PRINT( "libewf_read_buffer: invalid buffer.\n" );

		return( -1 );
	}
	if( buffer == internal_handle->chunk_cache->compressed )
	{
		LIBEWF_WARNING_PRINT( "libewf_read_buffer: invalid buffer - chunk cache compressed cannot be used as buffer.\n");

		return( -1 );
	}
	if( size > (size_t) SSIZE_MAX )
	{
		LIBEWF_WARNING_PRINT( "libewf_read_buffer: invalid size value exceeds maximum.\n" );

		return( -1 );
	}
	LIBEWF_VERBOSE_PRINT( "libewf_read_buffer: reading size: %zu.\n", size );

	/* Check if chunk cache passthrough is used
	 * if the chunk cache is used as the chunk data buffer
	 */
	chunk_cache_used = (int8_t) ( buffer == internal_handle->chunk_cache->data );

	/* Reallocate the chunk cache if the chunk size is not the default chunk size
	 * this prevents multiple reallocations of the chunk cache
	 */
	chunk_data_size = internal_handle->media->chunk_size + EWF_CRC_SIZE;

	if( chunk_data_size > internal_handle->chunk_cache->allocated_size )
	{
		LIBEWF_VERBOSE_PRINT( "libewf_read_buffer: reallocating chunk data size: %zu.\n", chunk_data_size );

		if( libewf_internal_handle_chunk_cache_realloc( internal_handle, chunk_data_size ) == NULL )
		{
			LIBEWF_WARNING_PRINT( "libewf_read_buffer: unable to reallocate chunk cache.\n");

			return( -1 );
		}
		/* Adjust chunk data buffer if necessary
		 */
		if( ( chunk_cache_used == 1 ) && ( buffer != internal_handle->chunk_cache->data ) )
		{
			buffer = (void *) internal_handle->chunk_cache->data;
		}
	}
	while( size > 0 )
	{
		chunk_read_count = libewf_read_chunk( internal_handle, internal_handle->current_chunk, internal_handle->current_chunk_offset, (void *) &( (uint8_t *) buffer )[ total_read_count ], size );

		/* libewf_read_chunk could relocate the chunk cache
		 * correct buffer is chunk cache passthrough is used
		 */
		if( ( chunk_cache_used == 1 ) && ( buffer != internal_handle->chunk_cache->data ) )
		{
			buffer = (void *) internal_handle->chunk_cache->data;
		}
		if( chunk_read_count <= -1 )
		{
			LIBEWF_WARNING_PRINT( "libewf_read_buffer: unable to read data from chunk.\n" );

			return( -1 );
		}
		else if( chunk_read_count == 0 )
		{
			break;
		}
		size                                  -= chunk_read_count;
		total_read_count                      += chunk_read_count;
		internal_handle->current_chunk_offset += (uint32_t) chunk_read_count;

		if( internal_handle->current_chunk_offset == internal_handle->media->chunk_size )
		{
			internal_handle->current_chunk_offset = 0;
			internal_handle->current_chunk       += 1;
		}
		else if( internal_handle->current_chunk_offset > internal_handle->media->chunk_size )
		{
			LIBEWF_WARNING_PRINT( "libewf_read_buffer: invalid current chunk offset.\n" );

			return( -1 );
		}
	}
	return( total_read_count );
}
Пример #19
0
/* Builds the index (section list and offset table) from the input files
 * Returns 1 if successful, or -1 on error
 */
int8_t libewf_read_build_index( LIBEWF_INTERNAL_HANDLE *internal_handle )
{
	EWF_SECTION *last_section = NULL;
	uint16_t segment_number   = 0;

	if( internal_handle == NULL )
	{
		LIBEWF_WARNING_PRINT( "libewf_read_build_index: invalid handle.\n" );

		return( -1 );
	}
	if( internal_handle->index_build != 0 )
	{
		LIBEWF_WARNING_PRINT( "libewf_read_build_index: index has already been build.\n" );

		return( -1 );
	}
	if( libewf_internal_handle_read_initialize( internal_handle ) != 1 )
	{
		LIBEWF_WARNING_PRINT( "libewf_read_build_index: unable to initialize read values in handle.\n" );

		return( -1 );
	}
	for( segment_number = 1; segment_number < internal_handle->segment_table->amount; segment_number++ )
	{
		if( last_section != NULL )
		{
			libewf_common_free( last_section );
		}
		LIBEWF_VERBOSE_PRINT( "libewf_read_build_index: building index for segment number: %" PRIu32 ".\n", segment_number );

		last_section = libewf_read_sections_from_segment( internal_handle, segment_number );
	}
	/* Check to see if the done section has been found
	 */
	if( last_section == NULL )
	{
		LIBEWF_WARNING_PRINT( "libewf_read_build_index: invalid last section.\n" );

		return( -1 );
	}
	else if( ewf_section_is_type_done( last_section ) == 0 )
	{
		LIBEWF_WARNING_PRINT( "libewf_read_build_index: unable to find the last segment file (done section).\n" );

		libewf_common_free( last_section );

		return( -1 );
	}
	libewf_common_free( last_section );

	/* Determine the EWF file format
	 */
	if( libewf_internal_handle_determine_format( internal_handle ) != 1 )
	{
		LIBEWF_WARNING_PRINT( "libewf_read_build_index: unable to determine file format.\n" );
	}
	LIBEWF_VERBOSE_PRINT( "libewf_read_build_index: index successful build.\n" );

	/* Calculate the media size
	 */
	internal_handle->media->media_size = (uint64_t) internal_handle->media->amount_of_sectors * (uint64_t) internal_handle->media->bytes_per_sector;

	/* Flag that the index was build
	 */
	internal_handle->index_build = 1;

	return( 1 );
}
Пример #20
0
/* Reads a certain chunk of data from the segment file(s)
 * Will read until the requested size is filled or the entire chunk is read
 * This function swaps byte pairs if specified
 * Returns the amount of bytes read, 0 if no bytes can be read, or -1 on error
 */
ssize_t libewf_read_chunk( LIBEWF_INTERNAL_HANDLE *internal_handle, uint32_t chunk, uint32_t chunk_offset, void *buffer, size_t size )
{
	EWF_CHUNK *chunk_data       = NULL;
	EWF_CHUNK *chunk_read       = NULL;
	EWF_CRC calculated_crc      = 0;
	EWF_CRC stored_crc          = 0;
#if defined( HAVE_WIDE_CHARACTER_TYPE ) && defined( HAVE_WIDE_CHARACTER_SUPPORT_FUNCTIONS )
	wchar_t *filename           = NULL;
#else
	char *filename              = NULL;
#endif
	ssize_t chunk_read_count    = 0;
	ssize_t crc_read_count      = 0;
	size_t chunk_data_size      = 0;
	size_t bytes_available      = 0;
	size_t md5_hash_size        = 0;
	uint16_t segment_number     = 0;
	int8_t chunk_cache_used     = 0;
	int8_t result               = 0;
	uint8_t percentage          = 0;
	int file_descriptor         = 0;

	if( internal_handle == NULL )
	{
		LIBEWF_WARNING_PRINT( "libewf_read_chunk: invalid handle.\n" );

		return( -1 );
	}
	if( internal_handle->media == NULL )
	{
		LIBEWF_WARNING_PRINT( "libewf_read_chunk: invalid handle - missing subhandle media.\n" );

		return( -1 );
	}
	if( internal_handle->read == NULL )
	{
		LIBEWF_WARNING_PRINT( "libewf_read_chunk: invalid handle - missing subhandle read.\n" );

		return( -1 );
	}
	if( internal_handle->offset_table == NULL )
	{
		LIBEWF_WARNING_PRINT( "libewf_read_chunk: invalid handle - missing offset table.\n" );

		return( -1 );
	}
	if( internal_handle->segment_table == NULL )
	{
		LIBEWF_WARNING_PRINT( "libewf_read_chunk: invalid handle - missing segment table.\n" );

		return( -1 );
	}
	if( internal_handle->chunk_cache == NULL )
	{
		LIBEWF_WARNING_PRINT( "libewf_read_chunk: invalid chunk cache.\n" );

		return( -1 );
	}
	if( internal_handle->index_build == 0 )
	{
		LIBEWF_WARNING_PRINT( "libewf_read_chunk: index was not build.\n" );

		return( -1 );
	}
	if( buffer == NULL )
	{
		LIBEWF_WARNING_PRINT( "libewf_read_chunk: invalid buffer.\n" );

		return( -1 );
	}
	if( buffer == internal_handle->chunk_cache->compressed )
	{
		LIBEWF_WARNING_PRINT( "libewf_read_chunk: invalid buffer - same as chunk cache compressed.\n" );

		return( -1 );
	}
	/* Check if the chunk is available
	 */
	if( chunk >= internal_handle->offset_table->amount )
	{
		return( 0 );
	}
	/* Check if the chunk is cached
	 */
	if( ( internal_handle->chunk_cache->chunk != chunk ) || ( internal_handle->chunk_cache->cached == 0 ) )
	{
		file_descriptor = internal_handle->offset_table->file_descriptor[ chunk ];
		segment_number  = internal_handle->offset_table->segment_number[ chunk ];

		/* Check if chunk cache passthrough is used
		 * if the chunk cache is used as the chunk data buffer
		 */
		chunk_cache_used = (int8_t) ( buffer == internal_handle->chunk_cache->data );

		/* Determine the size of the chunk including the CRC
		 */
		chunk_data_size = internal_handle->offset_table->size[ chunk ];

		/* Make sure the chunk cache is large enough
		 */
		if( chunk_data_size > internal_handle->chunk_cache->allocated_size )
		{
			LIBEWF_VERBOSE_PRINT( "libewf_read_chunk: reallocating chunk data size: %zu.\n", chunk_data_size );

			if( libewf_internal_handle_chunk_cache_realloc( internal_handle, chunk_data_size ) == NULL )
			{
				LIBEWF_WARNING_PRINT( "libewf_read_chunk: unable to reallocate chunk cache.\n");

				return( -1 );
			}
			/* Adjust chunk data buffer if necessary
			 */
			if( ( chunk_cache_used == 1 ) && ( buffer != internal_handle->chunk_cache->data ) )
			{
				buffer = internal_handle->chunk_cache->data;
			}
		}
		chunk_data = internal_handle->chunk_cache->data;

#ifdef HAVE_BUFFER_PASSTHROUGH
		/* Determine if the chunk data should be put directly in the buffer
		 */
		if( ( buffer != internal_handle->chunk_cache->data ) && ( chunk_offset == 0 ) && ( size >= (uint64_t) internal_handle->media->chunk_size ) )
		{
			chunk_data = (EWF_CHUNK *) buffer;
		}
#endif
		/* Determine if the chunk data should be directly read into chunk data buffer
		 * or to use the intermediate storage for a compressed chunk
		 */
		if( internal_handle->offset_table->compressed[ chunk ] == 1 )
		{
			chunk_read = internal_handle->chunk_cache->compressed;
		}
		else
		{
			chunk_read = chunk_data;
		}
		/* If buffer passthrough is used the CRC is read seperately
		 */
		if( ( chunk_read != internal_handle->chunk_cache->compressed ) && ( chunk_read != internal_handle->chunk_cache->data ) )
		{
			chunk_data_size -= EWF_CRC_SIZE;
		}
		/* Make sure the file offset is in the right place
		 */
		if( libewf_seek_chunk( internal_handle, chunk ) <= -1 )
		{
			LIBEWF_WARNING_PRINT( "libewf_read_chunk: unable to seek chunk.\n");

			return( -1 );
		}
		/* Read the chunk data
		 */
		chunk_read_count = ewf_chunk_read( chunk_read, file_descriptor, chunk_data_size );

		if( chunk_read_count <= -1 )
		{
			LIBEWF_WARNING_PRINT( "libewf_read_chunk: unable to read chunk.\n");

			return( -1 );
		}
		internal_handle->segment_table->file_offset[ segment_number ] += (off_t) chunk_read_count;

		if( ( internal_handle->offset_table->last > 0 ) && ( chunk > 0 ) )
		{
			percentage = (uint8_t) ( (uint32_t) ( chunk * 100 ) / internal_handle->offset_table->last );
		}
		/* Determine if the chunk is not compressed
		 */
		if( internal_handle->offset_table->compressed[ chunk ] == 0 )
		{
			LIBEWF_VERBOSE_PRINT( "libewf_read_chunk: chunk %" PRIu32 " of %" PRIu32 " (%" PRIu8 "%%) is UNCOMPRESSED.\n", ( chunk + 1 ), internal_handle->offset_table->amount, percentage );

			/* If buffer passthrough is used the CRC needs to be read seperately
			 */
			if( ( chunk_read != internal_handle->chunk_cache->compressed ) && ( chunk_read != internal_handle->chunk_cache->data ) )
			{
				crc_read_count = ewf_crc_read( &stored_crc, file_descriptor );

				if( crc_read_count != (ssize_t) EWF_CRC_SIZE )
				{
#if defined( HAVE_WIDE_CHARACTER_TYPE ) && defined( HAVE_WIDE_CHARACTER_SUPPORT_FUNCTIONS )
					filename = libewf_segment_table_get_wide_filename( internal_handle->segment_table, segment_number );
#else
					filename = libewf_segment_table_get_filename( internal_handle->segment_table, segment_number );
#endif

					if( filename == NULL )
					{
						LIBEWF_WARNING_PRINT( "libewf_read_chunk: error reading CRC of chunk: %" PRIu32 " from segment file: %" PRIu16 ".\n",
							chunk, segment_number );
					}
					else
					{
#if defined( HAVE_WIDE_CHARACTER_TYPE ) && defined( HAVE_WIDE_CHARACTER_SUPPORT_FUNCTIONS )
						LIBEWF_WARNING_PRINT( "libewf_read_chunk: error reading CRC of chunk: %" PRIu32 " from segment file: %" PRIu16 " (%ls).\n",
							chunk, segment_number, filename );
#else
						LIBEWF_WARNING_PRINT( "libewf_read_chunk: error reading CRC of chunk: %" PRIu32 " from segment file: %" PRIu16 " (%s).\n",
							chunk, segment_number, filename );
#endif
					}
					return( -1 );
				}
				internal_handle->segment_table->file_offset[ segment_number ] += (off_t) crc_read_count;
			}
			/* Otherwise convert the last 4 bytes of the chunk cache
			 */
			else
			{
				if( libewf_endian_convert_32bit( &stored_crc, &chunk_data[ chunk_data_size - EWF_CRC_SIZE ] ) != 1 )
				{
					LIBEWF_WARNING_PRINT( "libewf_read_chunk: unable to convert stored CRC value.\n" );

					return( -1 );
				}
				chunk_data_size -= (uint32_t) EWF_CRC_SIZE;
			}
			/* Calculate the CRC
			 */
			if( ewf_crc_calculate( &calculated_crc, (uint8_t *) chunk_data, chunk_data_size, 1 ) != 1 )
			{
				LIBEWF_WARNING_PRINT( "libewf_read_chunk: unable to calculate CRC.\n" );

				return( -1 );
			}
			LIBEWF_VERBOSE_PRINT( "libewf_read_chunk: CRC for chunk: %" PRIu32 " (in file: %" PRIu32 ", calculated: %" PRIu32 ").\n", ( chunk + 1 ), stored_crc, calculated_crc );

			if( stored_crc != calculated_crc )
			{
				LIBEWF_WARNING_PRINT( "libewf_read_chunk: CRC does not match for chunk: %" PRIu32 " (in file: %" PRIu32 ", calculated: %" PRIu32 ").\n", chunk, stored_crc, calculated_crc );

#ifdef WIPEONERROR
				/* The chunk data is wiped
				 */
				if( libewf_common_memset( chunk_read, 0, internal_handle->media->chunk_size ) == NULL )
				{
					LIBEWF_WARNING_PRINT( "libewf_read_chunk: unable to wipe chunk data.\n" );

					return( -1 );
				}
#endif
				if( libewf_internal_handle_add_crc_error_chunk( internal_handle, chunk ) != 1 )
				{
					LIBEWF_WARNING_PRINT( "libewf_read_chunk: unable to set CRC error chunk.\n" );

					return( -1 );
				}
				if( internal_handle->error_tollerance < LIBEWF_ERROR_TOLLERANCE_COMPENSATE )
				{
					return( -1 );
				}
			}
		}
		/* Determine if the chunk is compressed
		 */
		else if( internal_handle->offset_table->compressed[ chunk ] == 1 )
		{
			chunk_data_size = internal_handle->media->chunk_size + EWF_CRC_SIZE;
			result          = ewf_chunk_uncompress( chunk_data, &chunk_data_size, chunk_read, chunk_read_count );

			LIBEWF_VERBOSE_PRINT( "libewf_read_chunk: chunk %" PRIu32 " of %" PRIu32 " (%" PRIu8 "%%) is COMPRESSED.\n", ( chunk + 1 ), internal_handle->offset_table->amount, percentage );

			if( result != 1 )
			{
				LIBEWF_WARNING_PRINT( "libewf_read_chunk: unable to uncompress chunk.\n" );

#ifdef WIPEONERROR
				/* The chunk data is wiped
				 */
				if( libewf_common_memset( chunk_data, 0, internal_handle->media->chunk_size ) == NULL )
				{
					LIBEWF_WARNING_PRINT( "libewf_read_chunk: unable to wipe chunk data.\n" );

					return( -1 );
				}
#endif
				if( libewf_internal_handle_add_crc_error_chunk( internal_handle, chunk ) != 1 )
				{
					LIBEWF_WARNING_PRINT( "libewf_read_chunk: unable to set CRC error chunk.\n" );

					return( -1 );
				}
				if( internal_handle->error_tollerance < LIBEWF_ERROR_TOLLERANCE_COMPENSATE )
				{
					return( -1 );
				}
			}
		}
		else
		{
			LIBEWF_WARNING_PRINT( "libewf_read_chunk: unsupported compressed chunk value.\n" );

			return( -1 );
		}
		/* Check if the chunk was processed in the MD5 hash calculation
		 */
		if( internal_handle->offset_table->hashed[ chunk ] != 1 )
		{
			if( libewf_md5_update( &internal_handle->md5_context, chunk_data, chunk_data_size ) != 1 )
			{
				LIBEWF_WARNING_PRINT( "libewf_read_chunk: unable to update MD5 context.\n" );

				if( internal_handle->error_tollerance < LIBEWF_ERROR_TOLLERANCE_COMPENSATE )
				{
					return( -1 );
				}
			}
			internal_handle->offset_table->hashed[ chunk ] = 1;
		}
		/* Check if the last chunk was processed and finalize MD5 hash
		 */
		if( chunk == ( internal_handle->offset_table->amount - 1 ) )
		{
			md5_hash_size = EWF_DIGEST_HASH_SIZE_MD5;

			if( internal_handle->calculated_md5_hash == NULL )
			{
				internal_handle->calculated_md5_hash = (EWF_DIGEST_HASH *) libewf_common_alloc( md5_hash_size );

				if( internal_handle->calculated_md5_hash == NULL )
				{
					LIBEWF_WARNING_PRINT( "libewf_read_chunk: unable to created calculated MD5 hash.\n" );

					return( -1 );
				}
			}
			if( ( libewf_md5_finalize( &internal_handle->md5_context, internal_handle->calculated_md5_hash, &md5_hash_size ) != 1 )
			 || ( md5_hash_size != EWF_DIGEST_HASH_SIZE_MD5 ) )
			{
				LIBEWF_WARNING_PRINT( "libewf_read_chunk: unable to finalize MD5 context.\n" );

				if( internal_handle->error_tollerance < LIBEWF_ERROR_TOLLERANCE_COMPENSATE )
				{
					return( -1 );
				}
			}
		}
		/* Swap bytes after MD5 calculation
		 */
		if( ( internal_handle->swap_byte_pairs == 1 ) && ( libewf_endian_swap_byte_pairs( chunk_data, chunk_data_size ) != 1 ) )
		{
			LIBEWF_WARNING_PRINT( "libewf_read_chunk: unable to swap byte pairs.\n" );

			return( -1 );
		}
		/* Flag that the chunk was cached
		 */
		if( chunk_data == internal_handle->chunk_cache->data )
		{
			internal_handle->chunk_cache->chunk  = chunk;
			internal_handle->chunk_cache->amount = chunk_data_size;
			internal_handle->chunk_cache->offset = 0;
			internal_handle->chunk_cache->cached = 1;
		}
	}
	else
	{
		chunk_data      = internal_handle->chunk_cache->data;
		chunk_data_size = internal_handle->chunk_cache->amount;
	}
	/* Determine the available amount of data within the cached chunk
	 */
	if( chunk_data_size < chunk_offset )
	{
		LIBEWF_WARNING_PRINT( "libewf_read_chunk: chunk offset exceeds amount of bytes available in chunk.\n" );

		return( -1 );
	}
	bytes_available = chunk_data_size - chunk_offset;

	/* Correct the available amount of bytes is larger than the requested amount of bytes
	 */
	if( (uint64_t) bytes_available > size )
	{
		bytes_available = (uint32_t) size;
	}
	if( bytes_available > (uint64_t) INT32_MAX )
	{
		LIBEWF_WARNING_PRINT( "libewf_read_chunk: invalid available amount of bytes only values below 2^32 are supported.\n" );

		return( -1 );
	}
	/* If the data was read into the chunk cache copy it to the buffer
	 */
	if( chunk_data == internal_handle->chunk_cache->data )
	{
		/* Copy the relevant data to buffer
		 */
		if( ( bytes_available > 0 ) && ( libewf_common_memcpy( buffer, &chunk_data[ chunk_offset ], bytes_available ) == NULL ) )
		{
			LIBEWF_WARNING_PRINT( "libewf_read_chunk: unable to set chunk data in buffer.\n" );

			return( -1 );
		}
	}
	return( (int32_t) bytes_available );
}