ruby-libvirt-catphish 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,490 @@
1
+ /*
2
+ * common.c: Common utilities for the ruby libvirt bindings
3
+ *
4
+ * Copyright (C) 2007,2010 Red Hat Inc.
5
+ * Copyright (C) 2013-2016 Chris Lalancette <clalancette@gmail.com>
6
+ *
7
+ * This library is free software; you can redistribute it and/or
8
+ * modify it under the terms of the GNU Lesser General Public
9
+ * License as published by the Free Software Foundation; either
10
+ * version 2.1 of the License, or (at your option) any later version.
11
+ *
12
+ * This library is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ * Lesser General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU Lesser General Public
18
+ * License along with this library; if not, write to the Free Software
19
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
+ */
21
+
22
+ #ifndef _GNU_SOURCE
23
+ #define _GNU_SOURCE 1
24
+ #endif
25
+ #include <stdio.h>
26
+ #include <ruby.h>
27
+ #include <st.h>
28
+ #include <libvirt/libvirt.h>
29
+ #include <libvirt/virterror.h>
30
+ #include "common.h"
31
+ #include "connect.h"
32
+
33
+ struct rb_exc_new2_arg {
34
+ VALUE error;
35
+ char *msg;
36
+ };
37
+
38
+ static VALUE ruby_libvirt_exc_new2_wrap(VALUE arg)
39
+ {
40
+ struct rb_exc_new2_arg *e = (struct rb_exc_new2_arg *)arg;
41
+
42
+ return rb_exc_new2(e->error, e->msg);
43
+ }
44
+
45
+ VALUE ruby_libvirt_ary_new2_wrap(VALUE arg)
46
+ {
47
+ return rb_ary_new2(*((int *)arg));
48
+ }
49
+
50
+ VALUE ruby_libvirt_ary_push_wrap(VALUE arg)
51
+ {
52
+ struct ruby_libvirt_ary_push_arg *e = (struct ruby_libvirt_ary_push_arg *)arg;
53
+
54
+ return rb_ary_push(e->arr, e->value);
55
+ }
56
+
57
+ VALUE ruby_libvirt_ary_store_wrap(VALUE arg)
58
+ {
59
+ struct ruby_libvirt_ary_store_arg *e = (struct ruby_libvirt_ary_store_arg *)arg;
60
+
61
+ rb_ary_store(e->arr, e->index, e->elem);
62
+
63
+ return Qnil;
64
+ }
65
+
66
+ VALUE ruby_libvirt_str_new2_wrap(VALUE arg)
67
+ {
68
+ char **str = (char **)arg;
69
+
70
+ return rb_str_new2(*str);
71
+ }
72
+
73
+ VALUE ruby_libvirt_str_new_wrap(VALUE arg)
74
+ {
75
+ struct ruby_libvirt_str_new_arg *e = (struct ruby_libvirt_str_new_arg *)arg;
76
+
77
+ return rb_str_new(e->val, e->size);
78
+ }
79
+
80
+ VALUE ruby_libvirt_hash_aset_wrap(VALUE arg)
81
+ {
82
+ struct ruby_libvirt_hash_aset_arg *e = (struct ruby_libvirt_hash_aset_arg *)arg;
83
+
84
+ return rb_hash_aset(e->hash, rb_str_new2(e->name), e->val);
85
+ }
86
+
87
+ VALUE ruby_libvirt_str_new2_and_ary_store_wrap(VALUE arg)
88
+ {
89
+ struct ruby_libvirt_str_new2_and_ary_store_arg *e = (struct ruby_libvirt_str_new2_and_ary_store_arg *)arg;
90
+
91
+ rb_ary_store(e->arr, e->index, rb_str_new2(e->value));
92
+
93
+ return Qnil;
94
+ }
95
+
96
+ void ruby_libvirt_raise_error_if(const int condition, VALUE error,
97
+ const char *method, virConnectPtr conn)
98
+ {
99
+ VALUE ruby_errinfo;
100
+ virErrorPtr err;
101
+ char *msg;
102
+ int rc;
103
+ struct rb_exc_new2_arg arg;
104
+ int exception = 0;
105
+
106
+ if (!condition) {
107
+ return;
108
+ }
109
+
110
+ if (conn == NULL) {
111
+ err = virGetLastError();
112
+ }
113
+ else {
114
+ err = virConnGetLastError(conn);
115
+ }
116
+
117
+ if (err != NULL && err->message != NULL) {
118
+ rc = asprintf(&msg, "Call to %s failed: %s", method, err->message);
119
+ }
120
+ else {
121
+ rc = asprintf(&msg, "Call to %s failed", method);
122
+ }
123
+
124
+ if (rc < 0) {
125
+ /* there's not a whole lot we can do here; try to raise an
126
+ * out-of-memory message */
127
+ rb_memerror();
128
+ }
129
+
130
+ arg.error = error;
131
+ arg.msg = msg;
132
+ ruby_errinfo = rb_protect(ruby_libvirt_exc_new2_wrap, (VALUE)&arg,
133
+ &exception);
134
+ free(msg);
135
+ if (exception) {
136
+ rb_jump_tag(exception);
137
+ }
138
+
139
+ rb_iv_set(ruby_errinfo, "@libvirt_function_name", rb_str_new2(method));
140
+
141
+ if (err != NULL) {
142
+ rb_iv_set(ruby_errinfo, "@libvirt_code", INT2NUM(err->code));
143
+ rb_iv_set(ruby_errinfo, "@libvirt_component", INT2NUM(err->domain));
144
+ rb_iv_set(ruby_errinfo, "@libvirt_level", INT2NUM(err->level));
145
+ if (err->message != NULL) {
146
+ rb_iv_set(ruby_errinfo, "@libvirt_message",
147
+ rb_str_new2(err->message));
148
+ }
149
+ }
150
+
151
+ rb_exc_raise(ruby_errinfo);
152
+ };
153
+
154
+ char *ruby_libvirt_get_cstring_or_null(VALUE arg)
155
+ {
156
+ if (TYPE(arg) == T_NIL) {
157
+ return NULL;
158
+ }
159
+ else if (TYPE(arg) == T_STRING) {
160
+ return StringValueCStr(arg);
161
+ }
162
+ else {
163
+ rb_raise(rb_eTypeError, "wrong argument type (expected String or nil)");
164
+ }
165
+
166
+ return NULL;
167
+ }
168
+
169
+ VALUE ruby_libvirt_new_class(VALUE klass, void *ptr, VALUE conn,
170
+ RUBY_DATA_FUNC free_func)
171
+ {
172
+ VALUE result;
173
+ result = Data_Wrap_Struct(klass, NULL, free_func, ptr);
174
+ rb_iv_set(result, "@connection", conn);
175
+ return result;
176
+ }
177
+
178
+ int ruby_libvirt_is_symbol_or_proc(VALUE handle)
179
+ {
180
+ return ((strcmp(rb_obj_classname(handle), "Symbol") == 0) ||
181
+ (strcmp(rb_obj_classname(handle), "Proc") == 0));
182
+ }
183
+
184
+ /* this is an odd function, because it has massive side-effects.
185
+ * The intended usage of this function is after a list has been collected
186
+ * from a libvirt list function, and now we want to make an array out of it.
187
+ * However, it is possible that the act of creating an array causes an
188
+ * exception, which would lead to a memory leak of the values we got from
189
+ * libvirt. Therefore, this function not only wraps all of the relevant
190
+ * calls with rb_protect, it also frees every individual entry in list after
191
+ * it is done with it. Freeing list itself is left to the callers.
192
+ */
193
+ VALUE ruby_libvirt_generate_list(int num, char **list)
194
+ {
195
+ VALUE result;
196
+ int exception = 0;
197
+ int i, j;
198
+ struct ruby_libvirt_str_new2_and_ary_store_arg arg;
199
+
200
+ i = 0;
201
+
202
+ result = rb_protect(ruby_libvirt_ary_new2_wrap, (VALUE)&num, &exception);
203
+ if (exception) {
204
+ goto exception;
205
+ }
206
+ for (i = 0; i < num; i++) {
207
+ arg.arr = result;
208
+ arg.index = i;
209
+ arg.value = list[i];
210
+ rb_protect(ruby_libvirt_str_new2_and_ary_store_wrap, (VALUE)&arg,
211
+ &exception);
212
+ if (exception) {
213
+ goto exception;
214
+ }
215
+
216
+ xfree(list[i]);
217
+ }
218
+
219
+ return result;
220
+
221
+ exception:
222
+ for (j = i; j < num; j++) {
223
+ xfree(list[j]);
224
+ }
225
+ rb_jump_tag(exception);
226
+
227
+ /* not needed, but here to shut the compiler up */
228
+ return Qnil;
229
+ }
230
+
231
+ void ruby_libvirt_typed_params_to_hash(void *voidparams, int i, VALUE hash)
232
+ {
233
+ virTypedParameterPtr params = (virTypedParameterPtr)voidparams;
234
+ VALUE val;
235
+
236
+ switch (params[i].type) {
237
+ case VIR_TYPED_PARAM_INT:
238
+ val = INT2NUM(params[i].value.i);
239
+ break;
240
+ case VIR_TYPED_PARAM_UINT:
241
+ val = UINT2NUM(params[i].value.ui);
242
+ break;
243
+ case VIR_TYPED_PARAM_LLONG:
244
+ val = LL2NUM(params[i].value.l);
245
+ break;
246
+ case VIR_TYPED_PARAM_ULLONG:
247
+ val = ULL2NUM(params[i].value.ul);
248
+ break;
249
+ case VIR_TYPED_PARAM_DOUBLE:
250
+ val = rb_float_new(params[i].value.d);
251
+ break;
252
+ case VIR_TYPED_PARAM_BOOLEAN:
253
+ val = (params[i].value.b == 0) ? Qfalse : Qtrue;
254
+ break;
255
+ case VIR_TYPED_PARAM_STRING:
256
+ val = rb_str_new2(params[i].value.s);
257
+ break;
258
+ default:
259
+ rb_raise(rb_eArgError, "Invalid parameter type");
260
+ }
261
+
262
+ rb_hash_aset(hash, rb_str_new2(params[i].field), val);
263
+ }
264
+
265
+ VALUE ruby_libvirt_get_parameters(VALUE d, unsigned int flags, void *opaque,
266
+ unsigned int typesize,
267
+ const char *(*nparams_cb)(VALUE d,
268
+ unsigned int flags,
269
+ void *opaque,
270
+ int *nparams),
271
+ const char *(*get_cb)(VALUE d,
272
+ unsigned int flags,
273
+ void *voidparams,
274
+ int *nparams,
275
+ void *opaque),
276
+ void (*hash_set)(void *voidparams, int i,
277
+ VALUE result))
278
+ {
279
+ int nparams = 0;
280
+ void *params;
281
+ VALUE result;
282
+ const char *errname;
283
+ int i;
284
+
285
+ errname = nparams_cb(d, flags, opaque, &nparams);
286
+ ruby_libvirt_raise_error_if(errname != NULL, e_RetrieveError, errname,
287
+ ruby_libvirt_connect_get(d));
288
+
289
+ result = rb_hash_new();
290
+
291
+ if (nparams == 0) {
292
+ return result;
293
+ }
294
+
295
+ params = alloca(typesize * nparams);
296
+
297
+ errname = get_cb(d, flags, params, &nparams, opaque);
298
+ ruby_libvirt_raise_error_if(errname != NULL, e_RetrieveError, errname,
299
+ ruby_libvirt_connect_get(d));
300
+
301
+ for (i = 0; i < nparams; i++) {
302
+ hash_set(params, i, result);
303
+ }
304
+
305
+ return result;
306
+ }
307
+
308
+ VALUE ruby_libvirt_get_typed_parameters(VALUE d, unsigned int flags,
309
+ void *opaque,
310
+ const char *(*nparams_cb)(VALUE d,
311
+ unsigned int flags,
312
+ void *opaque,
313
+ int *nparams),
314
+ const char *(*get_cb)(VALUE d,
315
+ unsigned int flags,
316
+ void *params,
317
+ int *nparams,
318
+ void *opaque))
319
+ {
320
+ return ruby_libvirt_get_parameters(d, flags, opaque,
321
+ sizeof(virTypedParameter), nparams_cb,
322
+ get_cb,
323
+ ruby_libvirt_typed_params_to_hash);
324
+ }
325
+
326
+ void ruby_libvirt_assign_hash_and_flags(VALUE in, VALUE *hash, VALUE *flags)
327
+ {
328
+ if (TYPE(in) == T_HASH) {
329
+ *hash = in;
330
+ *flags = INT2NUM(0);
331
+ }
332
+ else if (TYPE(in) == T_ARRAY) {
333
+ if (RARRAY_LEN(in) != 2) {
334
+ rb_raise(rb_eArgError, "wrong number of arguments (%ld for 1 or 2)",
335
+ RARRAY_LEN(in));
336
+ }
337
+ *hash = rb_ary_entry(in, 0);
338
+ *flags = rb_ary_entry(in, 1);
339
+ }
340
+ else {
341
+ rb_raise(rb_eTypeError, "wrong argument type (expected Hash or Array)");
342
+ }
343
+ }
344
+
345
+ int ruby_libvirt_typed_parameter_assign(VALUE key, VALUE val, VALUE in)
346
+ {
347
+ struct ruby_libvirt_parameter_assign_args *args = (struct ruby_libvirt_parameter_assign_args *)in;
348
+ char *keyname;
349
+ unsigned int i;
350
+ int found;
351
+
352
+ keyname = StringValueCStr(key);
353
+
354
+ found = 0;
355
+ for (i = 0; i < args->num_allowed; i++) {
356
+ if (strcmp(args->allowed[i].name, keyname) == 0) {
357
+ args->params[args->i].type = args->allowed[i].type;
358
+ switch (args->params[args->i].type) {
359
+ case VIR_TYPED_PARAM_INT:
360
+ args->params[i].value.i = NUM2INT(val);
361
+ break;
362
+ case VIR_TYPED_PARAM_UINT:
363
+ args->params[i].value.ui = NUM2UINT(val);
364
+ break;
365
+ case VIR_TYPED_PARAM_LLONG:
366
+ args->params[i].value.l = NUM2LL(val);
367
+ break;
368
+ case VIR_TYPED_PARAM_ULLONG:
369
+ args->params[args->i].value.ul = NUM2ULL(val);
370
+ break;
371
+ case VIR_TYPED_PARAM_DOUBLE:
372
+ args->params[i].value.d = NUM2DBL(val);
373
+ break;
374
+ case VIR_TYPED_PARAM_BOOLEAN:
375
+ args->params[i].value.b = (val == Qtrue) ? 1 : 0;
376
+ break;
377
+ case VIR_TYPED_PARAM_STRING:
378
+ args->params[args->i].value.s = StringValueCStr(val);
379
+ break;
380
+ default:
381
+ rb_raise(rb_eArgError, "Invalid parameter type");
382
+ }
383
+ /* ensure that the field is NULL-terminated */
384
+ args->params[args->i].field[VIR_TYPED_PARAM_FIELD_LENGTH - 1] = '\0';
385
+ strncpy(args->params[args->i].field, keyname,
386
+ VIR_TYPED_PARAM_FIELD_LENGTH - 1);
387
+ (args->i)++;
388
+ found = 1;
389
+ break;
390
+ }
391
+ }
392
+
393
+ if (!found) {
394
+ rb_raise(rb_eArgError, "Unknown key %s", keyname);
395
+ }
396
+
397
+ return ST_CONTINUE;
398
+ }
399
+
400
+ VALUE ruby_libvirt_set_typed_parameters(VALUE d, VALUE input,
401
+ unsigned int flags, void *opaque,
402
+ struct ruby_libvirt_typed_param *allowed,
403
+ unsigned int num_allowed,
404
+ const char *(*set_cb)(VALUE d,
405
+ unsigned int flags,
406
+ virTypedParameterPtr params,
407
+ int nparams,
408
+ void *opaque))
409
+ {
410
+ const char *errname;
411
+ struct ruby_libvirt_parameter_assign_args args;
412
+ unsigned long hashsize;
413
+
414
+ /* make sure input is a hash */
415
+ Check_Type(input, T_HASH);
416
+
417
+ hashsize = RHASH_SIZE(input);
418
+
419
+ if (hashsize == 0) {
420
+ return Qnil;
421
+ }
422
+
423
+ args.allowed = allowed;
424
+ args.num_allowed = num_allowed;
425
+ args.params = alloca(sizeof(virTypedParameter) * hashsize);
426
+ args.i = 0;
427
+
428
+ rb_hash_foreach(input, ruby_libvirt_typed_parameter_assign, (VALUE)&args);
429
+
430
+ errname = set_cb(d, flags, args.params, args.i, opaque);
431
+ ruby_libvirt_raise_error_if(errname != NULL, e_RetrieveError, errname,
432
+ ruby_libvirt_connect_get(d));
433
+
434
+ return Qnil;
435
+ }
436
+
437
+ unsigned int ruby_libvirt_value_to_uint(VALUE in)
438
+ {
439
+ if (NIL_P(in)) {
440
+ return 0;
441
+ }
442
+
443
+ return NUM2UINT(in);
444
+ }
445
+
446
+ int ruby_libvirt_value_to_int(VALUE in)
447
+ {
448
+ if (NIL_P(in)) {
449
+ return 0;
450
+ }
451
+
452
+ return NUM2INT(in);
453
+ }
454
+
455
+ unsigned long ruby_libvirt_value_to_ulong(VALUE in)
456
+ {
457
+ if (NIL_P(in)) {
458
+ return 0;
459
+ }
460
+
461
+ return NUM2ULONG(in);
462
+ }
463
+
464
+ unsigned long long ruby_libvirt_value_to_ulonglong(VALUE in)
465
+ {
466
+ if (NIL_P(in)) {
467
+ return 0;
468
+ }
469
+
470
+ return NUM2ULL(in);
471
+ }
472
+
473
+ int ruby_libvirt_get_maxcpus(virConnectPtr conn)
474
+ {
475
+ int maxcpu = -1;
476
+ virNodeInfo nodeinfo;
477
+
478
+ #if HAVE_VIRNODEGETCPUMAP
479
+ maxcpu = virNodeGetCPUMap(conn, NULL, NULL, 0);
480
+ #endif
481
+ if (maxcpu < 0) {
482
+ /* fall back to nodeinfo */
483
+ ruby_libvirt_raise_error_if(virNodeGetInfo(conn, &nodeinfo) < 0,
484
+ e_RetrieveError, "virNodeGetInfo", conn);
485
+
486
+ maxcpu = VIR_NODEINFO_MAXCPUS(nodeinfo);
487
+ }
488
+
489
+ return maxcpu;
490
+ }