ffi-vix_disk_lib 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,451 @@
1
+ require 'ffi-vix_disk_lib'
2
+ require 'logger'
3
+ require 'ffi-vix_disk_lib/safe_connect_params'
4
+ require 'ffi-vix_disk_lib/safe_create_params'
5
+ require 'ffi-vix_disk_lib/disk_info'
6
+
7
+ unless defined? $vix_disk_lib_log
8
+ $vix_disk_lib_log = Logger.new(STDOUT)
9
+ $vix_disk_lib_log.level = Logger::Severity::WARN
10
+ end
11
+
12
+ module FFI
13
+ module VixDiskLib
14
+ module ApiWrapper
15
+ extend API
16
+
17
+ attr_reader :info_logger, :warn_logger, :error_logger
18
+
19
+ def self.attach(parent_disk_handle, child_disk_handle)
20
+ vix_error = super(parent_disk_handle, child_disk_handle)
21
+ check_error(vix_error, __method__)
22
+ nil
23
+ end
24
+
25
+ #
26
+ # The VixDiskLib_CheckRepair method
27
+ #
28
+ def self.check_repair(connection, file_name, repair)
29
+ file_ptr = FFI::MemoryPointer.from_string(file_name)
30
+ vix_error = super(connection, file_ptr, repair)
31
+ check_error(vix_error, __method__)
32
+ nil
33
+ end
34
+
35
+ #
36
+ # The VixDiskLib_Cleanup method
37
+ #
38
+ def self.cleanup(connect_parms)
39
+ safe_parms = SafeConnectParams.new(connect_parms)
40
+ cleaned_up = FFI::MemoryPointer.new :pointer
41
+ remaining = FFI::MemoryPointer.new :pointer
42
+ vix_error = super(safe_parms.connect_params, cleaned_up, remaining)
43
+ num_cleaned_up = cleaned_up.get_uint32(0) unless cleaned_up.nil?
44
+ num_remaining = remaining.get_uint32(0) unless remaining.nil?
45
+ check_error(vix_error, __method__)
46
+ return num_cleaned_up, num_remaining
47
+ end
48
+
49
+ #
50
+ # The VixDiskLib_Clone method
51
+ #
52
+ def self.clone(dest_connection, dest_path, src_connection, src_path, create_parms, over_write)
53
+ dest_ptr = FFI::MemoryPointer.from_string(dest_path)
54
+ src_ptr = FFI::MemoryPointer.from_string(src_path)
55
+ safe_parms = SafeCreateParams.new(create_parms)
56
+ vix_error = super(dest_connection, dest_ptr, src_connection, src_ptr,
57
+ safe_parms.create_params, nil, nil, over_write)
58
+ check_error(vix_error, __method__)
59
+ nil
60
+ end
61
+
62
+ #
63
+ # The VixDiskLib_Close method
64
+ #
65
+ def self.close(disk_handle)
66
+ vix_error = super(disk_handle)
67
+ check_error(vix_error, __method__)
68
+ nil
69
+ end
70
+
71
+ #
72
+ # The VixDiskLib_Connect method
73
+ #
74
+ def self.connect(connect_parms)
75
+ connection = FFI::MemoryPointer.new :pointer
76
+ safe_parms = SafeConnectParams.new(connect_parms)
77
+ vix_error = super(safe_parms.connect_params, connection)
78
+ connection = connection.get_pointer(0)
79
+ check_error(vix_error, __method__)
80
+ connection
81
+ end
82
+
83
+ #
84
+ # The VixDiskLib_ConnectEx method
85
+ #
86
+ def self.connect_ex(connect_parms, read_only, snapshot_ref, transport_modes)
87
+ connection = FFI::MemoryPointer.new :pointer
88
+ safe_parms = SafeConnectParams.new(connect_parms)
89
+ snapshot_ptr = snapshot_ref && FFI::MemoryPointer.from_string(snapshot_ref)
90
+ modes_ptr = transport_modes && FFI::MemoryPointer.from_string(transport_modes)
91
+ vix_error = super(safe_parms.connect_params, read_only, snapshot_ptr, modes_ptr, connection)
92
+ connection = connection.get_pointer(0)
93
+ check_error(vix_error, __method__)
94
+ connection
95
+ end
96
+
97
+ #
98
+ # The VixDiskLib_Create method
99
+ #
100
+ def self.create(connection, path, create_parms, prog_func = nil, prog_callback_data = nil)
101
+ safe_parms = SafeCreateParams.new(create_parms)
102
+ path_ptr = FFI::MemoryPointer.from_string(path)
103
+ vix_error = super(connection, path_ptr, safe_parms.create_params, prog_func, prog_callback_data)
104
+ check_error(vix_error, __method)
105
+ nil
106
+ end
107
+
108
+ #
109
+ # The VixDiskLib_CreateChild method
110
+ #
111
+ def self.create_child(disk_handle, child_path, disk_type, prog_func = nil, prog_callback_data = nil)
112
+ path_ptr = FFI::MemoryPointer.from_string(child_path)
113
+ vix_error = super(disk_handle, path_ptr, disk_type, prog_func, prog_callback_data)
114
+ check_error(vix_error, __method)
115
+ nil
116
+ end
117
+
118
+ #
119
+ # The VixDiskLib_Defragment method
120
+ #
121
+ def self.defragment(disk_handle)
122
+ vix_error = super(disk_handle, nil, nil)
123
+ check_error(vix_error, __method__)
124
+ nil
125
+ end
126
+
127
+ #
128
+ # The VixDiskLib_Disconnect method
129
+ #
130
+ def self.disconnect(connection)
131
+ vix_error = super(connection)
132
+ check_error(vix_error, __method__)
133
+ nil
134
+ end
135
+
136
+ #
137
+ # The VixDiskLib_Access method
138
+ #
139
+ def self.end_access(connect_parms, identity)
140
+ safe_parms = SafeConnectParams.new(connect_parms)
141
+ identity_ptr = FFI::MemoryPointer.from_string(identity)
142
+ vix_error = super(safe_parms.connect_params, identity_ptr)
143
+ check_error(vix_error, __method__)
144
+ nil
145
+ end
146
+
147
+ #
148
+ # The VixDiskLib_Exit method
149
+ #
150
+ def self.exit
151
+ super
152
+ nil
153
+ end
154
+
155
+ #
156
+ # The VixDiskLib_FreeConnectParams method
157
+ #
158
+ def self.free_connect_params(connect_params)
159
+ super(connect_params)
160
+ end
161
+
162
+ #
163
+ # The VixDiskLib_GetConnectParams method
164
+ #
165
+ def self.get_connect_params(connection)
166
+ params_ptr = FFI::MemoryPointer.new :pointer
167
+ vix_error = super(connection, params_ptr)
168
+ check_error(vix_error, __method__)
169
+ ffi_connect_params = params_ptr.get_pointer(0)
170
+ safe_connect_params = SafeConnectParams.read(ffi_connect_params)
171
+ safe_connect_params
172
+ end
173
+
174
+ #
175
+ # The VixDiskLib_GetInfo method
176
+ #
177
+ def self.get_info(disk_handle)
178
+ info = DiskInfo.new(disk_handle)
179
+ info.info
180
+ end
181
+
182
+ #
183
+ # The VixDiskLib_GetMetadataKeys method
184
+ #
185
+ def self.get_metadata_keys(disk_handle)
186
+ #
187
+ # Get the size of the buffer required for the metadata keys for the disk.
188
+ #
189
+ len_ptr = FFI::MemoryPointer.new :pointer
190
+ vix_error = super(disk_handle, nil, 0, len_ptr)
191
+ if vix_error != API::VixErrorType[:VIX_OK] && vix_error != API::VixErrorType[:VIX_E_BUFFER_TOOSMALL]
192
+ check_error(vix_error, __method__)
193
+ end
194
+ #
195
+ # Read the metadata keys for the disk into the allocated buffer.
196
+ #
197
+ buf_size = len_ptr.get_uint64(0)
198
+ read_buf = FFI::MemoryPointer.new(buf_size)
199
+ vix_error = super(disk_handle, read_buf, buf_size, nil)
200
+ check_error(vix_error, __method__)
201
+ keys = read_buf.get_bytes(0, buf_size)
202
+ keys.split("\x00")
203
+ end
204
+
205
+ #
206
+ # The VixDiskLib_GetTransportMode method
207
+ #
208
+ def self.get_transport_mode(disk_handle)
209
+ mode = super(disk_handle)
210
+ mode.read_string
211
+ end
212
+
213
+ #
214
+ # The VixDiskLib_Grow method
215
+ #
216
+ def self.grow(connection, path, capacity, update_geometry)
217
+ path_ptr = FFI::MemoryPointer.from_string(path)
218
+ vix_error = super(connection, path_ptr, capacity, update_geometry, nil, nil)
219
+ check_error(vix_error, __method__)
220
+ nil
221
+ end
222
+
223
+ #
224
+ # The VixDiskLib_Init method
225
+ #
226
+ def self.init(info_logger = nil, warn_logger = nil, error_logger = nil, libDir = nil)
227
+ @info_logger, @warn_logger, @error_logger = info_logger, warn_logger, error_logger
228
+
229
+ vix_error = super(API::VERSION_MAJOR, API::VERSION_MINOR,
230
+ logger_for("info"), logger_for("warn"), logger_for("error"), libDir)
231
+ check_error(vix_error, __method__)
232
+ nil
233
+ end
234
+
235
+ #
236
+ # The VixDiskLib_InitEx method
237
+ #
238
+ def self.init_ex(info_logger = nil, warn_logger = nil, error_logger = nil, libDir = nil, configFile = nil)
239
+ @info_logger, @warn_logger, @error_logger = info_logger, warn_logger, error_logger
240
+
241
+ vix_error = super(API::VERSION_MAJOR, API::VERSION_MINOR,
242
+ logger_for("info"), logger_for("warn"), logger_for("error"), libDir, configFile)
243
+ check_error(vix_error, __method__)
244
+ nil
245
+ end
246
+
247
+ #
248
+ # The VixDiskLib_IsAttachPossible method
249
+ #
250
+ def self.is_attach_possible(parent_disk_handle, child_disk_handle)
251
+ vix_error = super(parent_disk_handle, child_disk_handle)
252
+ VixDiskLib.vix_succeeded?(vix_error)
253
+ end
254
+
255
+ #
256
+ # The VixDiskLib_ListTransportModes method
257
+ #
258
+ def self.list_transport_modes
259
+ list = super
260
+ list.read_string
261
+ end
262
+
263
+ #
264
+ # The VixDiskLib_Open method
265
+ #
266
+ def self.open(connection, path, flags)
267
+ path_ptr = FFI::MemoryPointer.from_string(path)
268
+ disk_handle = FFI::MemoryPointer.new :pointer
269
+ vix_error = super(connection, path_ptr, flags, disk_handle)
270
+ check_error(vix_error, __method__)
271
+ disk_handle.get_pointer(0)
272
+ end
273
+
274
+ #
275
+ # The VixDiskLib_PrepareForAccess method
276
+ #
277
+ def self.prepare_for_access(connect_parms, identity)
278
+ safe_parms = SafeConnectParams.new(connect_parms)
279
+ identity_ptr = FFI::MemoryPointer.from_string(identity)
280
+ vix_error = super(safe_parms.connect_params, identity_ptr)
281
+ check_error(vix_error, __method__)
282
+ nil
283
+ end
284
+
285
+ #
286
+ # The VixDiskLib_Read method
287
+ #
288
+ def self.read(disk_handle, start_sector, num_sectors)
289
+ buf_size = num_sectors * API::VIXDISKLIB_SECTOR_SIZE
290
+ read_buf = FFI::MemoryPointer.new(buf_size)
291
+ read_buf.clear
292
+ vix_error = super(disk_handle, start_sector, num_sectors, read_buf)
293
+ check_error(vix_error, __method__)
294
+ read_buf.get_bytes(0, buf_size)
295
+ end
296
+
297
+ #
298
+ # The VixDiskLib_ReadMetadata method
299
+ #
300
+ def self.read_metadata(disk_handle, key)
301
+ key_ptr = FFI::MemoryPointer.from_string(key)
302
+ #
303
+ # Get the size of the buffer required for the metadata key for this disk.
304
+ #
305
+ len_ptr = FFI::MemoryPointer.new :pointer
306
+ vix_error = super(disk_handle, key_ptr, nil, 0, len_ptr)
307
+ if vix_error != API::VixErrorType[:VIX_OK] && vix_error != API::VixErrorType[:VIX_E_BUFFER_TOOSMALL]
308
+ check_error(vix_error, __method__)
309
+ end
310
+ #
311
+ # Read the metadata key for the disk into the allocated buffer.
312
+ #
313
+ buf_size = len_ptr.get_uint64(0)
314
+ read_buf = FFI::MemoryPointer.new(buf_size)
315
+ vix_error = super(disk_handle, key_ptr, read_buf, buf_size, nil)
316
+ check_error(vix_error, __method__)
317
+ read_buf.get_bytes(0, buf_size)
318
+ end
319
+
320
+ #
321
+ # The VixDiskLib_Rename method
322
+ #
323
+ def self.rename(src_path, dest_path)
324
+ src_ptr = FFI::MemoryPointer.from_string(src_path)
325
+ dest_ptr = FFI::MemoryPointer.from_string(dest_path)
326
+ vix_error = super(src_ptr, dest_ptr)
327
+ check_error(vix_error, __method__)
328
+ nil
329
+ end
330
+
331
+ #
332
+ # The VixDiskLib_Shrink method
333
+ #
334
+ def self.shrink(disk_handle, prog_func = nil, prog_callback_data = nil)
335
+ vix_error = super(disk_handle, prog_func, prog_callback_data)
336
+ check_error(vix_error, __method__)
337
+ nil
338
+ end
339
+
340
+ #
341
+ # The VixDiskLib_SpaceNeededForClone method
342
+ #
343
+ def self.space_needed_for_clone(disk_handle, disk_type)
344
+ needed_ptr = FFI::MemoryPointer.new :pointer
345
+ vix_error = super(disk_handle, disk_type, needed_ptr)
346
+ check_error(vix_error, __method__)
347
+ needed_ptr.get_uint64(0)
348
+ end
349
+
350
+ #
351
+ # The VixDiskLib_Unlink method
352
+ #
353
+ def self.unlink(connection, path)
354
+ path_ptr = FFI::MemoryPointer.from_string(path)
355
+ vix_error = super(connection, path_ptr)
356
+ check_error(vix_error, __method__)
357
+ nil
358
+ end
359
+
360
+ #
361
+ # The VixDiskLib_Write method
362
+ #
363
+ def self.write(disk_handle, start_sector, num_sectors, buf)
364
+ buf_size = num_sectors * :VIXDISKLIB_SECTOR_SIZE
365
+ buf_ptr = FFI::MemoryPointer.new(buf_size)
366
+ buf_ptr.write_bytes(buf, 0, buf_size)
367
+ vix_error = super(disk_handle, start_sector, num_sectors, buf_ptr)
368
+ check_error(vix_error, __method__)
369
+ nil
370
+ end
371
+
372
+ #
373
+ # The VixDiskLib_WriteMetadata method
374
+ #
375
+ def self.write_metadata(disk_handle, key, value)
376
+ key_ptr = FFI::MemoryPointer.from_string(key)
377
+ val_ptr = FFI::MemoryPointer.from_string(value)
378
+ vix_error = super(disk_handle, key_ptr, val_ptr)
379
+ check_error(vix_error, __method__)
380
+ nil
381
+ end
382
+
383
+ private
384
+
385
+ INFO_LOGGER = proc do |fmt, args|
386
+ if @info_logger.nil?
387
+ if $vix_disk_lib_log
388
+ $vix_disk_lib_log.info "VMware(VixDiskLib): #{process_log_args(fmt, args)}"
389
+ else
390
+ puts "INFO: VMware(VixDiskLib): #{process_log_args(fmt, args)}"
391
+ end
392
+ else
393
+ @info_logger.call(process_log_args(fmt, args))
394
+ end
395
+ end
396
+
397
+ WARN_LOGGER = proc do |fmt, args|
398
+ if @warn_logger.nil?
399
+ if $vix_disk_lib_log
400
+ $vix_disk_lib_log.warn "VMware(VixDiskLib): #{process_log_args(fmt, args)}"
401
+ else
402
+ puts "WARN: VMware(VixDiskLib): #{process_log_args(fmt, args)}"
403
+ end
404
+ else
405
+ @warn_logger.call(process_log_args(fmt, args))
406
+ end
407
+ end
408
+
409
+ ERROR_LOGGER = proc do |fmt, args|
410
+ if @error_logger.nil?
411
+ if $vix_disk_lib_log
412
+ $vix_disk_lib_log.error "VMware(VixDiskLib): #{process_log_args(fmt, args)}"
413
+ else
414
+ puts "ERROR: VMware(VixDiskLib): #{process_log_args(fmt, args)}"
415
+ end
416
+ else
417
+ @error_logger.call(process_log_args(fmt, args))
418
+ end
419
+ end
420
+
421
+ def self.logger_for(level)
422
+ instance_variable_get("@#{level.downcase}_logger") && const_get("#{level.upcase}_LOGGER")
423
+ end
424
+
425
+ def self.process_log_args(fmt, args)
426
+ buf = FFI::MemoryPointer.new(:char, 1024, true)
427
+ # LIBC::vsnprintf(buf, 1024, fmt, args)
428
+ LIBC.vsnprintf(buf, 1024, fmt, args)
429
+ buf.read_string.chomp
430
+ end
431
+
432
+ def self.check_error(err, method)
433
+ # if API::vix_failed?(err)
434
+ if API.vix_failed?(err)
435
+ err_msg = get_error_text(err, nil)
436
+ # err_code = API::vix_error_code(err)
437
+ err_code = API.vix_error_code(err)
438
+ err_name = API::VixErrorType[err_code]
439
+ if err_msg.nil? || err_msg.null?
440
+ err_msg = "Error retrieving text of error message for errcode."
441
+ msg = "#{name}##{method} (errcode=#{err_code} - #{err_name}): #{err_msg}"
442
+ else
443
+ msg = "#{name}##{method} (errcode=#{err_code} - #{err_name}): #{err_msg.read_string}"
444
+ free_error_text(err_msg)
445
+ end
446
+ raise VixDiskLibError, "#{msg}"
447
+ end
448
+ end
449
+ end
450
+ end
451
+ end # class FFI::VixDiskLib::ApiWrapper
@@ -0,0 +1,45 @@
1
+ require 'ffi'
2
+
3
+ module FFI
4
+ module VixDiskLib
5
+ module API
6
+ extend FFI::Library
7
+
8
+ # An error is a 64-bit value. If there is no error, then the value is
9
+ # set to VIX_OK. If there is an error, then the least significant bits
10
+ # will be set to one of the integer error codes defined below. The more
11
+ # significant bits may or may not be set to various values, depending on
12
+ # the errors.
13
+
14
+ typedef :uint64, :VixError
15
+
16
+ typedef :uint64, :SectorType
17
+ typedef :pointer, :Connection
18
+
19
+ VIXDISKLIB_SECTOR_SIZE = 512
20
+
21
+ # Virtual hardware version
22
+
23
+ # VMware Workstation 4.x and GSX Server 3.x
24
+ HWVERSION_WORKSTATION_4 = 3
25
+
26
+ # VMware Workstation 5.x and Server 1.x
27
+ HWVERSION_WORKSTATION_5 = 4
28
+
29
+ # VMware ESX Server 3.0
30
+ HWVERSION_ESX30 = HWVERSION_WORKSTATION_5
31
+
32
+ # VMware Workstation 6.x
33
+ HWVERSION_WORKSTATION_6 = 6
34
+
35
+ # Defines the state of the art hardware version. Be careful using this as it
36
+ # will change from time to time.
37
+ HWVERSION_CURRENT = HWVERSION_WORKSTATION_6
38
+
39
+ # Flags for open
40
+ VIXDISKLIB_FLAG_OPEN_UNBUFFERED = (1 << 0) # disable host disk caching
41
+ VIXDISKLIB_FLAG_OPEN_SINGLE_LINK = (1 << 1) # don't open parent disk(s)
42
+ VIXDISKLIB_FLAG_OPEN_READ_ONLY = (1 << 2) # open read-only
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,47 @@
1
+ module FFI
2
+ module VixDiskLib
3
+ class DiskInfo
4
+ extend API
5
+
6
+ attr_reader :info
7
+
8
+ def geometry_attribute(info, offset_value, attribute)
9
+ info.get_uint32(offset_value + Geometry.offset_of(attribute))
10
+ end
11
+
12
+ #
13
+ # Initialize a hash with the disk info for the specified handle
14
+ # using the VixDiskLib_GetInfo method.
15
+ # This is a helper class for the VixDiskLib::Api::get_info method.
16
+ #
17
+ def initialize(disk_handle)
18
+ ruby_info = {}
19
+ info = FFI::MemoryPointer.new :pointer
20
+ vix_error = ApiWrapper.get_info(disk_handle, info)
21
+ ApiWrapper.check_error(vix_error, __method__)
22
+ real_info = info.get_pointer(0)
23
+
24
+ ruby_info[:biosGeo] = {}
25
+ ruby_info[:physGeo] = {}
26
+ bios_offset = API::Info.offset_of(:biosGeo)
27
+ phys_offset = API::Info.offset_of(:biosGeo)
28
+ ruby_info[:biosGeo][:cylinders] = geometry_attribute(real_info, bios_offset, :cylinders)
29
+ ruby_info[:biosGeo][:heads] = geometry_attribute(real_info, bios_offset, :heads)
30
+ ruby_info[:biosGeo][:sectors] = geometry_attribute(real_info, bios_offset, :sectors)
31
+ ruby_info[:physGeo][:cylinders] = geometry_attribute(real_info, phys_offset, :cylinders)
32
+ ruby_info[:physGeo][:heads] = geometry_attribute(real_info, phys_offset, :heads)
33
+ ruby_info[:physGeo][:sectors] = geometry_attribute(real_info, phys_offset, :sectors)
34
+ ruby_info[:capacity] = real_info.get_uint64(API::Info.offset_of(:capacity))
35
+ ruby_info[:adapterType] = real_info.get_int(API::Info.offset_of(:adapterType))
36
+ ruby_info[:numLinks] = real_info.get_int(API::Info.offset_of(:numLinks))
37
+
38
+ parent_info = real_info + API::Info.offset_of(:parentFileNameHint)
39
+ parent_info_str = parent_info.read_pointer
40
+ ruby_info[:parentFileNameHint] = parent_info_str.read_string unless parent_info_str.null?
41
+ uuid_info_str = (real_info + API::Info.offset_of(:uuid)).read_pointer
42
+ ruby_info[:uuid] = uuid_info_str.read_string unless uuid_info_str.null?
43
+ @info = ruby_info
44
+ end
45
+ end
46
+ end
47
+ end # class DiskInfo