Exemplo n.º 1
0
/* Call trace messages.  These are enabled by setting g->trace, and
 * calls to this function should only happen from the generated code
 * in src/actions.c
 */
void
guestfs___trace (guestfs_h *g, const char *fs, ...)
{
  va_list args;
  CLEANUP_FREE char *msg = NULL;
  int len;

  va_start (args, fs);
  len = vasprintf (&msg, fs, args);
  va_end (args);

  if (len < 0) return;

  guestfs___call_callbacks_message (g, GUESTFS_EVENT_TRACE, msg, len);
}
Exemplo n.º 2
0
/* Warning are printed unconditionally.  We try to make these rare.
 * Generally speaking, a warning should either be an error, or if it's
 * not important for end users then it should be a debug message.
 */
void
guestfs___warning (guestfs_h *g, const char *fs, ...)
{
  va_list args;
  char *msg, *msg2;
  int len;

  va_start (args, fs);
  len = vasprintf (&msg, fs, args);
  va_end (args);

  if (len < 0) return;

  len = asprintf (&msg2, _("warning: %s"), msg);
  free (msg);

  if (len < 0) return;

  guestfs___call_callbacks_message (g, GUESTFS_EVENT_LIBRARY, msg2, len);

  free (msg2);
}
Exemplo n.º 3
0
/* Debug messages. */
void
guestfs___debug (guestfs_h *g, const char *fs, ...)
{
  va_list args;
  CLEANUP_FREE char *msg = NULL;
  int len;

  /* The cpp macro "debug" has already checked that g->verbose is true
   * before calling this function, but we check it again just in case
   * anyone calls this function directly.
   */
  if (!g->verbose)
    return;

  va_start (args, fs);
  len = vasprintf (&msg, fs, args);
  va_end (args);

  if (len < 0) return;

  guestfs___call_callbacks_message (g, GUESTFS_EVENT_LIBRARY, msg, len);
}
Exemplo n.º 4
0
void
guestfs_close (guestfs_h *g)
{
  if (g->state == NO_HANDLE) {
    /* Not safe to call ANY callbacks here, so ... */
    fprintf (stderr, _("guestfs_close: called twice on the same handle\n"));
    return;
  }

  if (g->trace) {
    const char trace_msg[] = "close";

    guestfs___call_callbacks_message (g, GUESTFS_EVENT_TRACE,
                                      trace_msg, strlen (trace_msg));
  }

  debug (g, "closing guestfs handle %p (state %d)", g, g->state);

  /* Try to sync if autosync flag is set. */
  if (g->autosync && g->state == READY)
    guestfs_internal_autosync (g);

  /* If we are valgrinding the daemon, then we *don't* want to kill
   * the subprocess because we want the final valgrind messages sent
   * when we close sockets below.  However for normal production use,
   * killing the subprocess is the right thing to do (in case the
   * daemon or qemu is not responding).
   */
#ifndef VALGRIND_DAEMON
  /* Kill the qemu subprocess. */
  if (g->state != CONFIG)
    guestfs_kill_subprocess (g);
#endif

  /* Run user close callbacks. */
  guestfs___call_callbacks_void (g, GUESTFS_EVENT_CLOSE);

  /* Remove all other registered callbacks.  Since we've already
   * called the close callbacks, we shouldn't call any others.
   */
  free (g->events);
  g->nr_events = 0;
  g->events = NULL;

  guestfs___free_inspect_info (g);
  guestfs___free_drives (&g->drives);

  /* Close sockets. */
  if (g->fd[0] >= 0)
    close (g->fd[0]);
  if (g->fd[1] >= 0)
    close (g->fd[1]);
  if (g->sock >= 0)
    close (g->sock);
  g->fd[0] = -1;
  g->fd[1] = -1;
  g->sock = -1;

  /* Wait for subprocess(es) to exit. */
  if (g->pid > 0) waitpid (g->pid, NULL, 0);
  if (g->recoverypid > 0) waitpid (g->recoverypid, NULL, 0);

  /* Remove whole temporary directory. */
  guestfs___remove_tmpdir (g->tmpdir);
  free (g->tmpdir);

  if (g->cmdline) {
    size_t i;

    for (i = 0; i < g->cmdline_size; ++i)
      free (g->cmdline[i]);
    free (g->cmdline);
  }

  /* Mark the handle as dead before freeing it. */
  g->state = NO_HANDLE;

  gl_lock_lock (handles_lock);
  if (handles == g)
    handles = g->next;
  else {
    guestfs_h *gg;

    for (gg = handles; gg->next != g; gg = gg->next)
      ;
    gg->next = g->next;
  }
  gl_lock_unlock (handles_lock);

  if (g->pda)
    hash_free (g->pda);
  free (g->last_error);
  free (g->path);
  free (g->qemu);
  free (g->append);
  free (g->qemu_help);
  free (g->qemu_version);
  free (g);
}
Exemplo n.º 5
0
static int
read_log_message_or_eof (guestfs_h *g, int fd, int error_if_eof)
{
  char buf[BUFSIZ];
  ssize_t n;

#if 0
  debug (g, "read_log_message_or_eof: %p g->state = %d, fd = %d",
         g, g->state, fd);
#endif

  /* QEMU's console emulates a 16550A serial port.  The real 16550A
   * device has a small FIFO buffer (16 bytes) which means here we see
   * lots of small reads of 1-16 bytes in length, usually single
   * bytes.  Sleeping here for a very brief period groups reads
   * together (so we usually get a few lines of output at once) and
   * improves overall throughput, as well as making the event
   * interface a bit more sane for callers.  With a virtio-serial
   * based console (not yet implemented) we may be able to remove
   * this.  XXX
   */
  usleep (1000);

  n = read (fd, buf, sizeof buf);
  if (n == 0) {
    /* Hopefully this indicates the qemu child process has died. */
    child_cleanup (g);

    if (error_if_eof) {
      /* We weren't expecting eof here (called from launch) so place
       * something in the error buffer.  RHBZ#588851.
       */
      error (g, "child process died unexpectedly");
    }
    return -1;
  }

  if (n == -1) {
    if (errno == EINTR || errno == EAGAIN)
      return 0;

    perrorf (g, "read");
    return -1;
  }

  /* It's an actual log message, send it upwards if anyone is listening. */
  guestfs___call_callbacks_message (g, GUESTFS_EVENT_APPLIANCE, buf, n);

  /* This is a gross hack.  See the comment above
   * guestfs___launch_send_progress.
   */
  if (g->state == LAUNCHING) {
    const char *sentinel;
    size_t len;

    sentinel = "Linux version"; /* kernel up */
    len = strlen (sentinel);
    if (memmem (buf, n, sentinel, len) != NULL)
      guestfs___launch_send_progress (g, 6);

    sentinel = "Starting /init script"; /* /init running */
    len = strlen (sentinel);
    if (memmem (buf, n, sentinel, len) != NULL)
      guestfs___launch_send_progress (g, 9);
  }

  return 0;
}
Exemplo n.º 6
0
void
guestfs_close (guestfs_h *g)
{
  struct qemu_param *qp, *qp_next;

  if (g->state == NO_HANDLE) {
    /* Not safe to call ANY callbacks here, so ... */
    fprintf (stderr, _("guestfs_close: called twice on the same handle\n"));
    return;
  }

  /* Remove the handle from the handles list. */
  gl_lock_lock (handles_lock);
  if (handles == g)
    handles = g->next;
  else {
    guestfs_h *gg;

    for (gg = handles; gg->next != g; gg = gg->next)
      ;
    gg->next = g->next;
  }
  gl_lock_unlock (handles_lock);

  if (g->trace) {
    const char trace_msg[] = "close";

    guestfs___call_callbacks_message (g, GUESTFS_EVENT_TRACE,
                                      trace_msg, strlen (trace_msg));
  }

  debug (g, "closing guestfs handle %p (state %d)", g, g->state);

  /* If we are valgrinding the daemon, then we *don't* want to kill
   * the subprocess because we want the final valgrind messages sent
   * when we close sockets below.  However for normal production use,
   * killing the subprocess is the right thing to do (in case the
   * daemon or qemu is not responding).
   */
#ifndef VALGRIND_DAEMON
  if (g->state != CONFIG)
    ignore_value (guestfs_shutdown (g));
#endif

  /* Run user close callbacks. */
  guestfs___call_callbacks_void (g, GUESTFS_EVENT_CLOSE);

  /* Remove whole temporary directory. */
  guestfs___remove_tmpdir (g->tmpdir);

  /* Mark the handle as dead and then free up all memory. */
  g->state = NO_HANDLE;

  free (g->events);
  g->nr_events = 0;
  g->events = NULL;

#if HAVE_FUSE
  guestfs___free_fuse (g);
#endif

  guestfs___free_inspect_info (g);
  guestfs___free_drives (&g->drives);

  for (qp = g->qemu_params; qp; qp = qp_next) {
    free (qp->qemu_param);
    free (qp->qemu_value);
    qp_next = qp->next;
    free (qp);
  }

  if (g->pda)
    hash_free (g->pda);
  free (g->tmpdir);
  free (g->last_error);
  free (g->path);
  free (g->qemu);
  free (g->append);
  free (g);
}