a279b7e3a87b85d0241e6af4b557c6a7e080e08c
[ocaml-libvirt.git] / libvirt / libvirt_c_epilogue.c
1 /* OCaml bindings for libvirt.
2  * (C) Copyright 2007 Richard W.M. Jones, Red Hat Inc.
3  * http://libvirt.org/
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * Please see the file ../COPYING.LIB.
16  */
17
18 /* Please read libvirt/README file. */
19
20 static char *
21 Optstring_val (value strv)
22 {
23   if (strv == Val_int (0))      /* None */
24     return NULL;
25   else                          /* Some string */
26     return String_val (Field (strv, 0));
27 }
28
29 static value
30 Val_opt (void *ptr, Val_ptr_t Val_ptr)
31 {
32   CAMLparam0 ();
33   CAMLlocal2 (optv, ptrv);
34
35   if (ptr) {                    /* Some ptr */
36     optv = caml_alloc (1, 0);
37     ptrv = Val_ptr (ptr);
38     Store_field (optv, 0, ptrv);
39   } else                        /* None */
40     optv = Val_int (0);
41
42   CAMLreturn (optv);
43 }
44
45 #if 0
46 static value
47 option_default (value option, value deflt)
48 {
49   if (option == Val_int (0))    /* "None" */
50     return deflt;
51   else                          /* "Some 'a" */
52     return Field (option, 0);
53 }
54 #endif
55
56 static void
57 _raise_virterror (virConnectPtr conn, const char *fn)
58 {
59   CAMLparam0 ();
60   CAMLlocal1 (rv);
61   virErrorPtr errp;
62   struct _virError err;
63
64   errp = conn ? virConnGetLastError (conn) : virGetLastError ();
65
66   if (!errp) {
67     /* Fake a _virError structure. */
68     memset (&err, 0, sizeof err);
69     err.code = VIR_ERR_INTERNAL_ERROR;
70     err.domain = VIR_FROM_NONE;
71     err.level = VIR_ERR_ERROR;
72     err.message = (char *) fn;
73     errp = &err;
74   }
75
76   rv = Val_virterror (errp);
77   caml_raise_with_arg (*caml_named_value ("ocaml_libvirt_virterror"), rv);
78
79   /*NOTREACHED*/
80   /* Suppresses a compiler warning. */
81   (void) caml__frame;
82 }
83
84 /* Raise an error if a function is not supported. */
85 static void
86 not_supported (const char *fn)
87 {
88   CAMLparam0 ();
89   CAMLlocal1 (fnv);
90
91   fnv = caml_copy_string (fn);
92   caml_raise_with_arg (*caml_named_value ("ocaml_libvirt_not_supported"), fnv);
93
94   /*NOTREACHED*/
95   /* Suppresses a compiler warning. */
96   (void) caml__frame;
97 }
98
99 /* Convert the virErrorNumber, virErrorDomain and virErrorLevel enums
100  * into values (longs because they are variants in OCaml).
101  *
102  * The enum values are part of the libvirt ABI so they cannot change,
103  * which means that we can convert these numbers directly into
104  * OCaml variants (which use the same ordering) very fast.
105  *
106  * The tricky part here is when we are linked to a newer version of
107  * libvirt than the one we were compiled against.  If the newer libvirt
108  * generates an error code which we don't know about then we need
109  * to convert it into VIR_*_UNKNOWN (code).
110  */
111
112 #define MAX_VIR_CODE 50 /* VIR_ERR_NO_STORAGE_VOL */
113 #define MAX_VIR_DOMAIN 17 /* VIR_FROM_STORAGE */
114 #define MAX_VIR_LEVEL VIR_ERR_ERROR
115
116 static inline value
117 Val_err_number (virErrorNumber code)
118 {
119   CAMLparam0 ();
120   CAMLlocal1 (rv);
121
122   if (0 <= code && code <= MAX_VIR_CODE)
123     rv = Val_int (code);
124   else {
125     rv = caml_alloc (1, 0);     /* VIR_ERR_UNKNOWN (code) */
126     Store_field (rv, 0, Val_int (code));
127   }
128
129   CAMLreturn (rv);
130 }
131
132 static inline value
133 Val_err_domain (virErrorDomain code)
134 {
135   CAMLparam0 ();
136   CAMLlocal1 (rv);
137
138   if (0 <= code && code <= MAX_VIR_DOMAIN)
139     rv = Val_int (code);
140   else {
141     rv = caml_alloc (1, 0);     /* VIR_FROM_UNKNOWN (code) */
142     Store_field (rv, 0, Val_int (code));
143   }
144
145   CAMLreturn (rv);
146 }
147
148 static inline value
149 Val_err_level (virErrorLevel code)
150 {
151   CAMLparam0 ();
152   CAMLlocal1 (rv);
153
154   if (0 <= code && code <= MAX_VIR_LEVEL)
155     rv = Val_int (code);
156   else {
157     rv = caml_alloc (1, 0);     /* VIR_ERR_UNKNOWN_LEVEL (code) */
158     Store_field (rv, 0, Val_int (code));
159   }
160
161   CAMLreturn (rv);
162 }
163
164 /* Convert a virterror to a value. */
165 static value
166 Val_virterror (virErrorPtr err)
167 {
168   CAMLparam0 ();
169   CAMLlocal3 (rv, connv, optv);
170
171   rv = caml_alloc (9, 0);
172   Store_field (rv, 0, Val_err_number (err->code));
173   Store_field (rv, 1, Val_err_domain (err->domain));
174   Store_field (rv, 2,
175                Val_opt (err->message, (Val_ptr_t) caml_copy_string));
176   Store_field (rv, 3, Val_err_level (err->level));
177
178   Store_field (rv, 4,
179                Val_opt (err->str1, (Val_ptr_t) caml_copy_string));
180   Store_field (rv, 5,
181                Val_opt (err->str2, (Val_ptr_t) caml_copy_string));
182   Store_field (rv, 6,
183                Val_opt (err->str3, (Val_ptr_t) caml_copy_string));
184   Store_field (rv, 7, caml_copy_int32 (err->int1));
185   Store_field (rv, 8, caml_copy_int32 (err->int2));
186
187   CAMLreturn (rv);
188 }
189
190 static void conn_finalize (value);
191 static void dom_finalize (value);
192 static void net_finalize (value);
193 #ifdef HAVE_VIRSTORAGEPOOLPTR
194 static void pol_finalize (value);
195 #endif
196 #ifdef HAVE_VIRSTORAGEVOLPTR
197 static void vol_finalize (value);
198 #endif
199 #ifdef HAVE_VIRJOBPTR
200 static void jb_finalize (value);
201 #endif
202
203 static struct custom_operations conn_custom_operations = {
204   "conn_custom_operations",
205   conn_finalize,
206   custom_compare_default,
207   custom_hash_default,
208   custom_serialize_default,
209   custom_deserialize_default
210 };
211
212 static struct custom_operations dom_custom_operations = {
213   "dom_custom_operations",
214   dom_finalize,
215   custom_compare_default,
216   custom_hash_default,
217   custom_serialize_default,
218   custom_deserialize_default
219
220 };
221
222 static struct custom_operations net_custom_operations = {
223   "net_custom_operations",
224   net_finalize,
225   custom_compare_default,
226   custom_hash_default,
227   custom_serialize_default,
228   custom_deserialize_default
229 };
230
231 #ifdef HAVE_VIRSTORAGEPOOLPTR
232 static struct custom_operations pol_custom_operations = {
233   "pol_custom_operations",
234   pol_finalize,
235   custom_compare_default,
236   custom_hash_default,
237   custom_serialize_default,
238   custom_deserialize_default
239 };
240 #endif
241
242 #ifdef HAVE_VIRSTORAGEVOLPTR
243 static struct custom_operations vol_custom_operations = {
244   "vol_custom_operations",
245   vol_finalize,
246   custom_compare_default,
247   custom_hash_default,
248   custom_serialize_default,
249   custom_deserialize_default
250 };
251 #endif
252
253 #ifdef HAVE_VIRJOBPTR
254 static struct custom_operations jb_custom_operations = {
255   "jb_custom_operations",
256   jb_finalize,
257   custom_compare_default,
258   custom_hash_default,
259   custom_serialize_default,
260   custom_deserialize_default
261 };
262 #endif
263
264 static value
265 Val_connect (virConnectPtr conn)
266 {
267   CAMLparam0 ();
268   CAMLlocal1 (rv);
269   rv = caml_alloc_custom (&conn_custom_operations,
270                           sizeof (virConnectPtr), 0, 1);
271   Connect_val (rv) = conn;
272   CAMLreturn (rv);
273 }
274
275 static value
276 Val_dom (virDomainPtr dom)
277 {
278   CAMLparam0 ();
279   CAMLlocal1 (rv);
280   rv = caml_alloc_custom (&dom_custom_operations,
281                           sizeof (virDomainPtr), 0, 1);
282   Dom_val (rv) = dom;
283   CAMLreturn (rv);
284 }
285
286 static value
287 Val_net (virNetworkPtr net)
288 {
289   CAMLparam0 ();
290   CAMLlocal1 (rv);
291   rv = caml_alloc_custom (&net_custom_operations,
292                           sizeof (virNetworkPtr), 0, 1);
293   Net_val (rv) = net;
294   CAMLreturn (rv);
295 }
296
297 #ifdef HAVE_VIRSTORAGEPOOLPTR
298 static value
299 Val_pol (virStoragePoolPtr pol)
300 {
301   CAMLparam0 ();
302   CAMLlocal1 (rv);
303   rv = caml_alloc_custom (&pol_custom_operations,
304                           sizeof (virStoragePoolPtr), 0, 1);
305   Pol_val (rv) = pol;
306   CAMLreturn (rv);
307 }
308 #endif
309
310 #ifdef HAVE_VIRSTORAGEVOLPTR
311 static value
312 Val_vol (virStorageVolPtr vol)
313 {
314   CAMLparam0 ();
315   CAMLlocal1 (rv);
316   rv = caml_alloc_custom (&vol_custom_operations,
317                           sizeof (virStorageVolPtr), 0, 1);
318   Vol_val (rv) = vol;
319   CAMLreturn (rv);
320 }
321 #endif
322
323 #ifdef HAVE_VIRJOBPTR
324 static value
325 Val_jb (virJobPtr jb)
326 {
327   CAMLparam0 ();
328   CAMLlocal1 (rv);
329   rv = caml_alloc_custom (&jb_custom_operations,
330                           sizeof (virJobPtr), 0, 1);
331   Jb_val (rv) = jb;
332   CAMLreturn (rv);
333 }
334 #endif
335
336 /* This wraps up the (dom, conn) pair (Domain.t). */
337 static value
338 Val_domain (virDomainPtr dom, value connv)
339 {
340   CAMLparam1 (connv);
341   CAMLlocal2 (rv, v);
342
343   rv = caml_alloc_tuple (2);
344   v = Val_dom (dom);
345   Store_field (rv, 0, v);
346   Store_field (rv, 1, connv);
347   CAMLreturn (rv);
348 }
349
350 /* This wraps up the (net, conn) pair (Network.t). */
351 static value
352 Val_network (virNetworkPtr net, value connv)
353 {
354   CAMLparam1 (connv);
355   CAMLlocal2 (rv, v);
356
357   rv = caml_alloc_tuple (2);
358   v = Val_net (net);
359   Store_field (rv, 0, v);
360   Store_field (rv, 1, connv);
361   CAMLreturn (rv);
362 }
363
364 #ifdef HAVE_VIRSTORAGEPOOLPTR
365 /* This wraps up the (pol, conn) pair (Pool.t). */
366 static value
367 Val_pool (virStoragePoolPtr pol, value connv)
368 {
369   CAMLparam1 (connv);
370   CAMLlocal2 (rv, v);
371
372   rv = caml_alloc_tuple (2);
373   v = Val_pol (pol);
374   Store_field (rv, 0, v);
375   Store_field (rv, 1, connv);
376   CAMLreturn (rv);
377 }
378 #endif
379
380 #ifdef HAVE_VIRSTORAGEVOLPTR
381 /* This wraps up the (vol, conn) pair (Volume.t). */
382 static value
383 Val_volume (virStorageVolPtr vol, value connv)
384 {
385   CAMLparam1 (connv);
386   CAMLlocal2 (rv, v);
387
388   rv = caml_alloc_tuple (2);
389   v = Val_vol (vol);
390   Store_field (rv, 0, v);
391   Store_field (rv, 1, connv);
392   CAMLreturn (rv);
393 }
394 #endif
395
396 #ifdef HAVE_VIRJOBPTR
397 /* This wraps up the (jb, conn) pair (Job.t). */
398 static value
399 Val_job (virJobPtr jb, value connv)
400 {
401   CAMLparam1 (connv);
402   CAMLlocal2 (rv, v);
403
404   rv = caml_alloc_tuple (2);
405   v = Val_jb (jb);
406   Store_field (rv, 0, v);
407   Store_field (rv, 1, connv);
408   CAMLreturn (rv);
409 }
410 #endif
411
412 static void
413 conn_finalize (value connv)
414 {
415   virConnectPtr conn = Connect_val (connv);
416   if (conn) (void) virConnectClose (conn);
417 }
418
419 static void
420 dom_finalize (value domv)
421 {
422   virDomainPtr dom = Dom_val (domv);
423   if (dom) (void) virDomainFree (dom);
424 }
425
426 static void
427 net_finalize (value netv)
428 {
429   virNetworkPtr net = Net_val (netv);
430   if (net) (void) virNetworkFree (net);
431 }
432
433 #ifdef HAVE_VIRSTORAGEPOOLPTR
434 static void
435 pol_finalize (value polv)
436 {
437   virStoragePoolPtr pol = Pol_val (polv);
438   if (pol) (void) virStoragePoolFree (pol);
439 }
440 #endif
441
442 #ifdef HAVE_VIRSTORAGEVOLPTR
443 static void
444 vol_finalize (value volv)
445 {
446   virStorageVolPtr vol = Vol_val (volv);
447   if (vol) (void) virStorageVolFree (vol);
448 }
449 #endif
450
451 #ifdef HAVE_VIRJOBPTR
452 static void
453 jb_finalize (value jbv)
454 {
455   virJobPtr jb = Jb_val (jbv);
456   if (jb) (void) virJobFree (jb);
457 }
458 #endif