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