/* Clones the header sections * Returns 1 if successful or -1 on error */ int libewf_header_sections_clone( libewf_header_sections_t **destination_header_sections, libewf_header_sections_t *source_header_sections, liberror_error_t **error ) { static char *function = "libewf_header_sections_clone"; if( destination_header_sections == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid destination header sections.", function ); return( -1 ); } if( *destination_header_sections != NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid destination header sections already set.", function ); return( -1 ); } if( source_header_sections == NULL ) { *destination_header_sections = NULL; return( 1 ); } if( libewf_header_sections_initialize( destination_header_sections, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create destination header sections.", function ); goto on_error; } if( *destination_header_sections == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing destination header sections.", function ); goto on_error; } if( source_header_sections->header != NULL ) { ( *destination_header_sections )->header = (uint8_t *) memory_allocate( sizeof( uint8_t ) * source_header_sections->header_size ); if( ( *destination_header_sections )->header == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create destination header.", function ); goto on_error; } if( memory_copy( ( *destination_header_sections )->header, source_header_sections->header, sizeof( uint8_t ) * source_header_sections->header_size ) == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy source to destination header.", function ); goto on_error; } ( *destination_header_sections )->header_size = source_header_sections->header_size; } if( source_header_sections->header2 != NULL ) { ( *destination_header_sections )->header2 = (uint8_t *) memory_allocate( sizeof( uint8_t ) * source_header_sections->header2_size ); if( ( *destination_header_sections )->header2 == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create destination header2.", function ); goto on_error; } if( memory_copy( ( *destination_header_sections )->header2, source_header_sections->header2, sizeof( uint8_t ) * source_header_sections->header2_size ) == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy source to destination header2.", function ); goto on_error; } ( *destination_header_sections )->header2_size = source_header_sections->header2_size; } if( source_header_sections->xheader != NULL ) { ( *destination_header_sections )->xheader = (uint8_t *) memory_allocate( sizeof( uint8_t ) * source_header_sections->xheader_size ); if( ( *destination_header_sections )->xheader == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create destination xheader.", function ); goto on_error; } if( memory_copy( ( *destination_header_sections )->xheader, source_header_sections->xheader, sizeof( uint8_t ) * source_header_sections->xheader_size ) == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy source to destination xheader.", function ); goto on_error; } ( *destination_header_sections )->xheader_size = source_header_sections->xheader_size; } ( *destination_header_sections )->number_of_header_sections = source_header_sections->number_of_header_sections; return( 1 ); on_error: if( *destination_header_sections != NULL ) { if( ( *destination_header_sections )->xheader != NULL ) { memory_free( ( *destination_header_sections )->xheader ); } if( ( *destination_header_sections )->header2 != NULL ) { memory_free( ( *destination_header_sections )->header2 ); } if( ( *destination_header_sections )->header != NULL ) { memory_free( ( *destination_header_sections )->header ); } memory_free( *destination_header_sections ); *destination_header_sections = NULL; } return( -1 ); }
/* Sends a SCSI command to the file descriptor * Returns 1 if successful or -1 on error */ int libsmdev_scsi_command( int file_descriptor, uint8_t *command, size_t command_size, uint8_t *response, size_t response_size, uint8_t *sense, size_t sense_size, liberror_error_t **error ) { struct sg_io_hdr sg_io_header; static char *function = "libsmdev_scsi_command"; if( file_descriptor == -1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file descriptor.", function ); return( -1 ); } if( command == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid command.", function ); return( -1 ); } if( command_size > (size_t) SSIZE_MAX ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid command size value exceeds maximum.", function ); return( -1 ); } if( response == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid response.", function ); return( -1 ); } if( response_size > (size_t) SSIZE_MAX ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid response size value exceeds maximum.", function ); return( -1 ); } if( sense == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid sense.", function ); return( -1 ); } if( sense_size > (size_t) SSIZE_MAX ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid sense size value exceeds maximum.", function ); return( -1 ); } if( memory_set( &sg_io_header, 0, sizeof( struct sg_io_hdr ) ) == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear SCSI SG IO header.", function ); return( -1 ); } sg_io_header.interface_id = 'S'; sg_io_header.cmdp = command; sg_io_header.cmd_len = command_size; sg_io_header.sbp = sense; sg_io_header.mx_sb_len = sense_size; sg_io_header.dxferp = response; sg_io_header.dxfer_len = response_size; sg_io_header.dxfer_direction = SG_DXFER_FROM_DEV; sg_io_header.timeout = LIBSMDEV_SCSI_CONTROL_COMMAND_TIMEOUT; if( ioctl( file_descriptor, SG_IO, &sg_io_header ) == -1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_IO, LIBERROR_IO_ERROR_IOCTL_FAILED, "%s: unable to query device for: SG_IO.", function ); return( -1 ); } /* Check if command returned an error */ if( ( sg_io_header.info & SG_INFO_OK_MASK ) != SG_INFO_OK ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_IO, LIBERROR_IO_ERROR_IOCTL_FAILED, "%s: error while querying device: scsi status: %X, host status: %X, driver status: %X.", function, sg_io_header.status, sg_io_header.host_status, sg_io_header.driver_status ); return( -1 ); } return( 1 ); }
/* Determines and retrieves the bus type * Returns 1 if successful or -1 on error */ int libsmdev_scsi_get_bus_type( int file_descriptor, uint8_t *bus_type, liberror_error_t **error ) { #if defined( SCSI_IOCTL_PROBE_HOST ) union { int length; char buffer[ 128 ]; } sg_probe_host; size_t sg_probe_host_length = 0; #endif static char *function = "libsmdev_scsi_get_bus_type"; if( file_descriptor == -1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file descriptor.", function ); return( -1 ); } if( bus_type == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid bus type.", function ); return( -1 ); } *bus_type = LIBSMDEV_BUS_TYPE_UNKNOWN; #if defined( SCSI_IOCTL_PROBE_HOST ) sg_probe_host.length = 127; if( ioctl( file_descriptor, SCSI_IOCTL_PROBE_HOST, &sg_probe_host ) == -1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_IO, LIBERROR_IO_ERROR_IOCTL_FAILED, "%s: unable to query device for: SCSI_IOCTL_PROBE_HOST.", function ); return( -1 ); } sg_probe_host.buffer[ 127 ] = 0; sg_probe_host_length = libcstring_narrow_string_length( sg_probe_host.buffer ); #if defined( HAVE_DEBUG_OUTPUT ) if( libnotify_verbose != 0 ) { libnotify_printf( "%s: SCSI_IOCTL_PROBE_HOST (length: %d): %s\n", function, sg_probe_host_length, sg_probe_host.buffer ); libnotify_printf( "\n" ); } #endif if( sg_probe_host_length >= 4 ) { if( libcstring_narrow_string_compare( sg_probe_host.buffer, "ahci", 4 ) == 0 ) { *bus_type = LIBSMDEV_BUS_TYPE_ATA; } else if( libcstring_narrow_string_compare( sg_probe_host.buffer, "pata", 4 ) == 0 ) { *bus_type = LIBSMDEV_BUS_TYPE_ATA; } else if( libcstring_narrow_string_compare( sg_probe_host.buffer, "sata", 4 ) == 0 ) { *bus_type = LIBSMDEV_BUS_TYPE_ATA; } } /* Serial Bus Protocol (SBP-2) */ else if( ( sg_probe_host_length == 15 ) && ( libcstring_narrow_string_compare( sg_probe_host.buffer, "SBP-2 IEEE-1394", 15 ) == 0 ) ) { *bus_type = LIBSMDEV_BUS_TYPE_FIREWIRE; } else if( ( sg_probe_host_length == 43 ) && ( libcstring_narrow_string_compare( sg_probe_host.buffer, "SCSI emulation for USB Mass Storage devices", 43 ) == 0 ) ) { *bus_type = LIBSMDEV_BUS_TYPE_USB; } #endif return( 1 ); }
/* Initialize the segment file handle * Returns 1 if successful or -1 on error */ int libewf_segment_file_handle_initialize( libewf_segment_file_handle_t **segment_file_handle, int segment_file_index, liberror_error_t **error ) { static char *function = "libewf_segment_file_handle_initialize"; if( segment_file_handle == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid segment file handle.", function ); return( -1 ); } if( segment_file_index < 0 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_VALUE_LESS_THAN_ZERO, "%s: invalid segment file index value less than zero.", function ); return( -1 ); } if( *segment_file_handle == NULL ) { *segment_file_handle = memory_allocate_structure( libewf_segment_file_handle_t ); if( *segment_file_handle == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create segment file handle.", function ); goto on_error; } if( memory_set( *segment_file_handle, 0, sizeof( libewf_segment_file_handle_t ) ) == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear segment file handle.", function ); goto on_error; } ( *segment_file_handle )->segment_file_index = segment_file_index; } return( 1 ); on_error: if( *segment_file_handle != NULL ) { memory_free( *segment_file_handle ); *segment_file_handle = NULL; } return( -1 ); }
/* Sends a SCSI ioctl to the file descriptor * Returns 1 if successful or -1 on error */ int libsmdev_scsi_ioctrl( int file_descriptor, void *request_data, size_t request_data_size, liberror_error_t **error ) { uint8_t *ioctrl_request = 0; static char *function = "libsmdev_scsi_ioctrl"; size_t ioctrl_request_size = 0; if( file_descriptor == -1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file descriptor.", function ); return( -1 ); } ioctrl_request_size = sizeof( libsmdev_scsi_ioctrl_header_t ) + request_data_size; ioctrl_request = (uint8_t *) memory_allocate( ioctrl_request_size ); if( ioctrl_request == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create SCSI ioctrl request.", function ); return( -1 ); } if( memory_set( ioctrl_request, 0, ioctrl_request_size ) == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear SCSI ioctrl request.", function ); memory_free( ioctrl_request ); return( -1 ); } ( (libsmdev_scsi_ioctrl_header_t *) ioctrl_request )->request_size = request_data_size; if( memory_copy( &( ioctrl_request[ sizeof( libsmdev_scsi_ioctrl_header_t ) ] ), request_data, request_data_size ) == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to set SCSI ioctrl request.", function ); memory_free( ioctrl_request ); return( -1 ); } if( ioctl( file_descriptor, SCSI_IOCTL_SEND_COMMAND, ioctrl_request ) == -1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_IO, LIBERROR_IO_ERROR_IOCTL_FAILED, "%s: unable to query device for: SCSI_IOCTL_SEND_COMMAND.", function ); memory_free( ioctrl_request ); return( -1 ); } memory_free( ioctrl_request ); return( 1 ); }
/* Opens the notification stream using a filename * The stream is opened in append mode * Returns 1 if successful or -1 on error */ int libsystem_notify_stream_open( const char *filename, liberror_error_t **error ) { static char *function = "libsystem_notify_stream_open"; if( filename == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid filename.", function ); return( -1 ); } if( ( libsystem_notify_stream_opened_in_library != 0 ) && ( libsystem_notify_stream_close( error ) != 0 ) ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_IO, LIBERROR_IO_ERROR_OPEN_FAILED, "%s: unable to close notify stream.", function ); return( -1 ); } libsystem_notify_stream = file_stream_open( filename, FILE_STREAM_OPEN_APPEND ); if( libsystem_notify_stream == NULL ) { switch( errno ) { case EACCES: liberror_error_set( error, LIBERROR_ERROR_DOMAIN_IO, LIBERROR_IO_ERROR_ACCESS_DENIED, "%s: access denied to file: %s.", function, filename ); break; case ENOENT: liberror_error_set( error, LIBERROR_ERROR_DOMAIN_IO, LIBERROR_IO_ERROR_INVALID_RESOURCE, "%s: no such file: %s.", function, filename ); break; default: liberror_error_set( error, LIBERROR_ERROR_DOMAIN_IO, LIBERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open file: %s.", function, filename ); break; } return( -1 ); } libsystem_notify_stream_opened_in_library = 1; return( 1 ); }
/* Resolves filenames with wildcards (globs) * Returns the number of results if successful or -1 on error */ int libsystem_glob_resolve( libsystem_glob_t *glob, libcstring_system_character_t * const patterns[], int number_of_patterns, liberror_error_t **error ) { #if defined( HAVE_IO_H ) || defined( WINAPI ) libsystem_find_data_t find_data; libcstring_system_character_t find_path[ _MAX_PATH ]; libcstring_system_character_t find_drive[ _MAX_DRIVE ]; libcstring_system_character_t find_directory[ _MAX_DIR ]; libcstring_system_character_t find_name[ _MAX_FNAME ]; libcstring_system_character_t find_extension[ _MAX_EXT ]; intptr_t find_handle = 0; #endif static char *function = "libsystem_glob_resolve"; size_t find_path_length = 0; int globs_found = 0; int iterator = 0; if( glob == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid glob.", function ); return( -1 ); } for( iterator = 0; iterator < number_of_patterns; iterator++ ) { if( patterns[ iterator ] == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing pattern value.", function ); return( -1 ); } #if defined( _MSC_VER ) if( libsystem_path_split( patterns[ iterator ], find_drive, _MAX_DRIVE, find_directory, _MAX_DIR, find_name, _MAX_FNAME, find_extension, _MAX_EXT ) != 0 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to split path.", function ); return( -1 ); } #else libsystem_path_split( patterns[ iterator ], find_drive, _MAX_DRIVE, find_directory, _MAX_DIR, find_name, _MAX_FNAME, find_extension, _MAX_EXT ); #endif find_handle = libsystem_find_first( patterns[ iterator ], &find_data ); if( find_handle != -1 ) { do { if( libsystem_glob_resize( glob, glob->number_of_results + 1, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_RESIZE_FAILED, "%s: unable to resize glob.", function ); return( -1 ); } #if defined( _MSC_VER ) if( libsystem_path_make( find_path, _MAX_PATH, find_drive, find_directory, find_data.name, _LIBCSTRING_SYSTEM_STRING( "" ) ) != 0 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to make path.", function ); return( -1 ); } #elif defined( __BORLANDC__ ) && __BORLANDC__ <= 0x0520 libsystem_path_make( find_path, _MAX_PATH, find_drive, find_directory, find_data.ff_name, _LIBCSTRING_SYSTEM_STRING( "" ) ); #else libsystem_path_make( find_path, _MAX_PATH, find_drive, find_directory, find_data.name, _LIBCSTRING_SYSTEM_STRING( "" ) ); #endif find_path_length = libcstring_system_string_length( find_path ); glob->result[ glob->number_of_results - 1 ] = (libcstring_system_character_t *) memory_allocate( sizeof( libcstring_system_character_t ) * ( find_path_length + 1 ) ); if( glob->result[ glob->number_of_results - 1 ] == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create glob result.", function ); return( -1 ); } if( libcstring_system_string_copy( glob->result[ glob->number_of_results - 1 ], find_path, find_path_length ) == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set glob result.", function ); memory_free( glob->result[ glob->number_of_results - 1 ] ); glob->result[ glob->number_of_results - 1 ] = NULL; return( -1 ); } ( glob->result[ glob->number_of_results - 1 ] )[ find_path_length ] = 0; globs_found++; if( globs_found > (int32_t) UINT16_MAX ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: too many globs found.", function ); return( -1 ); } } while( libsystem_find_next( find_handle, &find_data ) == 0 ); if( errno != ENOENT ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_GET_FAILED, "%s: error finding next file entry.", function ); return( -1 ); } if( libsystem_find_close( find_handle ) != 0 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: error closing find handle.", function ); return( -1 ); } } else if( errno != ENOENT ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_GET_FAILED, "%s: error finding file entry.", function ); return( -1 ); } } return( 1 ); }
/* Tests libewf_handle_read_chunk, libewf_handle_write_chunk, libewf_handle_prepare_read_chunk and libewf_handle_prepare_write_chunk * Returns 1 if successful, 0 if not or -1 on error */ int ewf_test_read_write_chunk( libewf_handle_t *handle, uint8_t *data_buffer, size_t data_buffer_size, uint8_t *chunk_buffer, size_t chunk_buffer_size, size64_t input_size, size64_t expected_size, liberror_error_t **error ) { uint8_t checksum_buffer[ 4 ]; static char *function = "ewf_test_read_write_chunk"; size64_t remaining_size = 0; size64_t result_size = 0; size_t chunk_data_size = 0; size_t data_size = 0; size_t write_size = 0; ssize_t process_count = 0; ssize_t read_count = 0; ssize_t write_count = 0; uint32_t chunk_checksum = 0; int8_t is_compressed = 0; int8_t process_checksum = 0; remaining_size = input_size; while( remaining_size > 0 ) { read_count = libewf_handle_read_chunk( handle, chunk_buffer, chunk_buffer_size, &is_compressed, (void *) checksum_buffer, &chunk_checksum, &process_checksum, error ); if( read_count < 0 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_IO, LIBERROR_IO_ERROR_READ_FAILED, "%s: unable to read chunk of size: %" PRIzd ".", function, chunk_buffer_size ); return( -1 ); } else if( read_count == 0 ) { break; } data_size = data_buffer_size; process_count = libewf_handle_prepare_read_chunk( handle, chunk_buffer, (size_t) read_count, data_buffer, &data_size, is_compressed, chunk_checksum, process_checksum, error ); if( process_count < 0 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_IO, LIBERROR_IO_ERROR_READ_FAILED, "%s: unable to prepare chunk of size: %" PRIzd " after read.", function, read_count ); return( -1 ); } if( libewf_handle_seek_offset( handle, -1 * (off64_t) process_count, SEEK_CUR, error ) == -1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_IO, LIBERROR_IO_ERROR_READ_FAILED, "%s: unable to seek previous offset.", function ); return( -1 ); } if( memory_set( data_buffer, (int) 'C', data_buffer_size ) == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_SET_FAILED, "%s: unable set value in buffer.", function ); return( -1 ); } write_size = process_count; chunk_data_size = chunk_buffer_size; process_count = libewf_handle_prepare_write_chunk( handle, data_buffer, write_size, chunk_buffer, &chunk_data_size, &is_compressed, &chunk_checksum, &process_checksum, error ); if( process_count < 0 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to prepare chunk buffer before writing.", function ); return( -1 ); } if( is_compressed == 0 ) { write_count = libewf_handle_write_chunk( handle, data_buffer, process_count, write_size, is_compressed, checksum_buffer, chunk_checksum, process_checksum, error ); } else { write_count = libewf_handle_write_chunk( handle, chunk_buffer, chunk_data_size, write_size, is_compressed, checksum_buffer, chunk_checksum, process_checksum, error ); } if( write_count < 0 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_IO, LIBERROR_IO_ERROR_WRITE_FAILED, "%s: unable write chunk of size: %" PRIzd ".", function, chunk_data_size ); return( -1 ); } remaining_size -= (size64_t) write_size; result_size += (size64_t) write_size; } if( expected_size != result_size ) { fprintf( stderr, "%s: unexpected read/write count: %" PRIu64 "\n", function, result_size ); return( 0 ); } return( 1 ); }
/* Tests libewf_handle_read_buffer and libewf_handle_write_buffer * Returns 1 if successful, 0 if not or -1 on error */ int ewf_test_read_write_buffer( libewf_handle_t *handle, uint8_t *buffer, size_t buffer_size, size64_t input_size, size64_t expected_size, liberror_error_t **error ) { static char *function = "ewf_test_read_write_buffer"; size64_t remaining_size = 0; size64_t result_size = 0; size_t read_size = 0; ssize_t read_count = 0; ssize_t write_count = 0; remaining_size = input_size; while( remaining_size > 0 ) { read_size = buffer_size; if( remaining_size < (size64_t) read_size ) { read_size = (size_t) remaining_size; } read_count = libewf_handle_read_buffer( handle, buffer, read_size, error ); if( read_count < 0 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_IO, LIBERROR_IO_ERROR_READ_FAILED, "%s: unable to read buffer of size: %" PRIzd ".", function, read_size ); return( -1 ); } else if( read_count == 0 ) { break; } if( libewf_handle_seek_offset( handle, -1 * (off64_t) read_count, SEEK_CUR, error ) == -1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_IO, LIBERROR_IO_ERROR_READ_FAILED, "%s: unable to seek previous offset.", function ); return( -1 ); } if( memory_set( buffer, (int) 'B', (size_t) read_count ) == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_SET_FAILED, "%s: unable set value in buffer.", function ); return( -1 ); } write_count = libewf_handle_write_buffer( handle, buffer, (size_t) read_count, error ); if( write_count < 0 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_IO, LIBERROR_IO_ERROR_WRITE_FAILED, "%s: unable write buffer of size: %" PRIzd ".", function, read_count ); return( -1 ); } if( write_count != read_count ) { break; } remaining_size -= (size64_t) write_count; result_size += (size64_t) write_count; } if( expected_size != result_size ) { fprintf( stderr, "%s: unexpected read/write count: %" PRIu64 "\n", function, result_size ); return( 0 ); } return( 1 ); }
/* Copies a base16 stream from a byte stream * Returns 1 if successful or -1 on error */ int libuna_base16_stream_copy_from_byte_stream( uint8_t *base16_stream, size_t base16_stream_size, uint8_t *byte_stream, size_t byte_stream_size, liberror_error_t **error ) { static char *function = "libuna_base16_stream_copy_from_byte_stream"; size_t base16_stream_index = 0; size_t byte_stream_index = 0; uint8_t byte_value = 0; if( base16_stream == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid base16 stream.", function ); return( -1 ); } if( base16_stream_size > (size_t) SSIZE_MAX ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid base16 stream size value exceeds maximum.", function ); return( -1 ); } if( byte_stream == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid byte stream.", function ); return( -1 ); } if( byte_stream_size > (size_t) SSIZE_MAX ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid byte stream size value exceeds maximum.", function ); return( -1 ); } if( base16_stream_size < ( byte_stream_size * 2 ) ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: base16 stream is too small.", function ); return( -1 ); } /* TODO what about end of string character */ while( byte_stream_index < byte_stream_size ) { byte_value = byte_stream[ byte_stream_index ] >> 4; if( byte_value <= 9 ) { base16_stream[ base16_stream_index++ ] = (uint8_t) '0' + byte_value; } else { base16_stream[ base16_stream_index++ ] = (uint8_t) 'A' + byte_value; } byte_value = byte_stream[ byte_stream_index ] & 0x0f; if( byte_value < 9 ) { base16_stream[ base16_stream_index++ ] = (uint8_t) '0' + byte_value; } else { base16_stream[ base16_stream_index++ ] = (uint8_t) 'A' + byte_value; } byte_stream_index++; } return( 1 ); }
/* Initialize the segment file handle * Returns 1 if successful or -1 on error */ int libewf_segment_file_handle_initialize( libewf_segment_file_handle_t **segment_file_handle, int file_io_pool_entry, liberror_error_t **error ) { static char *function = "libewf_segment_file_handle_initialize"; if( segment_file_handle == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid segment file handle.", function ); return( -1 ); } if( *segment_file_handle == NULL ) { *segment_file_handle = (libewf_segment_file_handle_t *) memory_allocate( sizeof( libewf_segment_file_handle_t ) ); if( *segment_file_handle == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create segment file handle.", function ); return( -1 ); } if( memory_set( *segment_file_handle, 0, sizeof( libewf_segment_file_handle_t ) ) == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear segment file handle.", function ); memory_free( *segment_file_handle ); *segment_file_handle = NULL; return( -1 ); } ( *segment_file_handle )->section_list = (libewf_list_t *) memory_allocate( sizeof( libewf_list_t ) ); if( ( *segment_file_handle )->section_list == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create section list.", function ); memory_free( *segment_file_handle ); *segment_file_handle = NULL; return( -1 ); } if( memory_set( ( *segment_file_handle )->section_list, 0, sizeof( libewf_list_t ) ) == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear section list.", function ); memory_free( ( *segment_file_handle )->section_list ); memory_free( *segment_file_handle ); *segment_file_handle = NULL; return( -1 ); } ( *segment_file_handle )->file_io_pool_entry = file_io_pool_entry; } return( 1 ); }
/* Copies a byte stream from a base16 stream * Returns 1 if successful or -1 on error */ int libuna_base16_stream_copy_to_byte_stream( uint8_t *base16_stream, size_t base16_stream_size, uint8_t *byte_stream, size_t byte_stream_size, liberror_error_t **error ) { static char *function = "libuna_base16_stream_copy_to_byte_stream"; size_t base16_stream_index = 0; size_t byte_stream_index = 0; uint8_t byte_value = 0; if( base16_stream == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid base16 stream.", function ); return( -1 ); } if( base16_stream_size > (size_t) SSIZE_MAX ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid base16 stream size value exceeds maximum.", function ); return( -1 ); } if( ( base16_stream_size % 2 ) != 0 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid base16 stream size value not a multitude of 2.", function ); return( -1 ); } if( byte_stream == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid byte stream.", function ); return( -1 ); } if( byte_stream_size > (size_t) SSIZE_MAX ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid byte stream size value exceeds maximum.", function ); return( -1 ); } if( byte_stream_size < ( base16_stream_size / 2 ) ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: byte stream is too small.", function ); return( -1 ); } /* TODO what about end of string character */ while( base16_stream_index < base16_stream_size ) { byte_value = 0; if( ( base16_stream[ base16_stream_index ] >= (uint8_t) 'A' ) && ( base16_stream[ base16_stream_index ] <= (uint8_t) 'F' ) ) { byte_value = base16_stream[ base16_stream_index ] - (uint8_t) 'A'; } else if( ( base16_stream[ base16_stream_index ] >= (uint8_t) 'a' ) && ( base16_stream[ base16_stream_index ] <= (uint8_t) 'f' ) ) { byte_value = base16_stream[ base16_stream_index ] - (uint8_t) 'a'; } else if( ( base16_stream[ base16_stream_index ] >= (uint8_t) '0' ) && ( base16_stream[ base16_stream_index ] <= (uint8_t) '9' ) ) { byte_value = base16_stream[ base16_stream_index ] - (uint8_t) '0'; } else { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: invalid base16 character.", function ); return( -1 ); } byte_value <<= 4; base16_stream_index++; if( ( base16_stream[ base16_stream_index ] >= (uint8_t) 'A' ) && ( base16_stream[ base16_stream_index ] <= (uint8_t) 'F' ) ) { byte_value += base16_stream[ base16_stream_index ] - (uint8_t) 'A'; } else if( ( base16_stream[ base16_stream_index ] >= (uint8_t) 'a' ) && ( base16_stream[ base16_stream_index ] <= (uint8_t) 'f' ) ) { byte_value += base16_stream[ base16_stream_index ] - (uint8_t) 'a'; } else if( ( base16_stream[ base16_stream_index ] >= (uint8_t) '0' ) && ( base16_stream[ base16_stream_index ] <= (uint8_t) '9' ) ) { byte_value += base16_stream[ base16_stream_index ] - (uint8_t) '0'; } else { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: invalid base16 character.", function ); return( -1 ); } base16_stream_index++; byte_stream[ byte_stream_index++ ] = byte_value; } return( 1 ); }
/* Determines the EWF file format based on known characteristics * Returns 1 if the format was determined, 0 if not or -1 on error */ int libewf_header_sections_determine_format( libewf_header_sections_t *header_sections, uint8_t ewf_format, uint8_t *format, liberror_error_t **error ) { static char *function = "libewf_header_sections_determine_format"; int result = 0; if( header_sections == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid header sections.", function ); return( -1 ); } if( format == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid format.", function ); return( -1 ); } if( ewf_format == EWF_FORMAT_S01 ) { /* The format identifier for the EWF-S01 format was already set * while reading the volume section */ } else if( ewf_format == EWF_FORMAT_E01 ) { if( header_sections->xheader != NULL ) { *format = LIBEWF_FORMAT_EWFX; result = 1; } /* The header2 in raw format starts with 0xff 0xfe <number> */ else if( header_sections->header2 != NULL ) { if( header_sections->header2[ 2 ] == (uint8_t) '3' ) { /* The EnCase5 header2 contains av on the 6th position (36 ... 38 ...) * the header2 is an UTF16 string */ if( ( header_sections->header2[ 36 ] == (uint8_t) 'a' ) && ( header_sections->header2[ 38 ] == (uint8_t) 'v' ) ) { *format = LIBEWF_FORMAT_ENCASE5; result = 1; } else if( ( header_sections->header2[ 36 ] == (uint8_t) 'm' ) && ( header_sections->header2[ 38 ] == (uint8_t) 'd' ) ) { *format = LIBEWF_FORMAT_ENCASE6; result = 1; } #if defined( HAVE_VERBOSE_OUTPUT ) else if( libnotify_verbose != 0 ) { libnotify_printf( "%s: unsupported header2 format: %c%c.\n", function, (char) header_sections->header2[ 36 ], (char) header_sections->header2[ 38 ] ); } #endif } else if( header_sections->header2[ 2 ] == (uint8_t) '1' ) { *format = LIBEWF_FORMAT_ENCASE4; result = 1; } #if defined( HAVE_VERBOSE_OUTPUT ) else if( libnotify_verbose != 0 ) { libnotify_printf( "%s: unsupported header2 version: %c.\n", function, (char) header_sections->header2[ 2 ] ); } #endif } else if( header_sections->header != NULL ) { if( header_sections->header[ 0 ] == (uint8_t) '3' ) { /* The linen5 header2 contains av on the 6th position (17 18) * the header2 is an UTF16 string */ if( ( header_sections->header[ 17 ] == (uint8_t) 'a' ) && ( header_sections->header[ 18 ] == (uint8_t) 'v' ) ) { *format = LIBEWF_FORMAT_LINEN5; result = 1; } else if( ( header_sections->header[ 17 ] == (uint8_t) 'm' ) && ( header_sections->header[ 18 ] == (uint8_t) 'd' ) ) { *format = LIBEWF_FORMAT_LINEN6; result = 1; } #if defined( HAVE_VERBOSE_OUTPUT ) else if( libnotify_verbose != 0 ) { libnotify_printf( "%s: unsupported header format: %c%c.\n", function, (char) header_sections->header[ 17 ], (char) header_sections->header[ 18 ] ); } #endif } else if( header_sections->header[ 0 ] == (uint8_t) '1' ) { /* EnCase uses \r\n */ if( header_sections->header[ 1 ] == (uint8_t) '\r' ) { if( header_sections->header[ 25 ] == (uint8_t) 'r' ) { *format = LIBEWF_FORMAT_ENCASE1; result = 1; #if defined( HAVE_VERBOSE_OUTPUT ) if( header_sections->number_of_header_sections != 1 ) { if( libnotify_verbose != 0 ) { libnotify_printf( "%s: multiple header sections found.\n", function ); } } #endif } else if( header_sections->header[ 31 ] == (uint8_t) 'r' ) { *format = LIBEWF_FORMAT_ENCASE2; result = 1; } #if defined( HAVE_VERBOSE_OUTPUT ) else if( libnotify_verbose != 0 ) { libnotify_printf( "%s: unsupported header version.\n", function ); } #endif } /* FTK Imager uses \n */ else if( header_sections->header[ 1 ] == (uint8_t) '\n' ) { if( header_sections->header[ 29 ] == (uint8_t) 'r' ) { *format = LIBEWF_FORMAT_FTK; result = 1; } #if defined( HAVE_VERBOSE_OUTPUT ) else if( libnotify_verbose != 0 ) { libnotify_printf( "%s: unsupported header version.\n", function ); } #endif } #if defined( HAVE_VERBOSE_OUTPUT ) else if( libnotify_verbose != 0 ) { libnotify_printf( "%s: unsupported header version.\n", function ); } #endif } #if defined( HAVE_VERBOSE_OUTPUT ) else if( libnotify_verbose != 0 ) { libnotify_printf( "%s: unsupported header version.\n", function ); } #endif } #if defined( HAVE_VERBOSE_OUTPUT ) else if( libnotify_verbose != 0 ) { libnotify_printf( "%s: missing header information.\n", function ); } #endif } else if( ewf_format == EWF_FORMAT_L01 ) { *format = LIBEWF_FORMAT_LVF; result = 1; } #if defined( HAVE_VERBOSE_OUTPUT ) else if( libnotify_verbose != 0 ) { libnotify_printf( "%s: unsupported EWF file format.\n", function ); } #endif return( result ); }
/* Create the header sections from the header values * Returns 1 on success or -1 on error */ int libewf_header_sections_create( libewf_header_sections_t *header_sections, libfvalue_table_t *header_values, int8_t compression_level, uint8_t format, int header_codepage, liberror_error_t **error ) { static char *function = "libewf_header_sections_create"; time_t timestamp = time( NULL ); if( header_sections == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid header sections.", function ); return( -1 ); } if( format == LIBEWF_FORMAT_EWF ) { if( libewf_header_values_generate_header_ewf( header_values, timestamp, compression_level, &( header_sections->header ), &( header_sections->header_size ), header_codepage, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create header section.", function ); goto on_error; } } else if( format == LIBEWF_FORMAT_ENCASE1 ) { if( libewf_header_values_generate_header_encase1( header_values, timestamp, compression_level, &( header_sections->header ), &( header_sections->header_size ), header_codepage, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create header section.", function ); goto on_error; } } else if( ( format == LIBEWF_FORMAT_ENCASE2 ) || ( format == LIBEWF_FORMAT_ENCASE3 ) ) { if( libewf_header_values_generate_header_encase2( header_values, timestamp, compression_level, &( header_sections->header ), &( header_sections->header_size ), header_codepage, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create header section.", function ); goto on_error; } } else if( ( format == LIBEWF_FORMAT_FTK ) || ( format == LIBEWF_FORMAT_SMART ) ) { if( libewf_header_values_generate_header_ftk( header_values, timestamp, compression_level, &( header_sections->header ), &( header_sections->header_size ), header_codepage, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create header section.", function ); goto on_error; } } else if( format == LIBEWF_FORMAT_ENCASE4 ) { if( libewf_header_values_generate_header_encase4( header_values, timestamp, compression_level, &( header_sections->header ), &( header_sections->header_size ), header_codepage, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create header section.", function ); goto on_error; } if( libewf_header_values_generate_header2_encase4( header_values, timestamp, compression_level, &( header_sections->header2 ), &( header_sections->header2_size ), error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create header2 section.", function ); goto on_error; } } else if( format == LIBEWF_FORMAT_ENCASE5 ) { if( libewf_header_values_generate_header_encase4( header_values, timestamp, compression_level, &( header_sections->header ), &( header_sections->header_size ), header_codepage, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create header section.", function ); goto on_error; } if( libewf_header_values_generate_header2_encase5( header_values, timestamp, compression_level, &( header_sections->header2 ), &( header_sections->header2_size ), error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create header2 sections.", function ); goto on_error; } } else if( format == LIBEWF_FORMAT_ENCASE6 ) { if( libewf_header_values_generate_header_encase4( header_values, timestamp, compression_level, &( header_sections->header ), &( header_sections->header_size ), header_codepage, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create header section.", function ); goto on_error; } if( libewf_header_values_generate_header2_encase6( header_values, timestamp, compression_level, &( header_sections->header2 ), &( header_sections->header2_size ), error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create header2 sections.", function ); goto on_error; } } else if( format == LIBEWF_FORMAT_LINEN5 ) { if( libewf_header_values_generate_header_linen5( header_values, timestamp, compression_level, &( header_sections->header ), &( header_sections->header_size ), header_codepage, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create header section.", function ); goto on_error; } } else if( format == LIBEWF_FORMAT_LINEN6 ) { if( libewf_header_values_generate_header_linen6( header_values, timestamp, compression_level, &( header_sections->header ), &( header_sections->header_size ), header_codepage, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create header section.", function ); goto on_error; } } else if( format == LIBEWF_FORMAT_EWFX ) { if( libewf_header_values_generate_header_ewfx( header_values, timestamp, compression_level, &( header_sections->header ), &( header_sections->header_size ), header_codepage, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create header section.", function ); goto on_error; } if( libewf_header_values_generate_header2_ewfx( header_values, timestamp, compression_level, &( header_sections->header2 ), &( header_sections->header2_size ), error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create header2 section.", function ); goto on_error; } if( libewf_header_values_generate_xheader( header_values, timestamp, &( header_sections->xheader ), &( header_sections->xheader_size ), error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create xheader section.", function ); goto on_error; } } return( 1 ); on_error: if( header_sections->header2 != NULL ) { memory_free( header_sections->header2 ); header_sections->header2 = NULL; header_sections->header2_size = 0; } if( header_sections->header != NULL ) { memory_free( header_sections->header ); header_sections->header = NULL; header_sections->header_size = 0; } return( -1 ); }
/* Resizes the chunk cache * Returns 1 if successful or -1 on error */ int libewf_chunk_cache_resize( libewf_chunk_cache_t *chunk_cache, size_t size, liberror_error_t **error ) { static char *function = "libewf_chunk_cache_resize"; void *reallocation = NULL; if( chunk_cache == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid chunk cache.", function ); return( -1 ); } if( size > (size_t) SSIZE_MAX ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid size value exceeds maximum.", function ); return( -1 ); } if( size > chunk_cache->allocated_size ) { reallocation = memory_reallocate( chunk_cache->compressed, sizeof( uint8_t ) * size ); if( reallocation == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to resize chunk cache compressed.", function ); return( -1 ); } chunk_cache->compressed = (uint8_t *) reallocation; reallocation = memory_reallocate( chunk_cache->data, sizeof( uint8_t ) * size ); if( reallocation == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to resize chunk cache data.", function ); return( -1 ); } chunk_cache->data = (uint8_t *) reallocation; chunk_cache->allocated_size = size; chunk_cache->chunk = 0; chunk_cache->amount = 0; chunk_cache->offset = 0; chunk_cache->cached = 0; } return( 1 ); }
/* Packs the chunk data * This function either adds the checksum or compresses the chunk data * Returns 1 if successful or -1 on error */ int libewf_chunk_data_pack( libewf_chunk_data_t *chunk_data, int8_t compression_level, uint8_t compression_flags, uint8_t ewf_format, size32_t chunk_size, const uint8_t *compressed_zero_byte_empty_block, size_t compressed_zero_byte_empty_block_size, liberror_error_t **error ) { static char *function = "libewf_chunk_data_pack"; void *reallocation = NULL; uint32_t calculated_checksum = 0; int is_empty_zero_block = 0; int result = 0; if( chunk_data == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid chunk data.", function ); return( -1 ); } if( chunk_data->data == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid chunk data - missing data.", function ); return( -1 ); } if( chunk_data->is_packed != 0 ) { return( 1 ); } chunk_data->is_compressed = 0; if( ( ewf_format != EWF_FORMAT_S01 ) && ( compression_flags & LIBEWF_FLAG_COMPRESS_EMPTY_BLOCK ) != 0 ) { result = libewf_empty_block_test( chunk_data->data, chunk_data->data_size, error ); if( result == -1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if chunk data is empty an empty block.", function ); return( -1 ); } else if( result == 1 ) { if( compression_level == EWF_COMPRESSION_NONE ) { compression_level = EWF_COMPRESSION_DEFAULT; } if( ( chunk_data->data )[ 0 ] == 0 ) { is_empty_zero_block = 1; } } else { compression_level = EWF_COMPRESSION_NONE; } } if( ( ewf_format == EWF_FORMAT_S01 ) || ( compression_level != EWF_COMPRESSION_NONE ) ) { chunk_data->compressed_data_size = 2 * chunk_data->data_size; chunk_data->compressed_data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * chunk_data->compressed_data_size ); if( chunk_data->compressed_data == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create compressed data.", function ); return( -1 ); } if( ( is_empty_zero_block != 0 ) && ( chunk_data->data_size == (size_t) chunk_size ) && ( compressed_zero_byte_empty_block != NULL ) ) { if( memory_copy( chunk_data->compressed_data, compressed_zero_byte_empty_block, compressed_zero_byte_empty_block_size ) == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy compressed zero byte empty block to compressed chunk buffer.", function ); return( -1 ); } chunk_data->compressed_data_size = compressed_zero_byte_empty_block_size; } else { result = libewf_compress( chunk_data->compressed_data, &( chunk_data->compressed_data_size ), chunk_data->data, chunk_data->data_size, compression_level, error ); /* Check if the compressed buffer was too small * and a new compressed data size buffer was passed back */ if( ( result == -1 ) && ( chunk_data->compressed_data_size > 0 ) ) { liberror_error_free( error ); reallocation = memory_reallocate( chunk_data->compressed_data, sizeof( uint8_t ) * chunk_data->compressed_data_size ); if( reallocation == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to resize compressed data.", function ); return( -1 ); } chunk_data->compressed_data = (uint8_t *) reallocation; result = libewf_compress( chunk_data->compressed_data, &( chunk_data->compressed_data_size ), chunk_data->data, chunk_data->data_size, compression_level, error ); } if( result != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_COMPRESSION, LIBERROR_COMPRESSION_ERROR_COMPRESS_FAILED, "%s: unable to compress chunk data.", function ); return( -1 ); } } if( ( ewf_format == EWF_FORMAT_S01 ) || ( chunk_data->compressed_data_size < chunk_data->data_size ) ) { memory_free( chunk_data->data ); chunk_data->data = chunk_data->compressed_data; chunk_data->data_size = chunk_data->compressed_data_size; chunk_data->compressed_data = NULL; chunk_data->compressed_data_size = 0; chunk_data->is_compressed = 1; } } if( chunk_data->is_compressed == 0 ) { if( ( chunk_data->data_size + sizeof( uint32_t ) ) > chunk_data->allocated_data_size ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: chunk data size value out of bounds.", function ); return( -1 ); } calculated_checksum = ewf_checksum_calculate( chunk_data->data, chunk_data->data_size, 1 ); byte_stream_copy_from_uint32_little_endian( &( ( chunk_data->data )[ chunk_data->data_size ] ), calculated_checksum ); chunk_data->data_size += sizeof( uint32_t ); } chunk_data->is_packed = 1; return( 1 ); }
/* Initialize the chunk cache * Returns 1 if successful or -1 on error */ int libewf_chunk_cache_initialize( libewf_chunk_cache_t **chunk_cache, size_t size, liberror_error_t **error ) { static char *function = "libewf_chunk_cache_initialize"; if( chunk_cache == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid chunk cache.", function ); return( -1 ); } if( size > (size_t) SSIZE_MAX ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid size value exceeds maximum.", function ); return( -1 ); } if( *chunk_cache == NULL ) { *chunk_cache = (libewf_chunk_cache_t *) memory_allocate( sizeof( libewf_chunk_cache_t ) ); if( *chunk_cache == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create chunk cache.", function ); return( -1 ); } if( memory_set( *chunk_cache, 0, sizeof( libewf_chunk_cache_t ) ) == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear chunk cache.", function ); memory_free( *chunk_cache ); *chunk_cache = NULL; return( -1 ); } ( *chunk_cache )->compressed = (uint8_t *) memory_allocate( sizeof( uint8_t ) * size ); if( ( *chunk_cache )->compressed == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create chunk cache compressed.", function ); memory_free( *chunk_cache ); *chunk_cache = NULL; return( -1 ); } ( *chunk_cache )->data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * size ); if( ( *chunk_cache )->data == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create chunk cache data.", function ); memory_free( ( *chunk_cache )->compressed ); memory_free( *chunk_cache ); *chunk_cache = NULL; return( -1 ); } ( *chunk_cache )->allocated_size = size; } return( 1 ); }
/* Initialize the chunk data * Returns 1 if successful or -1 on error */ int libewf_chunk_data_initialize( libewf_chunk_data_t **chunk_data, size_t data_size, liberror_error_t **error ) { static char *function = "libewf_chunk_data_initialize"; if( chunk_data == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid chunk data.", function ); return( -1 ); } if( *chunk_data != NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid chunk data value already set.", function ); return( -1 ); } if( data_size > (size_t) SSIZE_MAX ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid data size value exceeds maximum.", function ); return( -1 ); } *chunk_data = memory_allocate_structure( libewf_chunk_data_t ); if( *chunk_data == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create chunk data.", function ); goto on_error; } if( memory_set( *chunk_data, 0, sizeof( libewf_chunk_data_t ) ) == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear chunk data.", function ); goto on_error; } ( *chunk_data )->data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * data_size ); if( ( *chunk_data )->data == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create data.", function ); goto on_error; } ( *chunk_data )->allocated_data_size = data_size; return( 1 ); on_error: if( *chunk_data != NULL ) { memory_free( *chunk_data ); *chunk_data = NULL; } return( -1 ); }
/* Resizes the glob * Returns 1 if successful or -1 on error */ int libsystem_glob_resize( libsystem_glob_t *glob, int new_number_of_results, liberror_error_t **error ) { void *reallocation = NULL; static char *function = "libsystem_glob_resize"; size_t previous_size = 0; size_t new_size = 0; if( glob == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid glob.", function ); return( -1 ); } if( glob->number_of_results >= new_number_of_results ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: new number of results less equal than current.", function ); return( -1 ); } previous_size = sizeof( libcstring_system_character_t * ) * glob->number_of_results; new_size = sizeof( libcstring_system_character_t * ) * new_number_of_results; if( ( previous_size > (size_t) SSIZE_MAX ) || ( new_size > (size_t) SSIZE_MAX ) ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid size value exceeds maximum.", function ); return( -1 ); } reallocation = memory_reallocate( glob->result, new_size ); if( reallocation == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to reallocate glob results.", function ); return( -1 ); } glob->result = (libcstring_system_character_t **) reallocation; if( memory_set( &( glob->result[ glob->number_of_results ] ), 0, new_size - previous_size ) == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear glob.", function ); return( -1 ); } glob->number_of_results = new_number_of_results; return( 1 ); }
/* Unpacks the chunk data * This function either validates the checksum or decompresses the chunk data * Returns 1 if successful or -1 on error */ int libewf_chunk_data_unpack( libewf_chunk_data_t *chunk_data, size_t chunk_size, liberror_error_t **error ) { static char *function = "libewf_chunk_data_unpack"; uint32_t calculated_checksum = 0; uint32_t stored_checksum = 0; int result = 0; if( chunk_data == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid chunk data.", function ); return( -1 ); } if( chunk_data->data == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid chunk data - missing data.", function ); return( -1 ); } if( ( chunk_size == 0 ) || ( chunk_size > (size_t) SSIZE_MAX ) ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: chunk size value out of bounds.", function ); return( -1 ); } if( chunk_data->is_packed == 0 ) { return( 1 ); } if( chunk_data->is_compressed == 0 ) { if( ( chunk_data->data_size < sizeof( uint32_t ) ) || ( chunk_data->data_size > (size_t) SSIZE_MAX ) ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: chunk data size value out of bounds.", function ); return( -1 ); } chunk_data->data_size -= sizeof( uint32_t ); byte_stream_copy_to_uint32_little_endian( &( ( chunk_data->data )[ chunk_data->data_size ] ), stored_checksum ); calculated_checksum = ewf_checksum_calculate( chunk_data->data, chunk_data->data_size, 1 ); if( stored_checksum != calculated_checksum ) { #if defined( HAVE_VERBOSE_OUTPUT ) if( libnotify_verbose != 0 ) { libnotify_printf( "%s: chunk data checksum does not match (stored: 0x%08" PRIx32 " calculated: 0x%08" PRIx32 ").\n", function, stored_checksum, calculated_checksum ); } #endif chunk_data->is_corrupt = 1; } } else { if( chunk_data->compressed_data != NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid chunk data - compressed data value already set.", function ); return( -1 ); } chunk_data->compressed_data = chunk_data->data; chunk_data->compressed_data_size = chunk_data->data_size; /* Reserve 4 bytes for the checksum */ chunk_data->allocated_data_size = chunk_size + sizeof( uint32_t ); chunk_data->data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * chunk_data->allocated_data_size ); if( chunk_data->data == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create data.", function ); return( -1 ); } chunk_data->data_size = chunk_size; result = libewf_decompress( chunk_data->data, &( chunk_data->data_size ), chunk_data->compressed_data, chunk_data->compressed_data_size, error ); if( result == -1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_COMPRESSION, LIBERROR_COMPRESSION_ERROR_DECOMPRESS_FAILED, "%s: unable to decompress chunk data.", function ); return( -1 ); } else if( result == 0 ) { #if defined( HAVE_VERBOSE_OUTPUT ) if( libnotify_verbose != 0 ) { libnotify_printf( "%s: unable to decompress chunk data.\n", function ); } #endif chunk_data->is_corrupt = 1; } } chunk_data->is_packed = 0; return( 1 ); }
/* Clones the segment file handle * Returns 1 if successful or -1 on error */ int libewf_segment_file_handle_clone( intptr_t **destination_segment_file_handle, intptr_t *source_segment_file_handle, liberror_error_t **error ) { static char *function = "libewf_segment_file_handle_clone"; if( destination_segment_file_handle == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid destination segment file handle.", function ); return( -1 ); } if( *destination_segment_file_handle != NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid destination segment file handle value already set.", function ); return( -1 ); } if( source_segment_file_handle == NULL ) { *destination_segment_file_handle = NULL; return( 1 ); } *destination_segment_file_handle = memory_allocate_structure_as_value( libewf_segment_file_handle_t ); if( *destination_segment_file_handle == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create destination segment file handle.", function ); goto on_error; } if( memory_copy( *destination_segment_file_handle, source_segment_file_handle, sizeof( libewf_segment_file_handle_t ) ) == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy source to destination segment file handle.", function ); goto on_error; } return( 1 ); on_error: if( *destination_segment_file_handle != NULL ) { memory_free( *destination_segment_file_handle ); *destination_segment_file_handle = NULL; } return( -1 ); }
/* Appends file handles to the pool for the corresponding filenames * Returns 1 if successful or -1 on error */ int libbfio_file_pool_append_handles_for_names( libbfio_pool_t *pool, char * const names[], int number_of_names, int access_flags, liberror_error_t **error ) { libbfio_handle_t *file_io_handle = NULL; static char *function = "libbfio_file_pool_append_handles_for_names"; size_t name_length = 0; int pool_entry = 0; int name_iterator = 0; if( pool == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid pool.", function ); return( -1 ); } if( names == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid names.", function ); return( -1 ); } if( number_of_names <= 0 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS, "%s: invalid number of names zero or less.", function ); return( -1 ); } for( name_iterator = 0; name_iterator < number_of_names; name_iterator++ ) { name_length = libcstring_narrow_string_length( names[ name_iterator ] ); if( libbfio_file_initialize( &file_io_handle, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create file IO handle: %d.", function, name_iterator ); return( -1 ); } if( libbfio_file_set_name( file_io_handle, names[ name_iterator ], name_length + 1, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set name in file IO handle: %d.", function, name_iterator ); libbfio_handle_free( &file_io_handle, NULL ); return( -1 ); } if( libbfio_pool_append_handle( pool, &pool_entry, file_io_handle, access_flags, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append file IO handle: %d to pool.", function, name_iterator ); libbfio_handle_free( &file_io_handle, NULL ); return( -1 ); } file_io_handle = NULL; } return( 1 ); }
/* Retrieves a descriptive string of the error number * Returns 1 if successful or -1 on error */ int libsmdev_error_string_copy_from_error_number( libcstring_system_character_t *string, size_t string_size, int error_number, liberror_error_t **error ) { static char *function = "libsmdev_error_string_copy_from_error_number"; #if ( defined( HAVE_STRERROR ) && !defined( HAVE_STRERROR_R ) && !defined( WINAPI ) ) || ( defined( WINAPI ) && defined( USE_CRT_FUNCTIONS ) && !defined( _MSC_VER ) ) #if defined( LIBCSTRING_HAVE_WIDE_SYSTEM_CHARACTER ) const wchar_t *static_error_string = NULL; #else const char *static_error_string = NULL; #endif size_t static_error_string_length = 0; #endif if( string == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid string.", function ); return( -1 ); } if( string_size > (size_t) SSIZE_MAX ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid string size value exceeds maximum.", function ); return( -1 ); } /* Use the WINAPI error string function */ #if defined( WINAPI ) && !defined( USE_CRT_FUNCTIONS ) #if defined( LIBCSTRING_HAVE_WIDE_SYSTEM_CHARACTER ) if( FormatMessageW( FORMAT_MESSAGE_FROM_SYSTEM, NULL, (DWORD) error_number, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), string, string_size, NULL ) == 0 ) #else if( FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM, NULL, (DWORD) error_number, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), string, string_size, NULL ) == 0 ) #endif { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set string.", function ); return( -1 ); } /* Use MSVSC++ specific CRT error string functions */ #elif defined( USE_CRT_FUNCTIONS ) && defined( _MSC_VER ) #if defined( LIBCSTRING_HAVE_WIDE_SYSTEM_CHARACTER ) if( _wcserror_s( string, string_size, error_number ) != 0 ) #else if( strerror_s( string, string_size, error_number ) != 0 ) #endif { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set string.", function ); return( -1 ); } /* Use POSIX specific error string functions */ #elif defined( HAVE_STRERROR_R ) /* Sanity check */ #if defined( LIBCSTRING_HAVE_WIDE_SYSTEM_CHARACTER ) #error Missing wide character strerror_r function #endif #if defined( STRERROR_R_CHAR_P ) if( strerror_r( error_number, string, string_size ) == NULL ) #else if( strerror_r( error_number, string, string_size ) != 0 ) #endif { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set string.", function ); return( -1 ); } /* Use the static error string function */ #elif defined( HAVE_STRERROR ) || defined( WINAPI ) /* Sanity check */ #if defined( LIBCSTRING_HAVE_WIDE_SYSTEM_CHARACTER ) && !defined( WINAPI ) #error Missing wide character strerror function #endif #if defined( LIBCSTRING_HAVE_WIDE_SYSTEM_CHARACTER ) static_error_string = _wcserror( error_number ); #else static_error_string = strerror( error_number ); #endif if( static_error_string == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to create static error string.", function ); return( -1 ); } static_error_string_length = libcstring_system_string_length( static_error_string ); if( libcstring_system_string_copy( string, static_error_string, static_error_string_length ) == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set string.", function ); return( -1 ); } string[ static_error_string_length ] = 0; #else #error Missing strerror function #endif return( 1 ); }
/* Initializes the element * Returns 1 if successful or -1 on error */ int libfdata_list_element_initialize( libfdata_list_element_t **element, libfdata_list_t *list, int element_index, liberror_error_t **error ) { libfdata_internal_list_element_t *internal_element = NULL; static char *function = "libfdata_list_element_initialize"; if( element == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid element.", function ); return( -1 ); } if( *element != NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid element value already set.", function ); return( -1 ); } if( list == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid list.", function ); return( -1 ); } if( element_index < 0 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_VALUE_LESS_THAN_ZERO, "%s: invalid element index value less than zero.", function ); return( -1 ); } internal_element = memory_allocate_structure( libfdata_internal_list_element_t ); if( internal_element == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create element.", function ); goto on_error; } if( memory_set( internal_element, 0, sizeof( libfdata_internal_list_element_t ) ) == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear element.", function ); goto on_error; } if( libfdata_range_initialize( &( internal_element->data_range ), error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create data range.", function ); goto on_error; } internal_element->list = list; internal_element->element_index = element_index; internal_element->timestamp = libfdata_date_time_get_timestamp(); *element = (libfdata_list_element_t *) internal_element; return( 1 ); on_error: if( internal_element != NULL ) { memory_free( internal_element ); } return( -1 ); }
/* Sends a SCSI inquiry to the file descriptor * Returns the number of bytes read if successful or -1 on error */ ssize_t libsmdev_scsi_inquiry( int file_descriptor, uint8_t inquiry_vital_product_data, uint8_t code_page, uint8_t *response, size_t response_size, liberror_error_t **error ) { libsmdev_scsi_inquiry_cdb_t command; uint8_t sense[ LIBSMDEV_SCSI_SENSE_SIZE ]; static char *function = "libsmdev_scsi_inquiry"; ssize_t response_count = 0; if( file_descriptor == -1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file descriptor.", function ); return( -1 ); } if( response == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid response.", function ); return( -1 ); } if( response_size > (size_t) SSIZE_MAX ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid response size value exceeds maximum.", function ); return( -1 ); } if( memory_set( &command, 0, sizeof( libsmdev_scsi_inquiry_cdb_t ) ) == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear command.", function ); return( -1 ); } command.operation_code = LIBSMDEV_SCSI_OPERATION_CODE_INQUIRY; if( inquiry_vital_product_data != 0 ) { command.lun |= 0x01; command.reserved1 = code_page; } if( libsmdev_scsi_command( file_descriptor, (uint8_t *) &command, sizeof( libsmdev_scsi_inquiry_cdb_t ), response, response_size, sense, LIBSMDEV_SCSI_SENSE_SIZE, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_IO, LIBERROR_IO_ERROR_GENERIC, "%s: SCSI INQUIRY command failed.", function ); return( -1 ); } /* In standard inquiry mode the additional size is in the 5th byte * in vital produce data inquiry mode it is in the 4th byte */ if( inquiry_vital_product_data == 0 ) { response_count = (ssize_t) ( response[ 4 ] + 5 ); } else { response_count = (ssize_t) ( response[ 3 ] + 4 ); } if( response_count > (ssize_t) response_size ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: response too small.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libnotify_verbose != 0 ) { libnotify_printf( "%s: response:\n", function ); libnotify_print_data( response, response_count, 0 ); } #endif return( response_count ); }
/* Returns a structured representation of a time using the local time zone, or NULL on error */ int libewf_date_time_localtime( const time_t *timestamp, struct tm *time_elements, liberror_error_t **error ) { #if ( defined( HAVE_LOCALTIME ) && !defined( HAVE_LOCALTIME_R ) ) || ( defined( WINAPI ) && !defined( _MSC_VER ) ) struct tm *static_time_elements = NULL; #endif static char *function = "libewf_date_time_localtime"; if( timestamp == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid time stamp.", function ); return( -1 ); } if( time_elements == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid time elements.", function ); return( -1 ); } #if defined( _MSC_VER ) if( localtime_s( time_elements, timestamp ) != 0 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set time elements.", function ); return( -1 ); } #elif defined( HAVE_LOCALTIME_R ) if( localtime_r( timestamp, time_elements ) == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set time elements.", function ); return( -1 ); } #elif defined( HAVE_LOCALTIME ) || defined( WINAPI ) static_time_elements = localtime( timestamp ); if( static_time_elements == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create static time elements.", function ); return( -1 ); } if( memory_copy( time_elements, static_time_elements, sizeof( struct tm ) ) == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to set time elements.", function ); return( -1 ); } #endif return( 1 ); }
/* Sends a SCSI read track information to the file descriptor * Returns the number of bytes read if successful or -1 on error */ ssize_t libsmdev_scsi_read_track_information( int file_descriptor, uint32_t offset, uint8_t *response, size_t response_size, liberror_error_t **error ) { libsmdev_scsi_read_track_information_cdb_t command; uint8_t sense[ LIBSMDEV_SCSI_SENSE_SIZE ]; static char *function = "libsmdev_scsi_read_track_information"; ssize_t response_count = 0; if( file_descriptor == -1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file descriptor.", function ); return( -1 ); } if( response == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid response.", function ); return( -1 ); } if( response_size > (size_t) SSIZE_MAX ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid response size value exceeds maximum.", function ); return( -1 ); } if( memory_set( &command, 0, sizeof( libsmdev_scsi_read_track_information_cdb_t ) ) == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear command.", function ); return( -1 ); } command.operation_code = LIBSMDEV_SCSI_OPERATION_CODE_READ_TRACK_INFORMATION; command.address_type = LIBSMDEV_SCSI_TRACK_INFORMATION_ADDRESS_TYPE_LBA; byte_stream_copy_from_uint32_big_endian( command.offset, offset ); byte_stream_copy_from_uint16_big_endian( command.receive_size, response_size ); if( libsmdev_scsi_command( file_descriptor, (uint8_t *) &command, sizeof( libsmdev_scsi_read_track_information_cdb_t ), response, response_size, sense, LIBSMDEV_SCSI_SENSE_SIZE, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_IO, LIBERROR_IO_ERROR_GENERIC, "%s: SCSI READ TRACK INFORMATION command failed.", function ); return( -1 ); } byte_stream_copy_to_uint16_big_endian( response, response_count ); if( response_count > (ssize_t) response_size ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: response too small.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libnotify_verbose != 0 ) { libnotify_printf( "%s: response:\n", function ); libnotify_print_data( response, response_count, 0 ); } #endif return( response_count ); }
/* Copies an UTF-7 stream from an UTF-32 string * Returns 1 if successful or -1 on error */ int libuna_utf7_stream_copy_from_utf32( uint8_t *utf7_stream, size_t utf7_stream_size, const libuna_utf32_character_t *utf32_string, size_t utf32_string_size, liberror_error_t **error ) { static char *function = "libuna_utf7_stream_copy_from_utf32"; size_t utf32_string_iterator = 0; size_t utf7_stream_iterator = 0; libuna_unicode_character_t unicode_character = 0; uint32_t utf7_stream_base64_data = 0; if( utf7_stream == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid UTF-7 stream.", function ); return( -1 ); } if( utf7_stream_size > (size_t) SSIZE_MAX ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid UTF-7 stream size value exceeds maximum.", function ); return( -1 ); } if( utf32_string == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid UTF-32 string.", function ); return( -1 ); } if( utf32_string_size > (size_t) SSIZE_MAX ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid UTF-32 string size value exceeds maximum.", function ); return( -1 ); } while( utf32_string_iterator < utf32_string_size ) { /* Convert the UTF-32 character bytes into a Unicode character */ if( libuna_unicode_character_copy_from_utf32( &unicode_character, utf32_string, utf32_string_size, &utf32_string_iterator, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_CONVERSION, LIBERROR_CONVERSION_ERROR_INPUT_FAILED, "%s: unable to copy Unicode character from UTF-32.", function ); return( -1 ); } /* Convert the Unicode character into UTF-7 character bytes */ if( libuna_unicode_character_copy_to_utf7_stream( unicode_character, utf7_stream, utf7_stream_size, &utf7_stream_iterator, &utf7_stream_base64_data, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_CONVERSION, LIBERROR_CONVERSION_ERROR_OUTPUT_FAILED, "%s: unable to copy Unicode character to UTF-7 stream.", function ); return( -1 ); } } return( 1 ); }
/* Determines and retrieves the PCI bus address * Returns 1 if successful or -1 on error */ int libsmdev_scsi_get_pci_bus_address( int file_descriptor, uint8_t *pci_bus_address, size_t pci_bus_address_size, liberror_error_t **error ) { static char *function = "libsmdev_scsi_get_bus_type"; if( file_descriptor == -1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file descriptor.", function ); return( -1 ); } if( pci_bus_address == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid PCI bus address.", function ); return( -1 ); } if( pci_bus_address_size > (size_t) SSIZE_MAX ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid PCI bus address size value exceeds maximum.", function ); return( -1 ); } if( pci_bus_address_size <= 8 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: invalid PCI bus address size value too small.", function ); return( -1 ); } if( memory_set( pci_bus_address, 0, pci_bus_address_size ) == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear PCI bus address.", function ); return( -1 ); } #if defined( SCSI_IOCTL_GET_PCI ) if( ioctl( file_descriptor, SCSI_IOCTL_GET_PCI, pci_bus_address ) == -1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_IO, LIBERROR_IO_ERROR_IOCTL_FAILED, "%s: unable to query device for: SCSI_IOCTL_GET_PCI.", function ); return( -1 ); } pci_bus_address[ pci_bus_address_size - 1 ] = 0; #if defined( HAVE_DEBUG_OUTPUT ) if( libnotify_verbose != 0 ) { libnotify_printf( "%s: SCSI_IOCTL_GET_PCI: %s\n", function, pci_bus_address ); libnotify_printf( "\n" ); } #endif #endif return( 1 ); }
/* Initializes the segment * Returns 1 if successful or -1 on error */ int libmfdata_segment_initialize( libmfdata_segment_t **segment, libmfdata_segment_table_t *segment_table, int segment_index, liberror_error_t **error ) { libmfdata_internal_segment_t *internal_segment = NULL; static char *function = "libmfdata_segment_initialize"; if( segment == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid segment.", function ); return( -1 ); } if( segment_table == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid segment table.", function ); return( -1 ); } if( segment_index < 0 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_VALUE_LESS_THAN_ZERO, "%s: invalid segment index value less than zero.", function ); return( -1 ); } if( *segment == NULL ) { internal_segment = memory_allocate_structure( libmfdata_internal_segment_t ); if( internal_segment == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create segment.", function ); goto on_error; } if( memory_set( internal_segment, 0, sizeof( libmfdata_internal_segment_t ) ) == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear segment.", function ); goto on_error; } internal_segment->segment_table = segment_table; internal_segment->segment_index = segment_index; internal_segment->file_io_pool_entry = -1; *segment = (libmfdata_segment_t *) internal_segment; } return( 1 ); on_error: if( internal_segment != NULL ) { memory_free( internal_segment ); } return( -1 ); }