Define virNetworkPortPtr typedef on old libvirt
[libvirt-python/ericb.git] / libvirt-utils.c
blob78b94caa7103730313f50cb807a0fa584fbee9ba
1 /*
2 * libvirt-utils.c: misc helper APIs for python binding
4 * Copyright (C) 2013 Red Hat, Inc.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library. If not, see
18 * <http://www.gnu.org/licenses/>.
22 #include <Python.h>
24 /* Ugly python defines that, which is also defined in errno.h */
25 #undef _POSIC_C_SOURCE
27 /* We want to see *_LAST enums. */
28 #define VIR_ENUM_SENTINELS
30 #include <errno.h>
31 #include <stddef.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <libvirt/libvirt.h>
35 #include "libvirt-utils.h"
36 #include "typewrappers.h"
38 /**
39 * virAlloc:
40 * @ptrptr: pointer to pointer for address of allocated memory
41 * @size: number of bytes to allocate
43 * Allocate 'size' bytes of memory. Return the address of the
44 * allocated memory in 'ptrptr'. The newly allocated memory is
45 * filled with zeros.
47 * Returns -1 on failure to allocate, zero on success
49 int
50 virAlloc(void *ptrptr,
51 size_t size)
53 *(void **)ptrptr = calloc(1, size);
54 if (*(void **)ptrptr == NULL) {
55 return -1;
57 return 0;
60 /**
61 * virAllocN:
62 * @ptrptr: pointer to pointer for address of allocated memory
63 * @size: number of bytes to allocate
64 * @count: number of elements to allocate
66 * Allocate an array of memory 'count' elements long,
67 * each with 'size' bytes. Return the address of the
68 * allocated memory in 'ptrptr'. The newly allocated
69 * memory is filled with zeros.
71 * Returns -1 on failure to allocate, zero on success
73 int
74 virAllocN(void *ptrptr,
75 size_t size,
76 size_t count)
78 *(void**)ptrptr = calloc(count, size);
79 if (*(void**)ptrptr == NULL) {
80 return -1;
82 return 0;
85 /**
86 * virReallocN:
87 * @ptrptr: pointer to pointer for address of allocated memory
88 * @size: number of bytes to allocate
89 * @count: number of elements in array
91 * Resize the block of memory in 'ptrptr' to be an array of
92 * 'count' elements, each 'size' bytes in length. Update 'ptrptr'
93 * with the address of the newly allocated memory. On failure,
94 * 'ptrptr' is not changed and still points to the original memory
95 * block. Any newly allocated memory in 'ptrptr' is uninitialized.
97 * Returns -1 on failure to allocate, zero on success
99 int
100 virReallocN(void *ptrptr,
101 size_t size,
102 size_t count)
104 void *tmp;
106 if (xalloc_oversized(count, size)) {
107 errno = ENOMEM;
108 return -1;
110 tmp = realloc(*(void**)ptrptr, size * count);
111 if (!tmp && ((size * count) != 0)) {
112 return -1;
114 *(void**)ptrptr = tmp;
115 return 0;
120 * virFree:
121 * @ptrptr: pointer to pointer for address of memory to be freed
123 * Release the chunk of memory in the pointer pointed to by
124 * the 'ptrptr' variable. After release, 'ptrptr' will be
125 * updated to point to NULL.
127 void
128 virFree(void *ptrptr)
130 int save_errno = errno;
132 free(*(void**)ptrptr);
133 *(void**)ptrptr = NULL;
134 errno = save_errno;
139 virFileClose(int *fdptr)
141 int saved_errno = 0;
142 int rc = 0;
144 saved_errno = errno;
146 if (*fdptr < 0)
147 return 0;
149 rc = close(*fdptr);
150 *fdptr = -1;
152 errno = saved_errno;
154 return rc;
157 #if ! LIBVIR_CHECK_VERSION(1, 0, 2)
159 * virTypedParamsClear:
160 * @params: the array of the typed parameters
161 * @nparams: number of parameters in the @params array
163 * Frees all memory used by string parameters. The memory occupied by @params
164 * is not free; use virTypedParamsFree if you want it to be freed too.
166 * Returns nothing.
168 void
169 virTypedParamsClear(virTypedParameterPtr params,
170 int nparams)
172 size_t i;
174 if (!params)
175 return;
177 for (i = 0; i < nparams; i++) {
178 if (params[i].type == VIR_TYPED_PARAM_STRING)
179 VIR_FREE(params[i].value.s);
184 * virTypedParamsFree:
185 * @params: the array of the typed parameters
186 * @nparams: number of parameters in the @params array
188 * Frees all memory used by string parameters and the memory occuiped by
189 * @params.
191 * Returns nothing.
193 void
194 virTypedParamsFree(virTypedParameterPtr params,
195 int nparams)
197 virTypedParamsClear(params, nparams);
198 VIR_FREE(params);
200 #endif /* ! LIBVIR_CHECK_VERSION(1, 0, 2) */
202 /* Helper function to convert a virTypedParameter output array into a
203 * Python dictionary for return to the user. Return NULL on failure,
204 * after raising a python exception. */
205 PyObject *
206 getPyVirTypedParameter(const virTypedParameter *params,
207 int nparams)
209 PyObject *key, *val, *info;
210 ssize_t i;
212 if ((info = PyDict_New()) == NULL)
213 return NULL;
215 for (i = 0; i < nparams; i++) {
216 switch (params[i].type) {
217 case VIR_TYPED_PARAM_INT:
218 val = libvirt_intWrap(params[i].value.i);
219 break;
221 case VIR_TYPED_PARAM_UINT:
222 val = libvirt_intWrap(params[i].value.ui);
223 break;
225 case VIR_TYPED_PARAM_LLONG:
226 val = libvirt_longlongWrap(params[i].value.l);
227 break;
229 case VIR_TYPED_PARAM_ULLONG:
230 val = libvirt_ulonglongWrap(params[i].value.ul);
231 break;
233 case VIR_TYPED_PARAM_DOUBLE:
234 val = PyFloat_FromDouble(params[i].value.d);
235 break;
237 case VIR_TYPED_PARAM_BOOLEAN:
238 val = PyBool_FromLong(params[i].value.b);
239 break;
241 case VIR_TYPED_PARAM_STRING:
242 val = libvirt_constcharPtrWrap(params[i].value.s);
243 break;
245 default:
246 /* Possible if a newer server has a bug and sent stuff we
247 * don't recognize. */
248 PyErr_Format(PyExc_LookupError,
249 "Type value \"%d\" not recognized",
250 params[i].type);
251 val = NULL;
252 break;
255 key = libvirt_constcharPtrWrap(params[i].field);
257 VIR_PY_DICT_SET_GOTO(info, key, val, cleanup);
259 return info;
261 cleanup:
262 Py_DECREF(info);
263 return NULL;
266 /* Allocate a new typed parameter array with the same contents and
267 * length as info, and using the array params of length nparams as
268 * hints on what types to use when creating the new array. The caller
269 * must clear the array before freeing it. Return NULL on failure,
270 * after raising a python exception. */
271 virTypedParameterPtr
272 setPyVirTypedParameter(PyObject *info,
273 const virTypedParameter *params,
274 int nparams)
276 PyObject *key, *value;
277 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION <= 4
278 int pos = 0;
279 #else
280 Py_ssize_t pos = 0;
281 #endif
282 virTypedParameterPtr temp = NULL, ret = NULL;
283 Py_ssize_t size;
284 ssize_t i;
286 if ((size = PyDict_Size(info)) < 0)
287 return NULL;
289 /* Libvirt APIs use NULL array and 0 size as a special case;
290 * setting should have at least one parameter. */
291 if (size == 0) {
292 PyErr_Format(PyExc_LookupError, "Dictionary must not be empty");
293 return NULL;
296 if (VIR_ALLOC_N(ret, size) < 0) {
297 PyErr_NoMemory();
298 return NULL;
301 temp = &ret[0];
302 while (PyDict_Next(info, &pos, &key, &value)) {
303 char *keystr = NULL;
305 if (libvirt_charPtrUnwrap(key, &keystr) < 0)
306 goto cleanup;
308 for (i = 0; i < nparams; i++) {
309 if (STREQ(params[i].field, keystr))
310 break;
312 if (i == nparams) {
313 PyErr_Format(PyExc_LookupError,
314 "Attribute name \"%s\" could not be recognized",
315 keystr);
316 VIR_FREE(keystr);
317 goto cleanup;
320 strncpy(temp->field, keystr, VIR_TYPED_PARAM_FIELD_LENGTH - 1);
321 temp->type = params[i].type;
322 VIR_FREE(keystr);
324 switch (params[i].type) {
325 case VIR_TYPED_PARAM_INT:
326 if (libvirt_intUnwrap(value, &temp->value.i) < 0)
327 goto cleanup;
328 break;
330 case VIR_TYPED_PARAM_UINT:
331 if (libvirt_uintUnwrap(value, &temp->value.ui) < 0)
332 goto cleanup;
333 break;
335 case VIR_TYPED_PARAM_LLONG:
336 if (libvirt_longlongUnwrap(value, &temp->value.l) < 0)
337 goto cleanup;
338 break;
340 case VIR_TYPED_PARAM_ULLONG:
341 if (libvirt_ulonglongUnwrap(value, &temp->value.ul) < 0)
342 goto cleanup;
343 break;
345 case VIR_TYPED_PARAM_DOUBLE:
346 if (libvirt_doubleUnwrap(value, &temp->value.d) < 0)
347 goto cleanup;
348 break;
350 case VIR_TYPED_PARAM_BOOLEAN:
352 bool b;
353 if (libvirt_boolUnwrap(value, &b) < 0)
354 goto cleanup;
355 temp->value.b = b;
356 break;
358 case VIR_TYPED_PARAM_STRING:
360 char *string_val;
361 if (libvirt_charPtrUnwrap(value, &string_val) < 0)
362 goto cleanup;
363 temp->value.s = string_val;
364 break;
367 default:
368 /* Possible if a newer server has a bug and sent stuff we
369 * don't recognize. */
370 PyErr_Format(PyExc_LookupError,
371 "Type value \"%d\" not recognized",
372 params[i].type);
373 goto cleanup;
376 temp++;
378 return ret;
380 cleanup:
381 virTypedParamsFree(ret, size);
382 return NULL;
386 /* While these appeared in libvirt in 1.0.2, we only
387 * need them in the python from 1.1.0 onwards */
388 #if LIBVIR_CHECK_VERSION(1, 1, 0)
390 virPyDictToTypedParamOne(virTypedParameterPtr *params,
391 int *n,
392 int *max,
393 virPyTypedParamsHintPtr hints,
394 int nhints,
395 const char *keystr,
396 PyObject *value)
398 int rv = -1, type = -1;
399 ssize_t i;
401 for (i = 0; i < nhints; i++) {
402 if (STREQ(hints[i].name, keystr)) {
403 type = hints[i].type;
404 break;
408 if (type == -1) {
409 if (libvirt_PyString_Check(value)) {
410 type = VIR_TYPED_PARAM_STRING;
411 } else if (PyBool_Check(value)) {
412 type = VIR_TYPED_PARAM_BOOLEAN;
413 } else if (PyLong_Check(value)) {
414 unsigned long long ull = PyLong_AsUnsignedLongLong(value);
415 if (ull == (unsigned long long) -1 && PyErr_Occurred())
416 type = VIR_TYPED_PARAM_LLONG;
417 else
418 type = VIR_TYPED_PARAM_ULLONG;
419 #if PY_MAJOR_VERSION < 3
420 } else if (PyInt_Check(value)) {
421 if (PyInt_AS_LONG(value) < 0)
422 type = VIR_TYPED_PARAM_LLONG;
423 else
424 type = VIR_TYPED_PARAM_ULLONG;
425 #endif
426 } else if (PyFloat_Check(value)) {
427 type = VIR_TYPED_PARAM_DOUBLE;
431 if (type == -1) {
432 PyErr_Format(PyExc_TypeError,
433 "Unknown type of \"%s\" field", keystr);
434 goto cleanup;
437 switch ((virTypedParameterType) type) {
438 case VIR_TYPED_PARAM_INT:
440 int val;
441 if (libvirt_intUnwrap(value, &val) < 0 ||
442 virTypedParamsAddInt(params, n, max, keystr, val) < 0)
443 goto cleanup;
444 break;
446 case VIR_TYPED_PARAM_UINT:
448 unsigned int val;
449 if (libvirt_uintUnwrap(value, &val) < 0 ||
450 virTypedParamsAddUInt(params, n, max, keystr, val) < 0)
451 goto cleanup;
452 break;
454 case VIR_TYPED_PARAM_LLONG:
456 long long val;
457 if (libvirt_longlongUnwrap(value, &val) < 0 ||
458 virTypedParamsAddLLong(params, n, max, keystr, val) < 0)
459 goto cleanup;
460 break;
462 case VIR_TYPED_PARAM_ULLONG:
464 unsigned long long val;
465 if (libvirt_ulonglongUnwrap(value, &val) < 0 ||
466 virTypedParamsAddULLong(params, n, max, keystr, val) < 0)
467 goto cleanup;
468 break;
470 case VIR_TYPED_PARAM_DOUBLE:
472 double val;
473 if (libvirt_doubleUnwrap(value, &val) < 0 ||
474 virTypedParamsAddDouble(params, n, max, keystr, val) < 0)
475 goto cleanup;
476 break;
478 case VIR_TYPED_PARAM_BOOLEAN:
480 bool val;
481 if (libvirt_boolUnwrap(value, &val) < 0 ||
482 virTypedParamsAddBoolean(params, n, max, keystr, val) < 0)
483 goto cleanup;
484 break;
486 case VIR_TYPED_PARAM_STRING:
488 char *val;;
489 if (libvirt_charPtrUnwrap(value, &val) < 0 ||
490 virTypedParamsAddString(params, n, max, keystr, val) < 0) {
491 VIR_FREE(val);
492 goto cleanup;
494 VIR_FREE(val);
495 break;
497 case VIR_TYPED_PARAM_LAST:
498 break; /* unreachable */
501 rv = 0;
503 cleanup:
504 return rv;
508 /* Automatically convert dict into type parameters based on types reported
509 * by python. All integer types are converted into LLONG (in case of a negative
510 * value) or ULLONG (in case of a positive value). If you need different
511 * handling, use @hints to explicitly specify what types should be used for
512 * specific parameters.
515 virPyDictToTypedParams(PyObject *dict,
516 virTypedParameterPtr *ret_params,
517 int *ret_nparams,
518 virPyTypedParamsHintPtr hints,
519 int nhints)
521 PyObject *key;
522 PyObject *value;
523 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION <= 4
524 int pos = 0;
525 #else
526 Py_ssize_t pos = 0;
527 #endif
528 virTypedParameterPtr params = NULL;
529 int n = 0;
530 int max = 0;
531 int ret = -1;
532 char *keystr = NULL;
534 *ret_params = NULL;
535 *ret_nparams = 0;
537 if (PyDict_Size(dict) < 0)
538 return -1;
540 while (PyDict_Next(dict, &pos, &key, &value)) {
541 if (libvirt_charPtrUnwrap(key, &keystr) < 0)
542 goto cleanup;
544 if (PyList_Check(value) || PyTuple_Check(value)) {
545 Py_ssize_t i, size = PySequence_Size(value);
547 for (i = 0; i < size; i++) {
548 PyObject *v = PySequence_ITEM(value, i);
549 if (virPyDictToTypedParamOne(&params, &n, &max,
550 hints, nhints, keystr, v) < 0)
551 goto cleanup;
553 } else if (virPyDictToTypedParamOne(&params, &n, &max,
554 hints, nhints, keystr, value) < 0)
555 goto cleanup;
557 VIR_FREE(keystr);
560 *ret_params = params;
561 *ret_nparams = n;
562 params = NULL;
563 ret = 0;
565 cleanup:
566 VIR_FREE(keystr);
567 virTypedParamsFree(params, n);
568 return ret;
570 #endif /* LIBVIR_CHECK_VERSION(1, 1, 0) */
573 /* virPyCpumapConvert
574 * @cpunum: the number of physical cpus of the host.
575 * @pycpumap: source cpu map, python tuple of bools.
576 * @cpumapptr: destination cpu map.
577 * @cpumaplen: destination cpu map length.
579 * Helper function to convert a pycpumap to char*.
581 * Returns 0 on success, -1 on failure with error set.
584 virPyCpumapConvert(int cpunum,
585 PyObject *pycpumap,
586 unsigned char **cpumapptr,
587 int *cpumaplen)
589 int tuple_size;
590 ssize_t i;
591 *cpumapptr = NULL;
593 if (!PyTuple_Check(pycpumap)) {
594 PyErr_SetString(PyExc_TypeError, "Unexpected type, tuple is required");
595 return -1;
598 *cpumaplen = VIR_CPU_MAPLEN(cpunum);
600 if ((tuple_size = PyTuple_Size(pycpumap)) == -1)
601 return -1;
603 if (VIR_ALLOC_N(*cpumapptr, *cpumaplen) < 0) {
604 PyErr_NoMemory();
605 return -1;
608 for (i = 0; i < cpunum && i < tuple_size; i++) {
609 PyObject *flag = PyTuple_GetItem(pycpumap, i);
610 bool b;
612 if (!flag || libvirt_boolUnwrap(flag, &b) < 0) {
613 VIR_FREE(*cpumapptr);
614 return -1;
617 if (b)
618 VIR_USE_CPU(*cpumapptr, i);
621 return 0;