예제 #1
0
/* Run uml_mkcow to create a COW overlay. */
static char *
make_cow_overlay (guestfs_h *g, const char *original)
{
  CLEANUP_CMD_CLOSE struct command *cmd = guestfs___new_command (g);
  char *overlay;
  int r;

  if (guestfs___lazy_make_tmpdir (g) == -1)
    return NULL;

  overlay = safe_asprintf (g, "%s/overlay%d", g->tmpdir, g->unique++);

  guestfs___cmd_add_arg (cmd, "uml_mkcow");
  guestfs___cmd_add_arg (cmd, overlay);
  guestfs___cmd_add_arg (cmd, original);
  r = guestfs___cmd_run (cmd);
  if (r == -1) {
    free (overlay);
    return NULL;
  }
  if (!WIFEXITED (r) || WEXITSTATUS (r) != 0) {
    guestfs___external_command_failed (g, r, "uml_mkcow", original);
    free (overlay);
    return NULL;
  }

  return overlay;
}
예제 #2
0
static int
write_or_append (guestfs_h *g, const char *path,
                 const char *content, size_t size,
                 int append)
{
  CLEANUP_UNLINK_FREE char *tmpfile = NULL;
  int fd = -1;
  int64_t filesize;

  /* If the content is small enough, use guestfs_internal_write{,_append}
   * since that call is more efficient.
   */
  if (size <= 2*1024*1024)
    return
      (!append ? guestfs_internal_write : guestfs_internal_write_append)
      (g, path, content, size);

  if (guestfs___lazy_make_tmpdir (g) == -1)
    goto err;

  /* Write the content out to a temporary file. */
  tmpfile = safe_asprintf (g, "%s/write%d", g->tmpdir, ++g->unique);

  fd = open (tmpfile, O_WRONLY|O_CREAT|O_NOCTTY|O_CLOEXEC, 0600);
  if (fd == -1) {
    perrorf (g, "open: %s", tmpfile);
    goto err;
  }

  if (full_write (fd, content, size) != size) {
    perrorf (g, "write: %s", tmpfile);
    goto err;
  }

  if (close (fd) == -1) {
    perrorf (g, "close: %s", tmpfile);
    goto err;
  }
  fd = -1;

  if (!append) {
    if (guestfs_upload (g, tmpfile, path) == -1)
      goto err;
  }
  else {
    /* XXX Should have an 'upload-append' call to make this atomic. */
    filesize = guestfs_filesize (g, path);
    if (filesize == -1)
      goto err;
    if (guestfs_upload_offset (g, tmpfile, path, filesize) == -1)
      goto err;
  }

  return 0;

 err:
  if (fd >= 0)
    close (fd);
  return -1;
}
예제 #3
0
파일: launch.c 프로젝트: jadbox/libguestfs
int
guestfs__launch (guestfs_h *g)
{
  /* Configured? */
  if (g->state != CONFIG) {
    error (g, _("the libguestfs handle has already been launched"));
    return -1;
  }

  /* Start the clock ... */
  gettimeofday (&g->launch_t, NULL);
  TRACE0 (launch_start);

  /* Make the temporary directory. */
  if (guestfs___lazy_make_tmpdir (g) == -1)
    return -1;

  /* Allow anyone to read the temporary directory.  The socket in this
   * directory won't be readable but anyone can see it exists if they
   * want. (RHBZ#610880).
   */
  if (chmod (g->tmpdir, 0755) == -1)
    warning (g, "chmod: %s: %m (ignored)", g->tmpdir);

  /* Some common debugging information. */
  if (g->verbose) {
    CLEANUP_FREE_VERSION struct guestfs_version *v =
      guestfs_version (g);
    struct backend *b;
    CLEANUP_FREE char *backend = guestfs_get_backend (g);

    debug (g, "launch: program=%s", g->program);
    debug (g, "launch: version=%"PRIi64".%"PRIi64".%"PRIi64"%s",
           v->major, v->minor, v->release, v->extra);

    for (b = backends; b != NULL; b = b->next)
      debug (g, "launch: backend registered: %s", b->name);
    debug (g, "launch: backend=%s", backend);

    debug (g, "launch: tmpdir=%s", g->tmpdir);
    debug (g, "launch: umask=0%03o", get_umask (g));
    debug (g, "launch: euid=%d", geteuid ());
  }

  /* Launch the appliance. */
  if (g->backend_ops->launch (g, g->backend_data, g->backend_arg) == -1)
    return -1;

  /* If network is enabled, upload /etc/resolv.conf from the host so
   * the guest will know how to reach the nameservers.
   */
  if (g->enable_network && access ("/etc/resolv.conf", F_OK) == 0) {
    guestfs_internal_upload (g, "/etc/resolv.conf", "/etc/resolv.conf", 0644);
  }

  return 0;
}
예제 #4
0
파일: info.c 프로젝트: yumingfei/libguestfs
static int
run_qemu_img_info (guestfs_h *g, const char *filename,
                   cmd_stdout_callback fn, void *data)
{
  char *abs_filename = NULL;
  char *safe_filename = NULL;
  struct command *cmd;
  int r;

  if (guestfs___lazy_make_tmpdir (g) == -1)
    return -1;

  safe_filename = safe_asprintf (g, "%s/format.%d", g->tmpdir, ++g->unique);

  /* 'filename' must be an absolute path so we can link to it. */
  abs_filename = realpath (filename, NULL);
  if (abs_filename == NULL) {
    perrorf (g, "realpath");
    goto error;
  }

  if (symlink (abs_filename, safe_filename) == -1) {
    perrorf (g, "symlink");
    goto error;
  }

  cmd = guestfs___new_command (g);
  guestfs___cmd_add_arg (cmd, "qemu-img");
  guestfs___cmd_add_arg (cmd, "info");
  guestfs___cmd_add_arg (cmd, safe_filename);
  guestfs___cmd_set_stdout_callback (cmd, fn, data, 0);
  r = guestfs___cmd_run (cmd);
  guestfs___cmd_close (cmd);
  if (r == -1)
    goto error;
  if (!WIFEXITED (r) || WEXITSTATUS (r) != 0) {
    error (g, _("qemu-img: %s: child process failed"), filename);
    goto error;
  }

  free (safe_filename);
  free (abs_filename);
  return 0;

 error:
  free (safe_filename);
  free (abs_filename);

  return -1;
}
예제 #5
0
static char *
create_cow_overlay_direct (guestfs_h *g, void *datav, struct drive *drv)
{
  char *overlay = NULL;
  CLEANUP_FREE char *backing_drive = NULL;
  CLEANUP_CMD_CLOSE struct command *cmd = guestfs___new_command (g);
  int r;

  backing_drive = guestfs___drive_source_qemu_param (g, &drv->src);
  if (!backing_drive)
    goto error;

  if (guestfs___lazy_make_tmpdir (g) == -1)
    goto error;

  overlay = safe_asprintf (g, "%s/overlay%d", g->tmpdir, ++g->unique);

  guestfs___cmd_add_arg (cmd, "qemu-img");
  guestfs___cmd_add_arg (cmd, "create");
  guestfs___cmd_add_arg (cmd, "-f");
  guestfs___cmd_add_arg (cmd, "qcow2");
  guestfs___cmd_add_arg (cmd, "-b");
  guestfs___cmd_add_arg (cmd, backing_drive);
  if (drv->src.format) {
    guestfs___cmd_add_arg (cmd, "-o");
    guestfs___cmd_add_arg_format (cmd, "backing_fmt=%s", drv->src.format);
  }
  guestfs___cmd_add_arg (cmd, overlay);
  r = guestfs___cmd_run (cmd);
  if (r == -1)
    goto error;
  if (!WIFEXITED (r) || WEXITSTATUS (r) != 0) {
    guestfs___external_command_failed (g, r, "qemu-img create", backing_drive);
    goto error;
  }

  /* Caller sets g->overlay in the handle to this, and then manages
   * the memory.
   */
  return overlay;

 error:
  free (overlay);

  return NULL;
}
예제 #6
0
/* This is implemented library-side in order to get around potential
 * protocol limits.
 *
 * A journal record can contain an arbitrarily large amount of data
 * (stuff like core dumps in particular).  To save the user from
 * having to deal with it, the implementation uses an internal
 * function that downloads to a FileOut, and we reconstruct the
 * hashtable entries from that.
 */
