lib/ffi-vix_disk_lib/api_wrapper.rb
require 'ffi-vix_disk_lib'
require 'logger'
require 'ffi-vix_disk_lib/safe_connect_params'
require 'ffi-vix_disk_lib/safe_create_params'
require 'ffi-vix_disk_lib/disk_info'
unless defined? $vix_disk_lib_log
$vix_disk_lib_log = Logger.new(STDOUT)
$vix_disk_lib_log.level = Logger::Severity::WARN
end
module FFI
module VixDiskLib
module ApiWrapper
extend API
attr_reader :info_logger, :warn_logger, :error_logger
def self.attach(parent_disk_handle, child_disk_handle)
vix_error = super(parent_disk_handle, child_disk_handle)
check_error(vix_error, __method__)
nil
end
#
# The VixDiskLib_CheckRepair method
#
def self.check_repair(connection, file_name, repair)
file_ptr = FFI::MemoryPointer.from_string(file_name)
vix_error = super(connection, file_ptr, repair)
check_error(vix_error, __method__)
nil
end
#
# The VixDiskLib_Cleanup method
#
def self.cleanup(connect_parms)
safe_parms = SafeConnectParams.new(connect_parms)
cleaned_up = FFI::MemoryPointer.new :pointer
remaining = FFI::MemoryPointer.new :pointer
vix_error = super(safe_parms.connect_params, cleaned_up, remaining)
num_cleaned_up = cleaned_up.get_uint32(0) unless cleaned_up.nil?
num_remaining = remaining.get_uint32(0) unless remaining.nil?
check_error(vix_error, __method__)
return num_cleaned_up, num_remaining
end
#
# The VixDiskLib_Clone method
#
def self.clone(dest_connection, dest_path, src_connection, src_path, create_parms, over_write)
dest_ptr = FFI::MemoryPointer.from_string(dest_path)
src_ptr = FFI::MemoryPointer.from_string(src_path)
safe_parms = SafeCreateParams.new(create_parms)
vix_error = super(dest_connection, dest_ptr, src_connection, src_ptr,
safe_parms.create_params, nil, nil, over_write)
check_error(vix_error, __method__)
nil
end
#
# The VixDiskLib_Close method
#
def self.close(disk_handle)
vix_error = super(disk_handle)
check_error(vix_error, __method__)
nil
end
#
# The VixDiskLib_Connect method
#
def self.connect(connect_parms)
connection = FFI::MemoryPointer.new :pointer
safe_parms = SafeConnectParams.new(connect_parms)
vix_error = super(safe_parms.connect_params, connection)
connection = connection.get_pointer(0)
check_error(vix_error, __method__)
connection
end
#
# The VixDiskLib_ConnectEx method
#
def self.connect_ex(connect_parms, read_only, snapshot_ref, transport_modes)
connection = FFI::MemoryPointer.new :pointer
safe_parms = SafeConnectParams.new(connect_parms)
snapshot_ptr = snapshot_ref && FFI::MemoryPointer.from_string(snapshot_ref)
modes_ptr = transport_modes && FFI::MemoryPointer.from_string(transport_modes)
vix_error = super(safe_parms.connect_params, read_only, snapshot_ptr, modes_ptr, connection)
connection = connection.get_pointer(0)
check_error(vix_error, __method__)
connection
end
#
# The VixDiskLib_Create method
#
def self.create(connection, path, create_parms, prog_func = nil, prog_callback_data = nil)
safe_parms = SafeCreateParams.new(create_parms)
path_ptr = FFI::MemoryPointer.from_string(path)
vix_error = super(connection, path_ptr, safe_parms.create_params, prog_func, prog_callback_data)
check_error(vix_error, __method)
nil
end
#
# The VixDiskLib_CreateChild method
#
def self.create_child(disk_handle, child_path, disk_type, prog_func = nil, prog_callback_data = nil)
path_ptr = FFI::MemoryPointer.from_string(child_path)
vix_error = super(disk_handle, path_ptr, disk_type, prog_func, prog_callback_data)
check_error(vix_error, __method)
nil
end
#
# The VixDiskLib_Defragment method
#
def self.defragment(disk_handle)
vix_error = super(disk_handle, nil, nil)
check_error(vix_error, __method__)
nil
end
#
# The VixDiskLib_Disconnect method
#
def self.disconnect(connection)
vix_error = super(connection)
check_error(vix_error, __method__)
nil
end
#
# The VixDiskLib_Access method
#
def self.end_access(connect_parms, identity)
safe_parms = SafeConnectParams.new(connect_parms)
identity_ptr = FFI::MemoryPointer.from_string(identity)
vix_error = super(safe_parms.connect_params, identity_ptr)
check_error(vix_error, __method__)
nil
end
#
# The VixDiskLib_Exit method
#
def self.exit
super
nil
end
#
# The VixDiskLib_FreeConnectParams method
#
def self.free_connect_params(connect_params)
super(connect_params)
end
#
# The VixDiskLib_GetConnectParams method
#
def self.get_connect_params(connection)
params_ptr = FFI::MemoryPointer.new :pointer
vix_error = super(connection, params_ptr)
check_error(vix_error, __method__)
ffi_connect_params = params_ptr.get_pointer(0)
safe_connect_params = SafeConnectParams.read(ffi_connect_params)
safe_connect_params
end
#
# The VixDiskLib_GetInfo method
#
def self.get_info(disk_handle)
info = DiskInfo.new(disk_handle)
info.info
end
#
# The VixDiskLib_GetMetadataKeys method
#
def self.get_metadata_keys(disk_handle)
#
# Get the size of the buffer required for the metadata keys for the disk.
#
len_ptr = FFI::MemoryPointer.new :pointer
vix_error = super(disk_handle, nil, 0, len_ptr)
if vix_error != API::VixErrorType[:VIX_OK] && vix_error != API::VixErrorType[:VIX_E_BUFFER_TOOSMALL]
check_error(vix_error, __method__)
end
#
# Read the metadata keys for the disk into the allocated buffer.
#
buf_size = len_ptr.get_uint64(0)
read_buf = FFI::MemoryPointer.new(buf_size)
vix_error = super(disk_handle, read_buf, buf_size, nil)
check_error(vix_error, __method__)
keys = read_buf.get_bytes(0, buf_size)
keys.split("\x00")
end
#
# The VixDiskLib_GetTransportMode method
#
def self.get_transport_mode(disk_handle)
mode = super(disk_handle)
mode.read_string
end
#
# The VixDiskLib_Grow method
#
def self.grow(connection, path, capacity, update_geometry)
path_ptr = FFI::MemoryPointer.from_string(path)
vix_error = super(connection, path_ptr, capacity, update_geometry, nil, nil)
check_error(vix_error, __method__)
nil
end
#
# The VixDiskLib_Init method
#
def self.init(info_logger = nil, warn_logger = nil, error_logger = nil, libDir = nil)
@info_logger, @warn_logger, @error_logger = info_logger, warn_logger, error_logger
vix_error = super(API::VERSION_MAJOR, API::VERSION_MINOR,
logger_for("info"), logger_for("warn"), logger_for("error"), libDir)
check_error(vix_error, __method__)
nil
end
#
# The VixDiskLib_InitEx method
#
def self.init_ex(info_logger = nil, warn_logger = nil, error_logger = nil, libDir = nil, configFile = nil)
@info_logger, @warn_logger, @error_logger = info_logger, warn_logger, error_logger
vix_error = super(API::VERSION_MAJOR, API::VERSION_MINOR,
logger_for("info"), logger_for("warn"), logger_for("error"), libDir, configFile)
check_error(vix_error, __method__)
nil
end
#
# The VixDiskLib_IsAttachPossible method
#
def self.is_attach_possible(parent_disk_handle, child_disk_handle)
vix_error = super(parent_disk_handle, child_disk_handle)
VixDiskLib.vix_succeeded?(vix_error)
end
#
# The VixDiskLib_ListTransportModes method
#
def self.list_transport_modes
list = super
list.read_string
end
#
# The VixDiskLib_Open method
#
def self.open(connection, path, flags)
path_ptr = FFI::MemoryPointer.from_string(path)
disk_handle = FFI::MemoryPointer.new :pointer
vix_error = super(connection, path_ptr, flags, disk_handle)
check_error(vix_error, __method__)
disk_handle.get_pointer(0)
end
#
# The VixDiskLib_PrepareForAccess method
#
def self.prepare_for_access(connect_parms, identity)
safe_parms = SafeConnectParams.new(connect_parms)
identity_ptr = FFI::MemoryPointer.from_string(identity)
vix_error = super(safe_parms.connect_params, identity_ptr)
check_error(vix_error, __method__)
nil
end
#
# The VixDiskLib_Read method
#
def self.read(disk_handle, start_sector, num_sectors)
buf_size = num_sectors * API::VIXDISKLIB_SECTOR_SIZE
read_buf = FFI::MemoryPointer.new(buf_size)
read_buf.clear
vix_error = super(disk_handle, start_sector, num_sectors, read_buf)
check_error(vix_error, __method__)
read_buf.get_bytes(0, buf_size)
end
#
# The VixDiskLib_ReadMetadata method
#
def self.read_metadata(disk_handle, key)
key_ptr = FFI::MemoryPointer.from_string(key)
#
# Get the size of the buffer required for the metadata key for this disk.
#
len_ptr = FFI::MemoryPointer.new :pointer
vix_error = super(disk_handle, key_ptr, nil, 0, len_ptr)
if vix_error != API::VixErrorType[:VIX_OK] && vix_error != API::VixErrorType[:VIX_E_BUFFER_TOOSMALL]
check_error(vix_error, __method__)
end
#
# Read the metadata key for the disk into the allocated buffer.
#
buf_size = len_ptr.get_uint64(0)
read_buf = FFI::MemoryPointer.new(buf_size)
vix_error = super(disk_handle, key_ptr, read_buf, buf_size, nil)
check_error(vix_error, __method__)
read_buf.get_bytes(0, buf_size)
end
#
# The VixDiskLib_Rename method
#
def self.rename(src_path, dest_path)
src_ptr = FFI::MemoryPointer.from_string(src_path)
dest_ptr = FFI::MemoryPointer.from_string(dest_path)
vix_error = super(src_ptr, dest_ptr)
check_error(vix_error, __method__)
nil
end
#
# The VixDiskLib_Shrink method
#
def self.shrink(disk_handle, prog_func = nil, prog_callback_data = nil)
vix_error = super(disk_handle, prog_func, prog_callback_data)
check_error(vix_error, __method__)
nil
end
#
# The VixDiskLib_SpaceNeededForClone method
#
def self.space_needed_for_clone(disk_handle, disk_type)
needed_ptr = FFI::MemoryPointer.new :pointer
vix_error = super(disk_handle, disk_type, needed_ptr)
check_error(vix_error, __method__)
needed_ptr.get_uint64(0)
end
#
# The VixDiskLib_Unlink method
#
def self.unlink(connection, path)
path_ptr = FFI::MemoryPointer.from_string(path)
vix_error = super(connection, path_ptr)
check_error(vix_error, __method__)
nil
end
#
# The VixDiskLib_Write method
#
def self.write(disk_handle, start_sector, num_sectors, buf)
buf_size = num_sectors * :VIXDISKLIB_SECTOR_SIZE
buf_ptr = FFI::MemoryPointer.new(buf_size)
buf_ptr.write_bytes(buf, 0, buf_size)
vix_error = super(disk_handle, start_sector, num_sectors, buf_ptr)
check_error(vix_error, __method__)
nil
end
#
# The VixDiskLib_WriteMetadata method
#
def self.write_metadata(disk_handle, key, value)
key_ptr = FFI::MemoryPointer.from_string(key)
val_ptr = FFI::MemoryPointer.from_string(value)
vix_error = super(disk_handle, key_ptr, val_ptr)
check_error(vix_error, __method__)
nil
end
private
INFO_LOGGER = proc do |fmt, args|
if @info_logger.nil?
if $vix_disk_lib_log
$vix_disk_lib_log.info "VMware(VixDiskLib): #{process_log_args(fmt, args)}"
else
puts "INFO: VMware(VixDiskLib): #{process_log_args(fmt, args)}"
end
else
@info_logger.call(process_log_args(fmt, args))
end
end
WARN_LOGGER = proc do |fmt, args|
if @warn_logger.nil?
if $vix_disk_lib_log
$vix_disk_lib_log.warn "VMware(VixDiskLib): #{process_log_args(fmt, args)}"
else
puts "WARN: VMware(VixDiskLib): #{process_log_args(fmt, args)}"
end
else
@warn_logger.call(process_log_args(fmt, args))
end
end
ERROR_LOGGER = proc do |fmt, args|
if @error_logger.nil?
if $vix_disk_lib_log
$vix_disk_lib_log.error "VMware(VixDiskLib): #{process_log_args(fmt, args)}"
else
puts "ERROR: VMware(VixDiskLib): #{process_log_args(fmt, args)}"
end
else
@error_logger.call(process_log_args(fmt, args))
end
end
def self.logger_for(level)
instance_variable_get("@#{level.downcase}_logger") && const_get("#{level.upcase}_LOGGER")
end
def self.process_log_args(fmt, args)
buf = FFI::MemoryPointer.new(:char, 1024, true)
# LIBC::vsnprintf(buf, 1024, fmt, args)
LIBC.vsnprintf(buf, 1024, fmt, args)
buf.read_string.chomp
end
def self.check_error(err, method)
# if API::vix_failed?(err)
if API.vix_failed?(err)
err_msg = get_error_text(err, nil)
# err_code = API::vix_error_code(err)
err_code = API.vix_error_code(err)
err_name = API::VixErrorType[err_code]
if err_msg.nil? || err_msg.null?
err_msg = "Error retrieving text of error message for errcode."
msg = "#{name}##{method} (errcode=#{err_code} - #{err_name}): #{err_msg}"
else
msg = "#{name}##{method} (errcode=#{err_code} - #{err_name}): #{err_msg.read_string}"
free_error_text(err_msg)
end
raise VixDiskLibError, "#{msg}"
end
end
end
end
end # class FFI::VixDiskLib::ApiWrapper