ffi-vix_disk_lib 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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