/* Reads a chunk
 * Callback function for the chunk table list
 * Returns 1 if successful or -1 on error
 */
int libewf_chunk_table_read_chunk(
     intptr_t *io_handle,
     libbfio_pool_t *file_io_pool,
     libmfdata_list_element_t *list_element,
     libfcache_cache_t *cache,
     int file_io_pool_entry,
     off64_t element_data_offset,
     size64_t element_data_size,
     uint32_t element_data_flags,
     uint8_t read_flags LIBEWF_ATTRIBUTE_UNUSED,
     libcerror_error_t **error )
{
	libewf_chunk_data_t *chunk_data = NULL;
	static char *function           = "libewf_chunk_table_read_chunk";
	ssize_t read_count              = 0;

#if defined( HAVE_DEBUG_OUTPUT )
	int element_index               = 0;
#endif

	LIBEWF_UNREFERENCED_PARAMETER( read_flags )

	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( element_data_size > (size64_t) SSIZE_MAX )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
		 "%s: invalid element data size value exceeds maximum.",
		 function );

		return( -1 );
	}
	if( ( element_data_flags & LIBMFDATA_RANGE_FLAG_IS_SPARSE ) != 0 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
		 "%s: unsupported element data flags.",
		 function );

		return( -1 );
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		if( libmfdata_list_element_get_element_index(
		     list_element,
		     &element_index,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
			 "%s: unable to retrieve element index from list element.",
			 function );

			goto on_error;
		}
		if( ( element_data_flags & LIBMFDATA_RANGE_FLAG_IS_COMPRESSED ) != 0 )
		{
			libcnotify_printf(
			 "%s: reading compressed chunk: %d from file IO pool entry: %d at offset: %" PRIi64 " of size: %" PRIu64 "\n",
			 function,
			 element_index,
			 file_io_pool_entry,
			 element_data_offset,
			 element_data_size );
		}
		else
		{
			libcnotify_printf(
			 "%s: reading uncompressed chunk: %d from file IO pool entry: %d at offset: %" PRIi64 " of size: %" PRIu64 "\n",
			 function,
			 element_index,
			 file_io_pool_entry,
			 element_data_offset,
			 element_data_size );
		}
	}
#endif
	if( libbfio_pool_seek_offset(
	     file_io_pool,
	     file_io_pool_entry,
	     element_data_offset,
	     SEEK_SET,
	     error ) == -1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_IO,
		 LIBCERROR_IO_ERROR_SEEK_FAILED,
		 "%s: unable to seek chunk offset: %" PRIi64 " in file IO pool entry: %d.",
		 function,
		 element_data_offset,
		 file_io_pool_entry );

		goto on_error;
	}
	if( libewf_chunk_data_initialize(
	     &chunk_data,
	     (size_t) element_data_size,
	     error ) != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
		 "%s: unable to create chunk data.",
		 function );

		goto on_error;
	}
	if( chunk_data == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
		 "%s: missing chunk data.",
		 function );

		goto on_error;
	}
	read_count = libbfio_pool_read_buffer(
		      file_io_pool,
		      file_io_pool_entry,
		      chunk_data->data,
		      (size_t) element_data_size,
		      error );

	if( read_count != (ssize_t) element_data_size )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_IO,
		 LIBCERROR_IO_ERROR_READ_FAILED,
		 "%s: unable to read chunk data.",
		 function );

		goto on_error;
	}
	chunk_data->data_size = (size_t) read_count;

	if( ( element_data_flags & LIBMFDATA_RANGE_FLAG_IS_COMPRESSED ) != 0 )
	{
		chunk_data->is_compressed = 1;
	}
	chunk_data->is_packed = 1;

	if( libmfdata_list_element_set_element_value(
	     list_element,
	     cache,
	     (intptr_t *) chunk_data,
	     (int (*)(intptr_t **, libcerror_error_t **)) &libewf_chunk_data_free,
	     LIBMFDATA_LIST_ELEMENT_VALUE_FLAG_MANAGED,
	     error ) != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
		 "%s: unable to set chunk data as element value.",
		 function );

		goto on_error;
	}
	return( 1 );

on_error:
	if( chunk_data != NULL )
	{
		libewf_chunk_data_free(
		 &chunk_data,
		 NULL );
	}
	return( -1 );
}
/* Reads a certain chunk of data
 * Adds a checksum error if the data is corrupted
 * Returns 1 if successful or -1 on error
 */
