/* Retrieves the SCSI identifier * Returns 1 if successful or -1 on error */ int libsmdev_scsi_get_identier( int file_descriptor, liberror_error_t **error ) { #if defined( SG_GET_SCSI_ID ) struct { int four_in_one; int host_unique_id; } identifier; #endif static char *function = "libsmdev_scsi_get_identifier"; 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 defined( SG_GET_SCSI_ID ) if( ioctl( file_descriptor, SCSI_IOCTL_GET_IDLUN, &identifier ) == -1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_IO, LIBERROR_IO_ERROR_IOCTL_FAILED, "%s: unable to query device for: SCSI_IOCTL_GET_IDLUN.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libnotify_verbose != 0 ) { libnotify_printf( "%s: identifier:\n", function ); libnotify_print_data( (uint8_t *) &identifier, sizeof( identifier ), 0 ); } #endif #endif return( 1 ); }
/* Prints the data on the notify stream * Returns the number of printed characters if successful or -1 on error */ int libnotify_print_data( const uint8_t *data, size_t data_size ) { size_t byte_iterator = 0; size_t data_iterator = 0; int print_count = 0; int total_print_count = 0; if( libnotify_stream == NULL ) { return( -1 ); } if( data == NULL ) { return( -1 ); } while( data_iterator < data_size ) { while( byte_iterator < data_size ) { if( byte_iterator % 16 == 0 ) { print_count = libnotify_printf( "%.8" PRIzx ": ", byte_iterator ); if( print_count <= -1 ) { return( -1 ); } total_print_count += print_count; } print_count = libnotify_printf( "%.2" PRIx8 " ", data[ byte_iterator++ ] ); if( print_count <= -1 ) { return( -1 ); } total_print_count += print_count; if( byte_iterator % 16 == 0 ) { break; } else if( byte_iterator % 8 == 0 ) { print_count = libnotify_printf( " " ); if( print_count <= -1 ) { return( -1 ); } total_print_count += print_count; } } while( byte_iterator % 16 != 0 ) { byte_iterator++; print_count = libnotify_printf( " " ); if( print_count <= -1 ) { return( -1 ); } total_print_count += print_count; if( ( byte_iterator % 8 == 0 ) && ( byte_iterator % 16 != 0 ) ) { print_count = libnotify_printf( " " ); if( print_count <= -1 ) { return( -1 ); } total_print_count += print_count; } } print_count = libnotify_printf( " " ); if( print_count <= -1 ) { return( -1 ); } total_print_count += print_count; byte_iterator = data_iterator; while( byte_iterator < data_size ) { if( ( data[ byte_iterator ] >= 0x20 ) && ( data[ byte_iterator ] <= 0x7e ) ) { print_count = libnotify_printf( "%c", (char) data[ byte_iterator ] ); } else { print_count = libnotify_printf( "." ); } if( print_count <= -1 ) { return( -1 ); } total_print_count += print_count; byte_iterator++; if( byte_iterator % 16 == 0 ) { break; } else if( byte_iterator % 8 == 0 ) { print_count = libnotify_printf( " " ); if( print_count <= -1 ) { return( -1 ); } total_print_count += print_count; } } print_count = libnotify_printf( "\n" ); if( print_count <= -1 ) { return( -1 ); } total_print_count += print_count; data_iterator = byte_iterator; } print_count = libnotify_printf( "\n" ); if( print_count <= -1 ) { return( -1 ); } total_print_count += print_count; return( total_print_count ); }
/* Copies the sector data to the buffer * Returns the number of bytes copied if successful or -1 on error */ ssize_t libodraw_io_handle_copy_sector_data_to_buffer( libodraw_io_handle_t *io_handle, const uint8_t *sector_data, size_t sector_data_size, uint32_t bytes_per_sector, uint8_t track_type, uint8_t *buffer, size_t buffer_size, uint32_t sector_index, uint32_t sector_offset, liberror_error_t **error ) { static char *function = "libodraw_io_handle_copy_sector_data_to_buffer"; size_t buffer_offset = 0; size_t read_size = 0; size_t sector_data_offset = 0; uint32_t sector_lba = 0; #if defined( HAVE_DEBUG_OUTPUT ) uint8_t sector_mode = 0; #endif if( io_handle == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid IO handle.", function ); return( -1 ); } if( sector_data == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid sector data.", function ); return( -1 ); } if( sector_data_size > (size_t) SSIZE_MAX ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid sector data size value exceeds maximum.", function ); return( -1 ); } if( buffer == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid buffer.", function ); return( -1 ); } if( buffer_size > (size_t) SSIZE_MAX ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid buffer size value exceeds maximum.", function ); return( -1 ); } if( ( (size_t) sector_offset >= sector_data_size ) || ( sector_offset >= io_handle->bytes_per_sector ) ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid sector offset value out of bounds.", function ); return( -1 ); } while( sector_data_offset < sector_data_size ) { if( io_handle->bytes_per_sector == 2048 ) { if( ( track_type == LIBODRAW_TRACK_TYPE_MODE1_2352 ) || ( track_type == LIBODRAW_TRACK_TYPE_MODE2_2352 ) ) { if( ( sector_data_offset + 16 ) >= sector_data_size ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: sector data too small.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libnotify_verbose != 0 ) { libnotify_printf( "%s: sector: %" PRIu32 " header:\n", function, sector_index ); libnotify_print_data( &( sector_data[ sector_data_offset ] ), 16 ); } #endif if( memory_compare( &( sector_data[ sector_data_offset ] ), libodraw_sector_synchronisation_data, 12 ) != 0 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_INPUT, LIBERROR_INPUT_ERROR_VALUE_MISMATCH, "%s: unsupported sector synchronisation data.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libnotify_verbose != 0 ) { libnotify_printf( "%s: sector: %" PRIu32 " synchronisation data:\n", function, sector_index ); libnotify_print_data( &( sector_data[ sector_data_offset ] ), 12 ); } #endif sector_data_offset += 12; libodraw_optical_disk_copy_msf_to_lba( sector_data[ sector_data_offset ], sector_data[ sector_data_offset + 1 ], sector_data[ sector_data_offset + 2 ], sector_lba ); #if defined( HAVE_DEBUG_OUTPUT ) sector_mode = sector_data[ sector_data_offset + 3 ] & 0x03; if( libnotify_verbose != 0 ) { libnotify_printf( "%s: sector: %" PRIu32 " MSF\t\t: %02" PRIu8 ":%02" PRIu8 ":%02" PRIu8 " (%" PRIu32 ")\n", function, sector_index, sector_data[ sector_data_offset ], sector_data[ sector_data_offset + 1 ], sector_data[ sector_data_offset + 2 ], sector_lba ); libnotify_printf( "%s: sector: %" PRIu32 " mode bits\t: 0x%02" PRIx8 "\n", function, sector_index, sector_data[ sector_data_offset + 3 ] ); } #endif #if defined( HAVE_VERBOSE_OUTPUT ) if( sector_lba != sector_index ) { libnotify_printf( "%s: sector MSF (LBA) does not match current.\n", function ); } if( ( ( track_type == LIBODRAW_TRACK_TYPE_MODE1_2352 ) && ( sector_mode != 1 ) ) || ( ( track_type == LIBODRAW_TRACK_TYPE_MODE2_2352 ) && ( sector_mode != 2 ) ) ) { libnotify_printf( "%s: sector mode does not match table of contents.\n", function ); } #endif sector_data_offset += 4; } else if( bytes_per_sector == 2352 ) { sector_data_offset += 16; } if( ( track_type == LIBODRAW_TRACK_TYPE_MODE2_2336 ) || ( track_type == LIBODRAW_TRACK_TYPE_MODE2_2352 ) ) { if( ( sector_data[ sector_data_offset ] != sector_data[ sector_data_offset + 4 ] ) || ( sector_data[ sector_data_offset + 1 ] != sector_data[ sector_data_offset + 5 ] ) || ( sector_data[ sector_data_offset + 2 ] != sector_data[ sector_data_offset + 6 ] ) || ( sector_data[ sector_data_offset + 3 ] != sector_data[ sector_data_offset + 7 ] ) ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_INPUT, LIBERROR_INPUT_ERROR_VALUE_MISMATCH, "%s: unsupported or corrupt XA sub-header.", function ); return( -1 ); } if( sector_data[ sector_data_offset + 1 ] >= 32 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_INPUT, LIBERROR_INPUT_ERROR_VALUE_MISMATCH, "%s: unsupported XA sub-header channel number.", function ); return( -1 ); } #if defined( HAVE_VERBOSE_OUTPUT ) if( libnotify_verbose != 0 ) { if( ( sector_data[ sector_data_offset + 2 ] & 0x08 ) != 0 ) { libnotify_printf( "%s: data flag not set in XA sub-header sub-mode flags.\n", function ); } } #endif /* TODO some writers seem to ignore these flags if( ( sector_data[ sector_data_offset + 2 ] & 0x08 ) != 0 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_INPUT, LIBERROR_INPUT_ERROR_VALUE_MISMATCH, "%s: unsupported XA sub-header sub-mode flags - data flag not set.", function ); return( -1 ); } */ sector_data_offset += 8; } } else if( io_handle->bytes_per_sector == 2352 ) { if( sector_offset == 0 ) { /* TODO what about run-out and lead-out data (have argument indicate non-track data) */ if( ( io_handle->mode == 1 ) || ( io_handle->mode == 2 ) ) { read_size = 12; if( ( read_size + buffer_offset ) > buffer_size ) { read_size = buffer_size - buffer_offset; } if( memory_copy( &( buffer[ buffer_offset ] ), libodraw_sector_synchronisation_data, read_size ) != 0 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unsupported copy sector synchronisation data to buffer.", function ); return( -1 ); } buffer_offset += read_size; if( buffer_offset >= buffer_size ) { break; } /* TODO set MSF requires current sector */ buffer[ buffer_offset++ ] = 0; if( buffer_offset >= buffer_size ) { break; } buffer[ buffer_offset++ ] = 0; if( buffer_offset >= buffer_size ) { break; } buffer[ buffer_offset++ ] = 0; if( buffer_offset >= buffer_size ) { break; } if( io_handle->mode == 1 ) { buffer[ buffer_offset++ ] = 1; } else if ( io_handle->mode == 2 ) { buffer[ buffer_offset++ ] = 2; } if( buffer_offset >= buffer_size ) { break; } } else { read_size = 16; if( ( read_size + buffer_offset ) > buffer_size ) { read_size = buffer_size - buffer_offset; } if( memory_set( &( buffer[ buffer_offset ] ), 0, read_size ) == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to set sector data in buffer.", function ); return( -1 ); } buffer_offset += read_size; if( buffer_offset >= buffer_size ) { break; } } if( io_handle->mode == 2 ) { /* TODO what about XA sub-header */ } } } read_size = io_handle->bytes_per_sector; if( sector_offset != 0 ) { sector_data_offset += sector_offset; read_size -= (size_t) sector_offset; sector_offset = 0; } if( ( read_size + buffer_offset ) > buffer_size ) { read_size = buffer_size - buffer_offset; } if( ( track_type == LIBODRAW_TRACK_TYPE_AUDIO ) && ( io_handle->bytes_per_sector != 2352 ) ) { /* If the sector size is not 2352 just return 0 bytes * for audio data */ if( memory_set( &( buffer[ buffer_offset ] ), 0, read_size ) == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to set sector data to buffer.", function ); return( -1 ); } } else { if( memory_copy( &( buffer[ buffer_offset ] ), &( sector_data[ sector_data_offset ] ), read_size ) == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy sector data to buffer.", function ); return( -1 ); } } buffer_offset += read_size; sector_data_offset += read_size; if( buffer_offset >= buffer_size ) { break; } if( io_handle->bytes_per_sector == 2048 ) { if( track_type == LIBODRAW_TRACK_TYPE_MODE1_2352 ) { /* TODO calculate checksum, what about read errors ?*/ sector_data_offset += 4; /* TODO check padding */ sector_data_offset += 8; /* TODO check ECC data if necessary, what about read errors ? */ sector_data_offset += 276; } else if( ( track_type == LIBODRAW_TRACK_TYPE_MODE2_2336 ) || ( track_type == LIBODRAW_TRACK_TYPE_MODE2_2352 ) ) { /* TODO calculate checksum, what about read errors ?*/ sector_data_offset += 4; /* TODO check ECC data if necessary, what about read errors ? */ sector_data_offset += 276; } else if( bytes_per_sector == 2352 ) { sector_data_offset += 288; } } else if( io_handle->bytes_per_sector == 2352 ) { /* TODO what about run-out and lead-out data (have argument indicate non-track data) */ if( ( io_handle->mode == 1 ) || ( io_handle->mode == 2 ) ) { read_size = 4; if( ( read_size + buffer_offset ) > buffer_size ) { read_size = buffer_size - buffer_offset; } /* TODO determine missing data instead of 0 fill */ if( memory_set( &( buffer[ buffer_offset ] ), 0, read_size ) == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to set sector checksum in buffer.", function ); return( -1 ); } buffer_offset += read_size; if( buffer_offset >= buffer_size ) { break; } } if( io_handle->mode == 1 ) { read_size = 8; if( ( read_size + buffer_offset ) > buffer_size ) { read_size = buffer_size - buffer_offset; } if( memory_set( &( buffer[ buffer_offset ] ), 0, read_size ) == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to set sector reserved in buffer.", function ); return( -1 ); } buffer_offset += read_size; if( buffer_offset >= buffer_size ) { break; } } if( ( io_handle->mode == 1 ) || ( io_handle->mode == 2 ) ) { read_size = 276; if( ( read_size + buffer_offset ) > buffer_size ) { read_size = buffer_size - buffer_offset; } /* TODO determine missing data instead of 0 fill */ if( memory_set( &( buffer[ buffer_offset ] ), 0, read_size ) == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to set sector error correction data in buffer.", function ); return( -1 ); } buffer_offset += read_size; if( buffer_offset >= buffer_size ) { break; } } else { read_size = 288; if( ( read_size + buffer_offset ) > buffer_size ) { read_size = buffer_size - buffer_offset; } if( memory_set( &( buffer[ buffer_offset ] ), 0, read_size ) == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_MEMORY, LIBERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to set sector data in buffer.", function ); return( -1 ); } buffer_offset += read_size; if( buffer_offset >= buffer_size ) { break; } } } sector_index++; } return( (ssize_t) buffer_offset ); }
/* 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 ); }
/* 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 ); }
/* 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 ); }
/* 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 ); }
/* 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 ); }
/* 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 ); }
/* Retrieves the node value of the node * Returns 1 if successful or -1 on error */ int libfdata_tree_get_node_value( libfdata_tree_t *tree, libbfio_handle_t *file_io_handle, libfcache_cache_t *cache, libfdata_tree_node_t *node, intptr_t **node_value, uint8_t read_flags, liberror_error_t **error ) { libfcache_cache_value_t *cache_value = NULL; libfdata_internal_tree_t *internal_tree = NULL; static char *function = "libfdata_tree_get_node_value"; off64_t cache_value_offset = (off64_t) -1; off64_t node_data_offset = 0; size64_t node_data_size = 0; time_t cache_value_timestamp = 0; time_t node_timestamp = 0; uint32_t node_data_flags = 0; int cache_entry_index = -1; int number_of_cache_entries = 0; int result = 0; if( tree == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid tree.", function ); return( -1 ); } internal_tree = (libfdata_internal_tree_t *) tree; if( internal_tree->read_node_data == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid tree - missing read node data function.", function ); return( -1 ); } if( libfdata_tree_node_get_data_range( node, &node_data_offset, &node_data_size, &node_data_flags, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data range from tree node.", function ); return( -1 ); } if( libfcache_cache_get_number_of_entries( cache, &number_of_cache_entries, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of cache entries.", function ); return( -1 ); } if( number_of_cache_entries <= 0 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid number of cache entries value out of bounds.", function ); return( -1 ); } if( ( read_flags & LIBFDATA_READ_FLAG_IGNORE_CACHE ) == 0 ) { if( ( ( ( (libfdata_internal_tree_node_t *) node )->flags & LIBFDATA_TREE_NODE_FLAG_IS_VIRTUAL ) == 0 ) && ( ( ( (libfdata_internal_tree_node_t *) node )->flags & LIBFDATA_TREE_NODE_FLAG_IS_LEAF ) != 0 ) ) { cache_entry_index = libfdata_tree_node_calculate_leaf_node_cache_entry_index( node_data_offset, number_of_cache_entries ); } else { cache_entry_index = libfdata_tree_node_calculate_branch_node_cache_entry_index( node_data_offset, number_of_cache_entries ); } if( libfcache_cache_get_value_by_index( cache, cache_entry_index, &cache_value, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve cache entry: %d from cache.", function, cache_entry_index ); return( -1 ); } if( cache_value != NULL ) { if( libfdata_tree_node_get_timestamp( node, &node_timestamp, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve time stamp from tree node.", function ); return( -1 ); } if( libfcache_cache_value_get_identifier( cache_value, &cache_value_offset, &cache_value_timestamp, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve cache value identifier.", function ); return( -1 ); } } if( ( node_data_offset == cache_value_offset ) && ( node_timestamp == cache_value_timestamp ) ) { result = 1; } #if defined( HAVE_DEBUG_OUTPUT ) if( libnotify_verbose != 0 ) { if( result == 0 ) { libnotify_printf( "%s: cache: 0x%08" PRIjx " miss (entry: %d, want: %" PRIi64 ", got: %" PRIi64 ")\n", function, (intptr_t) cache, cache_entry_index, node_data_offset, cache_value_offset ); } else { libnotify_printf( "%s: cache: 0x%08" PRIjx " hit (entry: %d)\n", function, (intptr_t) cache, cache_entry_index ); } } #endif } if( result == 0 ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libnotify_verbose != 0 ) { libnotify_printf( "%s: reading node data at offset: %" PRIi64 " (0x%08" PRIx64 ") of size: %" PRIu64 "\n", function, node_data_offset, node_data_offset, node_data_size ); } #endif /* Read the node data from the file IO handle */ if( internal_tree->read_node_data( internal_tree->io_handle, file_io_handle, node, cache, node_data_offset, node_data_size, read_flags, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_IO, LIBERROR_IO_ERROR_READ_FAILED, "%s: unable to read node data at offset: %" PRIi64 ".", function, node_data_offset ); return( -1 ); } if( ( ( ( (libfdata_internal_tree_node_t *) node )->flags & LIBFDATA_TREE_NODE_FLAG_IS_VIRTUAL ) == 0 ) && ( ( ( (libfdata_internal_tree_node_t *) node )->flags & LIBFDATA_TREE_NODE_FLAG_IS_LEAF ) != 0 ) ) { cache_entry_index = libfdata_tree_node_calculate_leaf_node_cache_entry_index( node_data_offset, number_of_cache_entries ); } else { cache_entry_index = libfdata_tree_node_calculate_branch_node_cache_entry_index( node_data_offset, number_of_cache_entries ); } if( libfcache_cache_get_value_by_index( cache, cache_entry_index, &cache_value, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve cache entry: %d from cache.", function, cache_entry_index ); return( -1 ); } if( cache_value != NULL ) { if( libfdata_tree_node_get_timestamp( node, &node_timestamp, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve time stamp from tree node.", function ); return( -1 ); } if( libfcache_cache_value_get_identifier( cache_value, &cache_value_offset, &cache_value_timestamp, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve cache value identifier.", function ); return( -1 ); } } if( ( node_data_offset != cache_value_offset ) || ( node_timestamp != cache_value_timestamp ) ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing cache value.", function ); return( -1 ); } } if( libfcache_cache_value_get_value( cache_value, node_value, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve node value.", function ); return( -1 ); } return( 1 ); }
/* Reads the database * Returns 1 if successful or -1 on error */ int libesedb_database_read( libesedb_database_t *database, libbfio_handle_t *file_io_handle, libesedb_io_handle_t *io_handle, libfdata_vector_t *pages_vector, libfcache_cache_t *pages_cache, liberror_error_t **error ) { libesedb_page_tree_t *database_page_tree = NULL; libesedb_values_tree_value_t *values_tree_value = NULL; libfcache_cache_t *database_values_cache = NULL; libfdata_tree_t *database_values_tree = NULL; libfdata_tree_node_t *database_values_tree_node = NULL; uint8_t *data = NULL; static char *function = "libesedb_database_read"; off64_t node_data_offset = 0; size_t data_size = 0; int number_of_leaf_nodes = 0; int leaf_node_index = 0; if( database == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid database.", function ); return( -1 ); } if( libesedb_page_tree_initialize( &database_page_tree, io_handle, pages_vector, pages_cache, LIBESEDB_FDP_OBJECT_IDENTIFIER_DATABASE, NULL, NULL, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create database page tree.", function ); goto on_error; } /* TODO clone function */ if( libfdata_tree_initialize( &database_values_tree, (intptr_t *) database_page_tree, (int (*)(intptr_t **, liberror_error_t **)) &libesedb_page_tree_free, NULL, &libesedb_page_tree_read_node_value, &libesedb_page_tree_read_sub_nodes, LIBFDATA_FLAG_IO_HANDLE_MANAGED, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create database values tree.", function ); goto on_error; } database_page_tree = NULL; if( libfcache_cache_initialize( &database_values_cache, LIBESEDB_MAXIMUM_CACHE_ENTRIES_TREE_VALUES, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create database values cache.", function ); goto on_error; } node_data_offset = LIBESEDB_PAGE_NUMBER_DATABASE - 1; node_data_offset *= io_handle->page_size; if( libfdata_tree_set_root_node( database_values_tree, node_data_offset, 0, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set root node in database values tree.", function ); goto on_error; } if( libfdata_tree_get_number_of_leaf_nodes( database_values_tree, file_io_handle, database_values_cache, &number_of_leaf_nodes, 0, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of leaf nodes from database values tree.", function ); goto on_error; } for( leaf_node_index = 0; leaf_node_index < number_of_leaf_nodes; leaf_node_index++ ) { if( libfdata_tree_get_leaf_node_by_index( database_values_tree, file_io_handle, database_values_cache, leaf_node_index, &database_values_tree_node, 0, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve leaf node: %d from database values tree.", function, leaf_node_index ); goto on_error; } if( libfdata_tree_node_get_node_value( database_values_tree_node, file_io_handle, database_values_cache, (intptr_t **) &values_tree_value, 0, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve node value from values tree node.", function ); goto on_error; } if( libesedb_values_tree_value_read_data( values_tree_value, file_io_handle, io_handle, pages_vector, pages_cache, &data, &data_size, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_IO, LIBERROR_IO_ERROR_READ_FAILED, "%s: unable to read values tree value data.", function ); goto on_error; } /* TODO */ #if defined( HAVE_DEBUG_OUTPUT ) if( libnotify_verbose != 0 ) { if( data_size > 0 ) { libnotify_printf( "%s: database value: %d data:\n", function, leaf_node_index ); libnotify_print_data( data, data_size ); } } #endif } if( libfcache_cache_free( &database_values_cache, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free database values cache.", function ); goto on_error; } if( libfdata_tree_free( &database_values_tree, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free database values tree.", function ); goto on_error; } return( 1 ); on_error: if( database_values_cache != NULL ) { libfcache_cache_free( &database_values_cache, NULL ); } if( database_values_tree != NULL ) { libfdata_tree_free( &database_values_tree, NULL ); } if( database_page_tree != NULL ) { libesedb_page_tree_free( &database_page_tree, NULL ); } return( -1 ); }