X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=libvirt%2Flibvirt_c_oneoffs.c;h=69d1b408d349d44a13fc594802d693c910e6ba56;hb=c27cacae2abac36e2ae89e3e354ec7b0ba8a70dc;hp=958ba69494502a193e455baac01f3c24e881c18f;hpb=3169af3337938e18bf9ecc6ce936d644e14ff3de;p=ocaml-libvirt.git diff --git a/libvirt/libvirt_c_oneoffs.c b/libvirt/libvirt_c_oneoffs.c index 958ba69..69d1b40 100644 --- a/libvirt/libvirt_c_oneoffs.c +++ b/libvirt/libvirt_c_oneoffs.c @@ -76,6 +76,136 @@ ocaml_libvirt_connect_open_readonly (value namev, value unit) CAMLreturn (rv); } +/* Helper struct holding data needed for the helper C authentication + * callback (which will call the actual OCaml callback). + */ +struct ocaml_auth_callback_data { + value *fvp; /* The OCaml auth callback. */ +}; + +static int +_ocaml_auth_callback (virConnectCredentialPtr cred, unsigned int ncred, void *cbdata) +{ + CAMLparam0 (); + CAMLlocal4 (listv, elemv, rv, v); + struct ocaml_auth_callback_data *s = cbdata; + int i, len; + + listv = Val_emptylist; + for (i = ncred - 1; i >= 0; --i) { + elemv = caml_alloc (2, 0); + Store_field (elemv, 0, Val_virconnectcredential (&cred[i])); + Store_field (elemv, 1, listv); + listv = elemv; + } + + /* Call the auth callback. */ + rv = caml_callback_exn (*s->fvp, listv); + if (Is_exception_result (rv)) { + /* The callback raised an exception, so return an error. */ + CAMLreturnT (int, -1); + } + + len = _list_length (rv); + if (len != (int) ncred) { + /* The callback did not return the same number of results as the + * credentials. + */ + CAMLreturnT (int, -1); + } + + for (i = 0; rv != Val_emptylist; rv = Field (rv, 1), ++i) { + virConnectCredentialPtr c = &cred[i]; + elemv = Field (rv, 0); + if (elemv == Val_int (0)) { + c->result = NULL; + c->resultlen = 0; + } else { + v = Field (elemv, 0); + len = caml_string_length (v); + c->result = malloc (len + 1); + if (c->result == NULL) + CAMLreturnT (int, -1); + memcpy (c->result, String_val (v), len); + c->result[len] = '\0'; + c->resultlen = len; + } + } + + CAMLreturnT (int, 0); +} + +static virConnectPtr +_ocaml_libvirt_connect_open_auth_common (value namev, value authv, int flags) +{ + CAMLparam2 (namev, authv); + CAMLlocal2 (listv, fv); + virConnectPtr conn; + virConnectAuth auth; + struct ocaml_auth_callback_data data; + int i; + char *name = NULL; + + /* Keep a copy of the 'namev' string, as its value could move around + * when calling other OCaml code that allocates memory. + */ + if (namev != Val_int (0)) { /* Some string */ + name = strdup (String_val (Field (namev, 0))); + if (name == NULL) + caml_raise_out_of_memory (); + } + + fv = Field (authv, 1); + data.fvp = &fv; + + listv = Field (authv, 0); + auth.ncredtype = _list_length (listv); + auth.credtype = malloc (sizeof (int) * auth.ncredtype); + if (auth.credtype == NULL) + caml_raise_out_of_memory (); + for (i = 0; listv != Val_emptylist; listv = Field (listv, 1), ++i) { + auth.credtype[i] = Int_val (Field (listv, 0)) + 1; + } + auth.cb = &_ocaml_auth_callback; + auth.cbdata = &data; + + /* Call virConnectOpenAuth directly, without using the NONBLOCKING + * macro, as this will indeed call ocaml_* APIs, and run OCaml code. + */ + conn = virConnectOpenAuth (name, &auth, flags); + free (auth.credtype); + free (name); + CHECK_ERROR (!conn, "virConnectOpenAuth"); + + CAMLreturnT (virConnectPtr, conn); +} + +CAMLprim value +ocaml_libvirt_connect_open_auth (value namev, value authv) +{ + CAMLparam2 (namev, authv); + CAMLlocal1 (rv); + virConnectPtr conn; + + conn = _ocaml_libvirt_connect_open_auth_common (namev, authv, 0); + rv = Val_connect (conn); + + CAMLreturn (rv); +} + +CAMLprim value +ocaml_libvirt_connect_open_auth_readonly (value namev, value authv) +{ + CAMLparam2 (namev, authv); + CAMLlocal1 (rv); + virConnectPtr conn; + + conn = _ocaml_libvirt_connect_open_auth_common (namev, authv, VIR_CONNECT_RO); + rv = Val_connect (conn); + + CAMLreturn (rv); +} + CAMLprim value ocaml_libvirt_connect_get_version (value connv) { @@ -154,16 +284,21 @@ ocaml_libvirt_connect_node_get_cells_free_memory (value connv, int start = Int_val (startv); int max = Int_val (maxv); int r, i; - unsigned long long freemems[max]; + unsigned long long *freemems; + + freemems = malloc(sizeof (*freemems) * max); + if (freemems == NULL) + caml_raise_out_of_memory (); NONBLOCKING (r = virNodeGetCellsFreeMemory (conn, freemems, start, max)); - CHECK_ERROR (r == -1, "virNodeGetCellsFreeMemory"); + CHECK_ERROR_CLEANUP (r == -1, free (freemems), "virNodeGetCellsFreeMemory"); rv = caml_alloc (r, 0); for (i = 0; i < r; ++i) { iv = caml_copy_int64 ((int64_t) freemems[i]); Store_field (rv, i, iv); } + free (freemems); CAMLreturn (rv); } @@ -291,11 +426,15 @@ ocaml_libvirt_domain_get_scheduler_parameters (value domv, value nparamsv) CAMLlocal4 (rv, v, v2, v3); virDomainPtr dom = Domain_val (domv); int nparams = Int_val (nparamsv); - virSchedParameter params[nparams]; + virSchedParameterPtr params; int r, i; + params = malloc (sizeof (*params) * nparams); + if (params == NULL) + caml_raise_out_of_memory (); + NONBLOCKING (r = virDomainGetSchedulerParameters (dom, params, &nparams)); - CHECK_ERROR (r == -1, "virDomainGetSchedulerParameters"); + CHECK_ERROR_CLEANUP (r == -1, free (params), "virDomainGetSchedulerParameters"); rv = caml_alloc (nparams, 0); for (i = 0; i < nparams; ++i) { @@ -331,6 +470,7 @@ ocaml_libvirt_domain_get_scheduler_parameters (value domv, value nparamsv) } Store_field (v, 1, v2); } + free (params); CAMLreturn (rv); } @@ -341,10 +481,14 @@ ocaml_libvirt_domain_set_scheduler_parameters (value domv, value paramsv) CAMLlocal1 (v); virDomainPtr dom = Domain_val (domv); int nparams = Wosize_val (paramsv); - virSchedParameter params[nparams]; + virSchedParameterPtr params; int r, i; char *name; + params = malloc (sizeof (*params) * nparams); + if (params == NULL) + caml_raise_out_of_memory (); + for (i = 0; i < nparams; ++i) { v = Field (paramsv, i); /* Points to the two-element tuple. */ name = String_val (Field (v, 0)); @@ -382,6 +526,7 @@ ocaml_libvirt_domain_set_scheduler_parameters (value domv, value paramsv) } NONBLOCKING (r = virDomainSetSchedulerParameters (dom, params, nparams)); + free (params); CHECK_ERROR (r == -1, "virDomainSetSchedulerParameters"); CAMLreturn (Val_unit); @@ -424,15 +569,21 @@ ocaml_libvirt_domain_get_vcpus (value domv, value maxinfov, value maplenv) virDomainPtr dom = Domain_val (domv); int maxinfo = Int_val (maxinfov); int maplen = Int_val (maplenv); - virVcpuInfo info[maxinfo]; - unsigned char cpumaps[maxinfo * maplen]; + virVcpuInfoPtr info; + unsigned char *cpumaps; int r, i; - memset (info, 0, sizeof (virVcpuInfo) * maxinfo); - memset (cpumaps, 0, maxinfo * maplen); + info = calloc (maxinfo, sizeof (*info)); + if (info == NULL) + caml_raise_out_of_memory (); + cpumaps = calloc (maxinfo * maplen, sizeof (*cpumaps)); + if (cpumaps == NULL) { + free (info); + caml_raise_out_of_memory (); + } NONBLOCKING (r = virDomainGetVcpus (dom, info, maxinfo, cpumaps, maplen)); - CHECK_ERROR (r == -1, "virDomainPinVcpu"); + CHECK_ERROR_CLEANUP (r == -1, free (info); free (cpumaps), "virDomainPinVcpu"); /* Copy the virVcpuInfo structures. */ infov = caml_alloc (maxinfo, 0); @@ -454,6 +605,9 @@ ocaml_libvirt_domain_get_vcpus (value domv, value maxinfov, value maplenv) Store_field (rv, 1, infov); Store_field (rv, 2, strv); + free (info); + free (cpumaps); + CAMLreturn (rv); } @@ -847,6 +1001,37 @@ ocaml_libvirt_domain_memory_peek_bytecode (value *argv, int argn) argv[3], argv[4], argv[5]); } +CAMLprim value +ocaml_libvirt_domain_get_xml_desc_flags (value domv, value flagsv) +{ + CAMLparam2 (domv, flagsv); + CAMLlocal2 (rv, flagv); + virDomainPtr dom = Domain_val (domv); + int flags = 0; + char *r; + + /* Do flags. */ + for (; flagsv != Val_int (0); flagsv = Field (flagsv, 1)) + { + flagv = Field (flagsv, 0); + if (flagv == Val_int (0)) + flags |= VIR_DOMAIN_XML_SECURE; + else if (flagv == Val_int (1)) + flags |= VIR_DOMAIN_XML_INACTIVE; + else if (flagv == Val_int (2)) + flags |= VIR_DOMAIN_XML_UPDATE_CPU; + else if (flagv == Val_int (3)) + flags |= VIR_DOMAIN_XML_MIGRATABLE; + } + + NONBLOCKING (r = virDomainGetXMLDesc (dom, flags)); + CHECK_ERROR (!r, "virDomainGetXMLDesc"); + + rv = caml_copy_string (r); + free (r); + CAMLreturn (rv); +} + /*----------------------------------------------------------------------*/ /* Domain events */