int libewf_read_io_handle_read_chunk_data(
    libewf_read_io_handle_t *read_io_handle,
    libbfio_pool_t *file_io_pool,
    libewf_media_values_t *media_values,
    libmfdata_list_t *chunk_table_list,
    libmfcache_cache_t *chunk_table_cache,
    int chunk_index,
    off64_t chunk_offset,
    libewf_chunk_data_t **chunk_data,
    liberror_error_t **error )
{
    static char *function      = "libewf_read_io_handle_read_chunk_data";
    size_t chunk_size          = 0;
    uint64_t start_sector      = 0;
    uint32_t number_of_sectors = 0;
    int result                 = 0;

    if( read_io_handle == NULL )
    {
        liberror_error_set(
            error,
            LIBERROR_ERROR_DOMAIN_ARGUMENTS,
            LIBERROR_ARGUMENT_ERROR_INVALID_VALUE,
            "%s: invalid read IO handle.",
            function );

        return( -1 );
    }
    if( media_values == NULL )
    {
        liberror_error_set(
            error,
            LIBERROR_ERROR_DOMAIN_ARGUMENTS,
            LIBERROR_ARGUMENT_ERROR_INVALID_VALUE,
            "%s: invalid media values.",
            function );

        return( -1 );
    }
    if( chunk_data == NULL )
    {
        liberror_error_set(
            error,
            LIBERROR_ERROR_DOMAIN_ARGUMENTS,
            LIBERROR_ARGUMENT_ERROR_INVALID_VALUE,
            "%s: invalid chunk data.",
            function );

        return( -1 );
    }
    /* This function will expand element groups
     */
    result = libmfdata_list_get_element_value_by_index(
                 chunk_table_list,
                 file_io_pool,
                 chunk_table_cache,
                 chunk_index,
                 (intptr_t **) chunk_data,
                 0,
                 error );

    if( result != 1 )
    {
        liberror_error_set(
            error,
            LIBERROR_ERROR_DOMAIN_RUNTIME,
            LIBERROR_RUNTIME_ERROR_GET_FAILED,
            "%s: unable to retrieve chunk data: %d.",
            function,
            chunk_index );

#if defined( HAVE_DEBUG_OUTPUT )
        if( libnotify_verbose != 0 )
        {
            if( ( error != NULL )
                    && ( *error != NULL ) )
            {
                libnotify_print_error_backtrace(
                    *error );
            }
        }
#endif
        liberror_error_free(
            error );

        chunk_size = media_values->chunk_size;

        if( (size64_t) ( chunk_offset + chunk_size ) > media_values->media_size )
        {
            chunk_size = (size_t) ( media_values->media_size - chunk_offset );
        }
        if( libewf_chunk_data_initialize(
                    chunk_data,
                    chunk_size,
                    error ) != 1 )
        {
            liberror_error_set(
                error,
                LIBERROR_ERROR_DOMAIN_RUNTIME,
                LIBERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
                "%s: unable to create chunk data.",
                function );

            return( -1 );
        }
        if( *chunk_data == NULL )
        {
            liberror_error_set(
                error,
                LIBERROR_ERROR_DOMAIN_RUNTIME,
                LIBERROR_RUNTIME_ERROR_VALUE_MISSING,
                "%s: missing chunk data: %d.",
                function,
                chunk_index );

            return( -1 );
        }
        ( *chunk_data )->data_size  = chunk_size;
        ( *chunk_data )->is_corrupt = 1;

        if( memory_set(
                    ( *chunk_data )->data,
                    0,
                    ( *chunk_data )->data_size ) == NULL )
        {
            liberror_error_set(
                error,
                LIBERROR_ERROR_DOMAIN_MEMORY,
                LIBERROR_MEMORY_ERROR_SET_FAILED,
                "%s: unable to zero chunk data.",
                function );

            libewf_chunk_data_free(
                chunk_data,
                NULL );

            return( -1 );
        }
        if( libmfdata_list_set_element_by_index(
                    chunk_table_list,
                    chunk_index,
                    -1,
                    chunk_offset,
                    chunk_size,
                    0,
                    error ) != 1 )
        {
            liberror_error_set(
                error,
                LIBERROR_ERROR_DOMAIN_RUNTIME,
                LIBERROR_RUNTIME_ERROR_GET_FAILED,
                "%s: unable to set chunk: %d in table.",
                function,
                chunk_index );

            libewf_chunk_data_free(
                chunk_data,
                NULL );

            return( -1 );
        }
        if( libmfdata_list_set_element_value_by_index(
                    chunk_table_list,
                    chunk_table_cache,
                    chunk_index,
                    (intptr_t *) *chunk_data,
                    (int (*)(intptr_t **, liberror_error_t **)) &libewf_chunk_data_free,
                    LIBMFDATA_LIST_ELEMENT_VALUE_FLAG_MANAGED,
                    error ) != 1 )
        {
            liberror_error_set(
                error,
                LIBERROR_ERROR_DOMAIN_RUNTIME,
                LIBERROR_RUNTIME_ERROR_GET_FAILED,
                "%s: unable to set chunk data: %d as element value.",
                function,
                chunk_index );

            libewf_chunk_data_free(
                chunk_data,
                NULL );

            return( -1 );
        }
    }
    else
    {
        if( *chunk_data == NULL )
        {
            liberror_error_set(
                error,
                LIBERROR_ERROR_DOMAIN_RUNTIME,
                LIBERROR_RUNTIME_ERROR_VALUE_MISSING,
                "%s: missing chunk data: %d.",
                function,
                chunk_index );

            return( -1 );
        }
        if( libewf_chunk_data_unpack(
                    *chunk_data,
                    media_values->chunk_size,
                    error ) != 1 )
        {
            liberror_error_set(
                error,
                LIBERROR_ERROR_DOMAIN_RUNTIME,
                LIBERROR_RUNTIME_ERROR_GENERIC,
                "%s: unable to unpack chunk data: %d.",
                function,
                chunk_index );

            return( -1 );
        }
        if( ( *chunk_data )->is_corrupt != 0 )
        {
            if( read_io_handle->zero_on_error != 0 )
            {
                if( memory_set(
                            ( *chunk_data )->data,
                            0,
                            ( *chunk_data )->data_size ) == NULL )
                {
                    liberror_error_set(
                        error,
                        LIBERROR_ERROR_DOMAIN_MEMORY,
                        LIBERROR_MEMORY_ERROR_SET_FAILED,
                        "%s: unable to zero chunk data.",
                        function );

                    return( -1 );
                }
            }
        }
    }
    if( ( *chunk_data )->is_corrupt != 0 )
    {
        /* Add checksum error
         */
        start_sector      = (uint64_t) chunk_index * (uint64_t) media_values->sectors_per_chunk;
        number_of_sectors = media_values->sectors_per_chunk;

        if( ( start_sector + number_of_sectors ) > (uint64_t) media_values->number_of_sectors )
        {
            number_of_sectors = (uint32_t) ( (uint64_t) media_values->number_of_sectors - start_sector );
        }
        if( libewf_sector_list_append_sector(
                    read_io_handle->checksum_errors,
                    start_sector,
                    number_of_sectors,
                    1,
                    error ) != 1 )
        {
            liberror_error_set(
                error,
                LIBERROR_ERROR_DOMAIN_RUNTIME,
                LIBERROR_RUNTIME_ERROR_APPEND_FAILED,
                "%s: unable to append checksum error to sectors list.",
                function );

            return( -1 );
        }
    }
    return( 1 );
}
Exemple #3
0
/* Writes a buffer to the data chunk
 * It applies compression if necessary and calculated the chunk checksum
 * This function should be used before libewf_handle_write_data_chunk
 * Returns the number of bytes written, 0 when no longer data can be written or -1 on error
 */
