/* 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 ); }
/* 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 ); }