Suppress errors to stderr and use thread-local virErrorPtr
[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  * with the OCaml linking exception described in ../COPYING.LIB.
10  *
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.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
19  */
20
21 /* Please read libvirt/README file. */
22
23 static char *
24 Optstring_val (value strv)
25 {
26   if (strv == Val_int (0))      /* None */
27     return NULL;
28   else                          /* Some string */
29     return String_val (Field (strv, 0));
30 }
31
32 static value
33 Val_opt (void *ptr, Val_ptr_t Val_ptr)
34 {
35   CAMLparam0 ();
36   CAMLlocal2 (optv, ptrv);
37
38   if (ptr) {                    /* Some ptr */
39     optv = caml_alloc (1, 0);
40     ptrv = Val_ptr (ptr);
41     Store_field (optv, 0, ptrv);
42   } else                        /* None */
43     optv = Val_int (0);
44
45   CAMLreturn (optv);
46 }
47
48 #if 0
49 static value
50 option_default (value option, value deflt)
51 {
52   if (option == Val_int (0))    /* "None" */
53     return deflt;
54   else                          /* "Some 'a" */
55     return Field (option, 0);
56 }
57 #endif
58
59 static void
60 _raise_virterror (const char *fn)
61 {
62   CAMLparam0 ();
63   CAMLlocal1 (rv);
64   virErrorPtr errp;
65   struct _virError err;
66
67   errp = virGetLastError ();
68
69   if (!errp) {
70     /* Fake a _virError structure. */
71     memset (&err, 0, sizeof err);
72     err.code = VIR_ERR_INTERNAL_ERROR;
73     err.domain = VIR_FROM_NONE;
74     err.level = VIR_ERR_ERROR;
75     err.message = (char *) fn;
76     errp = &err;
77   }
78
79   rv = Val_virterror (errp);
80   caml_raise_with_arg (*caml_named_value ("ocaml_libvirt_virterror"), rv);
81
82   /*NOTREACHED*/
83   /* Suppresses a compiler warning. */
84   (void) caml__frame;
85 }
86
87 /* Raise an error if a function is not supported. */
88 static void
89 not_supported (const char *fn)
90 {
91   CAMLparam0 ();
92   CAMLlocal1 (fnv);
93
94   fnv = caml_copy_string (fn);
95   caml_raise_with_arg (*caml_named_value ("ocaml_libvirt_not_supported"), fnv);
96
97   /*NOTREACHED*/
98   /* Suppresses a compiler warning. */
99   (void) caml__frame;
100 }
101
102 /* Convert the virErrorNumber, virErrorDomain and virErrorLevel enums
103  * into values (longs because they are variants in OCaml).
104  *
105  * The enum values are part of the libvirt ABI so they cannot change,
106  * which means that we can convert these numbers directly into
107  * OCaml variants (which use the same ordering) very fast.
108  *
109  * The tricky part here is when we are linked to a newer version of
110  * libvirt than the one we were compiled against.  If the newer libvirt
111  * generates an error code which we don't know about then we need
112  * to convert it into VIR_*_UNKNOWN (code).
113  */
114
115 #define MAX_VIR_CODE 50 /* VIR_ERR_NO_STORAGE_VOL */
116 #define MAX_VIR_DOMAIN 17 /* VIR_FROM_STORAGE */
117 #define MAX_VIR_LEVEL VIR_ERR_ERROR
118
119 static inline value
120 Val_err_number (virErrorNumber code)
121 {
122   CAMLparam0 ();
123   CAMLlocal1 (rv);
124
125   if (0 <= code && code <= MAX_VIR_CODE)
126     rv = Val_int (code);
127   else {
128     rv = caml_alloc (1, 0);     /* VIR_ERR_UNKNOWN (code) */
129     Store_field (rv, 0, Val_int (code));
130   }
131
132   CAMLreturn (rv);
133 }
134
135 static inline value
136 Val_err_domain (virErrorDomain code)
137 {
138   CAMLparam0 ();
139   CAMLlocal1 (rv);
140
141   if (0 <= code && code <= MAX_VIR_DOMAIN)
142     rv = Val_int (code);
143   else {
144     rv = caml_alloc (1, 0);     /* VIR_FROM_UNKNOWN (code) */
145     Store_field (rv, 0, Val_int (code));
146   }
147
148   CAMLreturn (rv);
149 }
150
151 static inline value
152 Val_err_level (virErrorLevel code)
153 {
154   CAMLparam0 ();
155   CAMLlocal1 (rv);
156
157   if (0 <= code && code <= MAX_VIR_LEVEL)
158     rv = Val_int (code);
159   else {
160     rv = caml_alloc (1, 0);     /* VIR_ERR_UNKNOWN_LEVEL (code) */
161     Store_field (rv, 0, Val_int (code));
162   }
163
164   CAMLreturn (rv);
165 }
166
167 /* Convert a virterror to a value. */
168 static value
169 Val_virterror (virErrorPtr err)
170 {
171   CAMLparam0 ();
172   CAMLlocal3 (rv, connv, optv);
173
174   rv = caml_alloc (9, 0);
175   Store_field (rv, 0, Val_err_number (err->code));
176   Store_field (rv, 1, Val_err_domain (err->domain));
177   Store_field (rv, 2,
178                Val_opt (err->message, (Val_ptr_t) caml_copy_string));
179   Store_field (rv, 3, Val_err_level (err->level));
180
181   Store_field (rv, 4,
182                Val_opt (err->str1, (Val_ptr_t) caml_copy_string));
183   Store_field (rv, 5,
184                Val_opt (err->str2, (Val_ptr_t) caml_copy_string));
185   Store_field (rv, 6,
186                Val_opt (err->str3, (Val_ptr_t) caml_copy_string));
187   Store_field (rv, 7, caml_copy_int32 (err->int1));
188   Store_field (rv, 8, caml_copy_int32 (err->int2));
189
190   CAMLreturn (rv);
191 }
192
193 static void conn_finalize (value);
194 static void dom_finalize (value);
195 static void net_finalize (value);
196 static void pol_finalize (value);
197 static void vol_finalize (value);
198
199 static struct custom_operations conn_custom_operations = {
200   "conn_custom_operations",
201   conn_finalize,
202   custom_compare_default,
203   custom_hash_default,
204   custom_serialize_default,
205   custom_deserialize_default
206 };
207
208 static struct custom_operations dom_custom_operations = {
209   "dom_custom_operations",
210   dom_finalize,
211   custom_compare_default,
212   custom_hash_default,
213   custom_serialize_default,
214   custom_deserialize_default
215
216 };
217
218 static struct custom_operations net_custom_operations = {
219   "net_custom_operations",
220   net_finalize,
221   custom_compare_default,
222   custom_hash_default,
223   custom_serialize_default,
224   custom_deserialize_default
225 };
226
227 static struct custom_operations pol_custom_operations = {
228   "pol_custom_operations",
229   pol_finalize,
230   custom_compare_default,
231   custom_hash_default,
232   custom_serialize_default,
233   custom_deserialize_default
234 };
235
236 static struct custom_operations vol_custom_operations = {
237   "vol_custom_operations",
238   vol_finalize,
239   custom_compare_default,
240   custom_hash_default,
241   custom_serialize_default,
242   custom_deserialize_default
243 };
244
245 static value
246 Val_connect (virConnectPtr conn)
247 {
248   CAMLparam0 ();
249   CAMLlocal1 (rv);
250   rv = caml_alloc_custom (&conn_custom_operations,
251                           sizeof (virConnectPtr), 0, 1);
252   Connect_val (rv) = conn;
253   CAMLreturn (rv);
254 }
255
256 static value
257 Val_dom (virDomainPtr dom)
258 {
259   CAMLparam0 ();
260   CAMLlocal1 (rv);
261   rv = caml_alloc_custom (&dom_custom_operations,
262                           sizeof (virDomainPtr), 0, 1);
263   Dom_val (rv) = dom;
264   CAMLreturn (rv);
265 }
266
267 static value
268 Val_net (virNetworkPtr net)
269 {
270   CAMLparam0 ();
271   CAMLlocal1 (rv);
272   rv = caml_alloc_custom (&net_custom_operations,
273                           sizeof (virNetworkPtr), 0, 1);
274   Net_val (rv) = net;
275   CAMLreturn (rv);
276 }
277
278 static value
279 Val_pol (virStoragePoolPtr pol)
280 {
281   CAMLparam0 ();
282   CAMLlocal1 (rv);
283   rv = caml_alloc_custom (&pol_custom_operations,
284                           sizeof (virStoragePoolPtr), 0, 1);
285   Pol_val (rv) = pol;
286   CAMLreturn (rv);
287 }
288
289 static value
290 Val_vol (virStorageVolPtr vol)
291 {
292   CAMLparam0 ();
293   CAMLlocal1 (rv);
294   rv = caml_alloc_custom (&vol_custom_operations,
295                           sizeof (virStorageVolPtr), 0, 1);
296   Vol_val (rv) = vol;
297   CAMLreturn (rv);
298 }
299
300 /* This wraps up the (dom, conn) pair (Domain.t). */
301 static value
302 Val_domain (virDomainPtr dom, value connv)
303 {
304   CAMLparam1 (connv);
305   CAMLlocal2 (rv, v);
306
307   rv = caml_alloc_tuple (2);
308   v = Val_dom (dom);
309   Store_field (rv, 0, v);
310   Store_field (rv, 1, connv);
311   CAMLreturn (rv);
312 }
313
314 /* This wraps up the (net, conn) pair (Network.t). */
315 static value
316 Val_network (virNetworkPtr net, value connv)
317 {
318   CAMLparam1 (connv);
319   CAMLlocal2 (rv, v);
320
321   rv = caml_alloc_tuple (2);
322   v = Val_net (net);
323   Store_field (rv, 0, v);
324   Store_field (rv, 1, connv);
325   CAMLreturn (rv);
326 }
327
328 /* This wraps up the (pol, conn) pair (Pool.t). */
329 static value
330 Val_pool (virStoragePoolPtr pol, value connv)
331 {
332   CAMLparam1 (connv);
333   CAMLlocal2 (rv, v);
334
335   rv = caml_alloc_tuple (2);
336   v = Val_pol (pol);
337   Store_field (rv, 0, v);
338   Store_field (rv, 1, connv);
339   CAMLreturn (rv);
340 }
341
342 /* This wraps up the (vol, conn) pair (Volume.t). */
343 static value
344 Val_volume (virStorageVolPtr vol, value connv)
345 {
346   CAMLparam1 (connv);
347   CAMLlocal2 (rv, v);
348
349   rv = caml_alloc_tuple (2);
350   v = Val_vol (vol);
351   Store_field (rv, 0, v);
352   Store_field (rv, 1, connv);
353   CAMLreturn (rv);
354 }
355
356 static void
357 conn_finalize (value connv)
358 {
359   virConnectPtr conn = Connect_val (connv);
360   if (conn) (void) virConnectClose (conn);
361 }
362
363 static void
364 dom_finalize (value domv)
365 {
366   virDomainPtr dom = Dom_val (domv);
367   if (dom) (void) virDomainFree (dom);
368 }
369
370 static void
371 net_finalize (value netv)
372 {
373   virNetworkPtr net = Net_val (netv);
374   if (net) (void) virNetworkFree (net);
375 }
376
377 static void
378 pol_finalize (value polv)
379 {
380   virStoragePoolPtr pol = Pol_val (polv);
381   if (pol) (void) virStoragePoolFree (pol);
382 }
383
384 static void
385 vol_finalize (value volv)
386 {
387   virStorageVolPtr vol = Vol_val (volv);
388   if (vol) (void) virStorageVolFree (vol);
389 }