Esempio n. 1
0
/* Guestfs.set_event_callback */
CAMLprim value
ocaml_guestfs_set_event_callback (value gv, value closure, value events)
{
  CAMLparam3 (gv, closure, events);
  char key[64];
  int eh;
  uint64_t event_bitmask;

  guestfs_h *g = Guestfs_val (gv);

  event_bitmask = event_bitmask_of_event_list (events);

  value *root = guestfs_safe_malloc (g, sizeof *root);
  *root = closure;

  eh = guestfs_set_event_callback (g, event_callback_wrapper,
                                   event_bitmask, 0, root);

  if (eh == -1) {
    free (root);
    ocaml_guestfs_raise_error (g, "set_event_callback");
  }

  /* XXX This global root is generational, but we cannot rely on every
   * user having the OCaml 3.11 version which supports this.
   */
  caml_register_global_root (root);

  snprintf (key, sizeof key, "_ocaml_event_%d", eh);
  guestfs_set_private (g, key, root);

  CAMLreturn (Val_int (eh));
}
Esempio n. 2
0
PyObject *
py_guestfs_delete_event_callback (PyObject *self, PyObject *args)
{
  PyObject *py_g;
  guestfs_h *g;
  int eh;
  PyObject *py_callback;
  char key[64];

  if (!PyArg_ParseTuple (args, (char *) "Oi:guestfs_delete_event_callback",
                         &py_g, &eh))
    return NULL;
  g = get_handle (py_g);

  snprintf (key, sizeof key, "_python_event_%d", eh);
  py_callback = guestfs_get_private (g, key);
  if (py_callback) {
    Py_XDECREF (py_callback);
    guestfs_set_private (g, key, NULL);
    guestfs_delete_event_callback (g, eh);
  }

  Py_INCREF (Py_None);
  return Py_None;
}
Esempio n. 3
0
/* Guestfs.create */
CAMLprim value
ocaml_guestfs_create (void)
{
  CAMLparam0 ();
  CAMLlocal1 (gv);
  guestfs_h *g;
  value *v;

  g = guestfs_create ();
  if (g == NULL)
    caml_failwith ("failed to create guestfs handle");

  guestfs_set_error_handler (g, NULL, NULL);

  gv = Val_guestfs (g);

  /* Store the OCaml handle into the C handle.  This is only so we can
   * map the C handle to the OCaml handle in event_callback_wrapper.
   */
  v = guestfs_safe_malloc (g, sizeof *v);
  *v = gv;
  /* XXX This global root is generational, but we cannot rely on every
   * user having the OCaml 3.11 version which supports this.
   */
  caml_register_global_root (v);
  guestfs_set_private (g, "_ocaml_g", v);

  CAMLreturn (gv);
}
Esempio n. 4
0
/* Guestfs.set_event_callback */
value
ocaml_guestfs_set_event_callback (value gv, value closure, value events)
{
  CAMLparam3 (gv, closure, events);
  char key[64];
  int eh;
  uint64_t event_bitmask;

  guestfs_h *g = Guestfs_val (gv);

  event_bitmask = event_bitmask_of_event_list (events);

  value *root = guestfs_int_safe_malloc (g, sizeof *root);
  *root = closure;

  eh = guestfs_set_event_callback (g, event_callback_wrapper,
                                   event_bitmask, 0, root);

  if (eh == -1) {
    free (root);
    ocaml_guestfs_raise_error (g, "set_event_callback");
  }

  caml_register_generational_global_root (root);

  snprintf (key, sizeof key, "_ocaml_event_%d", eh);
  guestfs_set_private (g, key, root);

  CAMLreturn (Val_int (eh));
}
Esempio n. 5
0
int
main (int argc, char *argv[])
{
  guestfs_h *g;
  const char *key;
  void *data;
  size_t count;

  g = guestfs_create ();
  if (g == NULL)
    error (EXIT_FAILURE, errno, "guestfs_create");

  if (guestfs_set_event_callback (g, close_callback, GUESTFS_EVENT_CLOSE,
                                  0, NULL) == -1)
    exit (EXIT_FAILURE);

  guestfs_set_private (g, PREFIX "a", (void *) 1);
  guestfs_set_private (g, PREFIX "b", (void *) 2);
  guestfs_set_private (g, PREFIX "c", (void *) 3);
  guestfs_set_private (g, PREFIX "a", (void *) 4); /* overwrites previous */

  /* Check we can fetch keys. */
  assert (guestfs_get_private (g, PREFIX "a") == (void *) 4);
  assert (guestfs_get_private (g, PREFIX "b") == (void *) 2);
  assert (guestfs_get_private (g, PREFIX "c") == (void *) 3);
  assert (guestfs_get_private (g, PREFIX "d") == NULL);

  /* Check we can count keys by iterating. */
  count = 0;
  data = guestfs_first_private (g, &key);
  while (data != NULL) {
    if (strncmp (key, PREFIX, strlen (PREFIX)) == 0)
      count++;
    data = guestfs_next_private (g, &key);
  }
  assert (count == 3);

  /* Delete some keys. */
  guestfs_set_private (g, PREFIX "a", NULL);
  guestfs_set_private (g, PREFIX "b", NULL);

  /* Count them again. */
  count = 0;
  data = guestfs_first_private (g, &key);
  while (data != NULL) {
    if (strncmp (key, PREFIX, strlen (PREFIX)) == 0)
      count++;
    data = guestfs_next_private (g, &key);
  }
  assert (count == 1);

  /* Closing should implicitly call the close_callback function. */
  guestfs_close (g);

  assert (close_callback_called == 1);

  exit (EXIT_SUCCESS);
}
Esempio n. 6
0
JNIEXPORT void JNICALL
Java_com_redhat_et_libguestfs_GuestFS__1delete_1event_1callback
  (JNIEnv *env, jobject obj, jlong jg, jint eh)
{
  guestfs_h *g = (guestfs_h *) (long) jg;
  char key[64];
  struct callback_data *data;

  snprintf (key, sizeof key, "_java_event_%d", eh);

  data = guestfs_get_private (g, key);
  if (data) {
    (*env)->DeleteGlobalRef (env, data->callback);
    free (data);
    guestfs_set_private (g, key, NULL);
    guestfs_delete_event_callback (g, eh);
  }
}
Esempio n. 7
0
PyObject *
py_guestfs_set_event_callback (PyObject *self, PyObject *args)
{
  PyObject *py_g;
  guestfs_h *g;
  PyObject *py_callback;
  unsigned PY_LONG_LONG events;
  int eh;
  PyObject *py_eh;
  char key[64];

  if (!PyArg_ParseTuple (args, (char *) "OOK:guestfs_set_event_callback",
                         &py_g, &py_callback, &events))
    return NULL;

  if (!PyCallable_Check (py_callback)) {
    PyErr_SetString (PyExc_TypeError,
                     "callback parameter is not callable "
                     "(eg. lambda or function)");
    return NULL;
  }

  g = get_handle (py_g);

  eh = guestfs_set_event_callback (g, py_guestfs_event_callback_wrapper,
                                   events, 0, py_callback);
  if (eh == -1) {
    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
    return NULL;
  }

  /* Increase the refcount for this callback since we are storing it
   * in the opaque C libguestfs handle.  We need to remember that we
   * did this, so we can decrease the refcount for all undeleted
   * callbacks left around at close time (see py_guestfs_close).
   */
  Py_XINCREF (py_callback);

  snprintf (key, sizeof key, "_python_event_%d", eh);
  guestfs_set_private (g, key, py_callback);

  py_eh = PyLong_FromLong ((long) eh);
  return py_eh;
}
Esempio n. 8
0
JNIEXPORT jint JNICALL
Java_com_redhat_et_libguestfs_GuestFS__1set_1event_1callback
  (JNIEnv *env, jobject obj, jlong jg, jobject jcallback, jlong jevents)
{
  guestfs_h *g = (guestfs_h *) (long) jg;
  int r;
  struct callback_data *data;
  jclass callback_class;
  jmethodID method;
  char key[64];

  callback_class = (*env)->GetObjectClass (env, jcallback);
  method = (*env)->GetMethodID (env, callback_class, METHOD_NAME, METHOD_SIGNATURE);
  if (method == 0) {
    throw_exception (env, "GuestFS.set_event_callback: callback class does not implement the EventCallback interface");
    return -1;
  }

  data = malloc (sizeof *data);
  if (data == NULL) {
    throw_out_of_memory (env, "malloc");
    return -1;
  }
  (*env)->GetJavaVM (env, &data->jvm);
  data->method = method;

  r = guestfs_set_event_callback (g, java_callback,
                                  (uint64_t) jevents, 0, data);
  if (r == -1) {
    free (data);
    throw_exception (env, guestfs_last_error (g));
    return -1;
  }

  /* Register jcallback as a global reference so the GC won't free it. */
  data->callback = (*env)->NewGlobalRef (env, jcallback);

  /* Store 'data' in the handle, so we can free it at some point. */
  snprintf (key, sizeof key, "_java_event_%d", r);
  guestfs_set_private (g, key, data);

  return (jint) r;
}
Esempio n. 9
0
/* Guestfs.delete_event_callback */
CAMLprim value
ocaml_guestfs_delete_event_callback (value gv, value ehv)
{
  CAMLparam2 (gv, ehv);
  char key[64];
  int eh = Int_val (ehv);

  guestfs_h *g = Guestfs_val (gv);

  snprintf (key, sizeof key, "_ocaml_event_%d", eh);

  value *root = guestfs_get_private (g, key);
  if (root) {
    caml_remove_global_root (root);
    free (root);
    guestfs_set_private (g, key, NULL);
    guestfs_delete_event_callback (g, eh);
  }

  CAMLreturn (Val_unit);
}
Esempio n. 10
0
/* Guestfs.create */
value
ocaml_guestfs_create (value environmentv, value close_on_exitv, value unitv)
{
  CAMLparam3 (environmentv, close_on_exitv, unitv);
  CAMLlocal1 (gv);
  unsigned flags = 0;
  guestfs_h *g;
  value *v;

  if (environmentv != Val_int (0) &&
      !Bool_val (Field (environmentv, 0)))
    flags |= GUESTFS_CREATE_NO_ENVIRONMENT;

  if (close_on_exitv != Val_int (0) &&
      !Bool_val (Field (close_on_exitv, 0)))
    flags |= GUESTFS_CREATE_NO_CLOSE_ON_EXIT;

  g = guestfs_create_flags (flags);
  if (g == NULL)
    caml_failwith ("failed to create guestfs handle");

  guestfs_set_error_handler (g, NULL, NULL);

  gv = Val_guestfs (g);

  /* Store the OCaml handle into the C handle.  This is only so we can
   * map the C handle to the OCaml handle in event_callback_wrapper.
   */
  v = guestfs_int_safe_malloc (g, sizeof *v);
  *v = gv;
  /* XXX This global root is generational, but we cannot rely on every
   * user having the OCaml 3.11 version which supports this.
   */
  caml_register_global_root (v);
  guestfs_set_private (g, "_ocaml_g", v);

  CAMLreturn (gv);
}
Esempio n. 11
0
/* This callback deletes all test keys in the handle. */
static void
close_callback (guestfs_h *g,
                void *opaque,
                uint64_t event,
                int event_handle,
                int flags,
                const char *buf, size_t buf_len,
                const uint64_t *array, size_t array_len)
{
  const char *key;
  void *data;

  close_callback_called++;

 again:
  data = guestfs_first_private (g, &key);
  while (data != NULL) {
    if (strncmp (key, PREFIX, strlen (PREFIX)) == 0) {
      guestfs_set_private (g, key, NULL);
      goto again;
    }
    data = guestfs_next_private (g, &key);
  }
}