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);
}
Example #2
0
/* Allocate handles and deal with finalization. */
static void
guestfs_finalize (value gv)
{
  guestfs_h *g = Guestfs_val (gv);

  if (g) {
    /* There is a nasty, difficult to solve case here where the
     * user deletes events in one of the callbacks that we are
     * about to invoke, resulting in a double-free.  XXX
     */
    size_t len, i;
    value **roots = get_all_event_callbacks (g, &len);

    value *v = guestfs_get_private (g, "_ocaml_g");

    /* Close the handle: this could invoke callbacks from the list
     * above, which is why we don't want to delete them before
     * closing the handle.
     */
    guestfs_close (g);

    /* Now unregister the global roots. */
    for (i = 0; i < len; ++i) {
      caml_remove_global_root (roots[i]);
      free (roots[i]);
    }
    free (roots);

    caml_remove_global_root (v);
    free (v);
  }
}
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;
}
Example #4
0
static void
event_callback_wrapper_locked (guestfs_h *g,
                               void *data,
                               uint64_t event,
                               int event_handle,
                               int flags,
                               const char *buf, size_t buf_len,
                               const uint64_t *array, size_t array_len)
{
  CAMLparam0 ();
  CAMLlocal5 (gv, evv, ehv, bufv, arrayv);
  CAMLlocal2 (rv, v);
  value *root;
  size_t i;

  root = guestfs_get_private (g, "_ocaml_g");
  gv = *root;

  /* Only one bit should be set in 'event'.  Which one? */
  evv = Val_int (event_bitmask_to_event (event));

  ehv = Val_int (event_handle);

  bufv = caml_alloc_string (buf_len);
  memcpy (String_val (bufv), buf, buf_len);

  arrayv = caml_alloc (array_len, 0);
  for (i = 0; i < array_len; ++i) {
    v = caml_copy_int64 (array[i]);
    Store_field (arrayv, i, v);
  }

  value args[5] = { gv, evv, ehv, bufv, arrayv };

  rv = caml_callbackN_exn (*(value*)data, 5, args);

  /* Callbacks shouldn't throw exceptions.  There's not much we can do
   * except to print it.
   */
  if (Is_exception_result (rv))
    fprintf (stderr,
             "libguestfs: uncaught OCaml exception in event callback: %s",
             caml_format_exception (Extract_exception (rv)));

  CAMLreturn0;
}
Example #5
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);
  }
}
Example #6
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);
}