Пример #1
0
/* 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 );
}
Пример #2
0
/* 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 );
}
Пример #3
0
/* 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 );
}
Пример #4
0
/* 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 );
}
Пример #5
0
/* 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 );
}