struct guestfs_xattr_list *
guestfs__journal_get (guestfs_h *g)
{
  CLEANUP_UNLINK_FREE char *tmpfile = NULL;
  CLEANUP_FREE char *buf = NULL;
  struct stat statbuf;
  struct guestfs_xattr_list *ret = NULL;
  char *p, *eofield, *eobuf;
  int fd = -1;
  size_t i, j, size;
  uint64_t len;

  if (guestfs___lazy_make_tmpdir (g) == -1)
    goto err;

  tmpfile = safe_asprintf (g, "%s/journal%d", g->tmpdir, ++g->unique);
  if (guestfs_internal_journal_get (g, tmpfile) == -1)
    goto err;

  fd = open (tmpfile, O_RDONLY|O_CLOEXEC);
  if (fd == -1) {
    perrorf (g, "open: %s", tmpfile);
    goto err;
  }

  /* Read the whole file into memory. */
  if (fstat (fd, &statbuf) == -1) {
    perrorf (g, "stat: %s", tmpfile);
    goto err;
  }

  /* Don't use safe_malloc.  Want to return an errno to the caller. */
  size = statbuf.st_size;
  buf = malloc (size+1);
  if (!buf) {
    perrorf (g, "malloc: %zu bytes", size);
    goto err;
  }
  eobuf = &buf[size];
  *eobuf = '\0';                /* Makes strchr etc safe. */

  if (full_read (fd, buf, size) != size) {
    perrorf (g, "full-read: %s: %zu bytes", tmpfile, size);
    goto err;
  }

  if (close (fd) == -1) {
    perrorf (g, "close: %s", tmpfile);
    goto err;
  }
  fd = -1;

  j = 0;
  ret = safe_malloc (g, sizeof *ret);
  ret->len = 0;
  ret->val = NULL;

  /* There is a simple, private protocol employed here (note: it may
   * be changed at any time), where fields are sent using a big-endian
   * 64 bit length field followed by N bytes of 'field=data' binary
   * data.
   */
  for (i = 0; i < size; ) {
    if (i+8 > size) {
      error (g, "invalid data from guestfs_internal_journal_get: "
             "truncated: "
             "size=%zu, i=%zu", size, i);
      goto err;
    }
    memcpy(&len, &buf[i], sizeof(len));
    len = be64toh (len);
    i += 8;
    eofield = &buf[i+len];
    if (eofield > eobuf) {
      error (g, "invalid data from guestfs_internal_journal_get: "
             "length field is too large: "
             "size=%zu, i=%zu, len=%" PRIu64, size, i, len);
      goto err;
    }
    p = strchr (&buf[i], '=');
    if (!p || p >= eofield) {
      error (g, "invalid data from guestfs_internal_journal_get: "
             "no '=' found separating field name and data: "
             "size=%zu, i=%zu, p=%p", size, i, p);
      goto err;
    }
    *p = '\0';

    j++;
    ret->val = safe_realloc (g, ret->val, j * sizeof (struct guestfs_xattr));
    ret->val[j-1].attrname = safe_strdup (g, &buf[i]);
    ret->val[j-1].attrval_len = eofield - (p+1);
    ret->val[j-1].attrval = safe_memdup (g, p+1, eofield - (p+1));
    ret->len = j;
    i += len;
  }

  return ret;                   /* caller frees */

 err:
  guestfs_free_xattr_list (ret);
  if (fd >= 0)
    close (fd);
  return NULL;
}
예제 #7
0
char *
guestfs__read_file (guestfs_h *g, const char *path, size_t *size_r)
{
  int fd = -1;
  size_t size;
  CLEANUP_UNLINK_FREE char *tmpfile = NULL;
  char *ret = NULL;
  struct stat statbuf;

  if (guestfs___lazy_make_tmpdir (g) == -1)
    goto err;

  tmpfile = safe_asprintf (g, "%s/cat%d", g->tmpdir, ++g->unique);

  if (guestfs_download (g, path, tmpfile) == -1)
    goto err;

  fd = open (tmpfile, O_RDONLY|O_CLOEXEC);
  if (fd == -1) {
    perrorf (g, "open: %s", tmpfile);
    goto err;
  }

  /* Read the whole file into memory. */
  if (fstat (fd, &statbuf) == -1) {
    perrorf (g, "stat: %s", tmpfile);
    goto err;
  }

  /* Don't use safe_malloc, because we want to return an errno to the caller. */
  size = statbuf.st_size;
  ret = malloc (size + 1);
  if (!ret) {
    perrorf (g, "malloc: %zu bytes", size + 1);
    goto err;
  }

  if (full_read (fd, ret, size) != size) {
    perrorf (g, "full-read: %s: %zu bytes", tmpfile, size + 1);
    goto err;
  }

  ret[size] = '\0';

  if (close (fd) == -1) {
    perrorf (g, "close: %s", tmpfile);
    goto err;
  }

  /* Mustn't touch *size_r until we are sure that we won't return any
   * error (RHBZ#589039).
   */
  *size_r = size;
  return ret;

 err:
  free (ret);
  if (fd >= 0)
    close (fd);
  return NULL;
}