X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=blobdiff_plain;f=ocaml%2Fguestfs_c.c;h=80dcf9954f1a0fc28516b728e33645ba2c921400;hp=dda338fade56b284f2bbe916b098a0d7230e94f5;hb=d37f69795396ec2354eb2d8480d64b9e5bdafacc;hpb=4144e2106cc70ad8f1e081b57da09f9c1e276812 diff --git a/ocaml/guestfs_c.c b/ocaml/guestfs_c.c index dda338f..80dcf99 100644 --- a/ocaml/guestfs_c.c +++ b/ocaml/guestfs_c.c @@ -16,26 +16,141 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include #include +#include #include #include #include #include +#include #include #include #include #include "guestfs_c.h" +/* This macro was added in OCaml 3.10. Backport for earlier versions. */ +#ifndef CAMLreturnT +#define CAMLreturnT(type, result) do{ \ + type caml__temp_result = (result); \ + caml_local_roots = caml__frame; \ + return (caml__temp_result); \ +}while(0) +#endif + +/* These prototypes are solely to quiet gcc warning. */ +CAMLprim value ocaml_guestfs_create (void); +CAMLprim value ocaml_guestfs_close (value gv); + +/* Allocate handles and deal with finalization. */ +static void +guestfs_finalize (value gv) +{ + guestfs_h *g = Guestfs_val (gv); + if (g) guestfs_close (g); +} + +static struct custom_operations guestfs_custom_operations = { + (char *) "guestfs_custom_operations", + guestfs_finalize, + custom_compare_default, + custom_hash_default, + custom_serialize_default, + custom_deserialize_default +}; + +static value +Val_guestfs (guestfs_h *g) +{ + CAMLparam0 (); + CAMLlocal1 (rv); + + rv = caml_alloc_custom (&guestfs_custom_operations, + sizeof (guestfs_h *), 0, 1); + Guestfs_val (rv) = g; + + CAMLreturn (rv); +} + +void +ocaml_guestfs_raise_error (guestfs_h *g, const char *func) +{ + CAMLparam0 (); + CAMLlocal1 (v); + const char *msg; + + msg = guestfs_last_error (g); + + if (msg) + v = caml_copy_string (msg); + else + v = caml_copy_string (func); + caml_raise_with_arg (*caml_named_value ("ocaml_guestfs_error"), v); + CAMLnoreturn; +} + +/* Guestfs.create */ +CAMLprim value +ocaml_guestfs_create (void) +{ + CAMLparam0 (); + CAMLlocal1 (gv); + guestfs_h *g; + + g = guestfs_create (); + if (g == NULL) + caml_failwith ("failed to create guestfs handle"); + + guestfs_set_error_handler (g, NULL, NULL); + + gv = Val_guestfs (g); + CAMLreturn (gv); +} + +/* Guestfs.close */ CAMLprim value -ocaml_guestfs_create (value hv /* XXX */) +ocaml_guestfs_close (value gv) { - CAMLparam1 (hv); /* XXX */ -/* XXX write something here */ - CAMLreturn (Val_unit); /* XXX */ + CAMLparam1 (gv); + + guestfs_finalize (gv); + + /* So we don't double-free in the finalizer. */ + Guestfs_val (gv) = NULL; + + CAMLreturn (Val_unit); } -/* etc */ +/* Copy string array value. + * The return value is only 'safe' provided we don't allocate anything + * further on the OCaml heap (ie. cannot trigger the OCaml GC) because + * that could move the strings around. + */ +char ** +ocaml_guestfs_strings_val (guestfs_h *g, value sv) +{ + CAMLparam1 (sv); + char **r; + unsigned int i; + + r = guestfs_safe_malloc (g, sizeof (char *) * (Wosize_val (sv) + 1)); + for (i = 0; i < Wosize_val (sv); ++i) + r[i] = String_val (Field (sv, i)); + r[i] = NULL; + + CAMLreturnT (char **, r); +} + +/* Free array of strings. */ +void +ocaml_guestfs_free_strings (char **argv) +{ + /* Don't free the actual strings - they are String_vals on + * the OCaml heap. + */ + free (argv); +}