ssize_t libewf_data_chunk_write_buffer(
         libewf_data_chunk_t *data_chunk,
         const 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_write_buffer";
	ssize_t write_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->io_handle == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
		 "%s: invalid data chunk - missing IO handle.",
		 function );

		return( -1 );
	}
	if( internal_data_chunk->write_io_handle == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
		 "%s: invalid data chunk - missing write IO handle.",
		 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 != NULL )
	{
		if( libewf_chunk_data_free(
		     &( internal_data_chunk->chunk_data ),
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
			 "%s: unable to free chunk data.",
			 function );

			goto on_error;
		}
	}
	if( libewf_chunk_data_initialize(
	     &( internal_data_chunk->chunk_data ),
	     internal_data_chunk->io_handle->chunk_size,
	     0,
	     error ) != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
		 "%s: unable to create chunk data.",
		 function );

		goto on_error;
	}
	write_count = libewf_chunk_data_write_buffer(
	               internal_data_chunk->chunk_data,
	               buffer,
	               buffer_size,
	               error );

	if( write_count < 0 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_IO,
		 LIBCERROR_IO_ERROR_WRITE_FAILED,
		 "%s: unable to write buffer to chunk data.",
		 function );

		goto on_error;
	}
	internal_data_chunk->data_size = buffer_size;

	if( libewf_chunk_data_pack(
	     internal_data_chunk->chunk_data,
	     internal_data_chunk->io_handle,
	     internal_data_chunk->write_io_handle->compressed_zero_byte_empty_block,
	     internal_data_chunk->write_io_handle->compressed_zero_byte_empty_block_size,
	     internal_data_chunk->write_io_handle->pack_flags,
	     error ) != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_GENERIC,
		 "%s: unable to pack 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( write_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 );
}