Example #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;
}
Example #2
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;
}
Example #3
0
static int
shutdown_uml (guestfs_h *g, void *datav, int check_for_errors)
{
  struct backend_uml_data *data = datav;
  int ret = 0;
  int status;

  /* Signal vmlinux to shutdown cleanly, and kill the recovery process. */
  if (data->pid > 0) {
    debug (g, "sending SIGTERM to process %d", data->pid);
    kill (data->pid, SIGTERM);
  }
  if (data->recoverypid > 0) kill (data->recoverypid, 9);

  /* Wait for subprocess(es) to exit. */
  if (data->pid > 0) {
    if (waitpid (data->pid, &status, 0) == -1) {
      perrorf (g, "waitpid (vmlinux)");
      ret = -1;
    }
    /* Note it's normal for the pre-3.11 vmlinux process to exit with
     * status "killed by signal 15" (where 15 == SIGTERM).  Post 3.11
     * the exit status can normally be 1.
     *
     * So don't consider those to be an error.
     */
    else if (!(WIFSIGNALED (status) && WTERMSIG (status) == SIGTERM) &&
             !(WIFEXITED (status) && WEXITSTATUS (status) == 0) &&
             !(WIFEXITED (status) && WEXITSTATUS (status) == 1)) {
      guestfs___external_command_failed (g, status, g->hv, NULL);
      ret = -1;
    }
  }
  if (data->recoverypid > 0) waitpid (data->recoverypid, NULL, 0);

  data->pid = data->recoverypid = 0;

  return ret;
}
Example #4
0
static char *
cpio_arch (guestfs_h *g, const char *file, const char *path)
{
  CLEANUP_FREE char *tmpdir = guestfs_get_tmpdir (g), *dir = NULL;
  CLEANUP_FREE char *initrd = NULL;
  CLEANUP_CMD_CLOSE struct command *cmd = guestfs___new_command (g);
  char *ret = NULL;
  const char *method;
  int64_t size;
  int r;
  size_t i;

  if (asprintf (&dir, "%s/libguestfsXXXXXX", tmpdir) == -1) {
    perror ("asprintf");
    return NULL;
  }

  if (strstr (file, "gzip"))
    method = "zcat";
  else if (strstr (file, "bzip2"))
    method = "bzcat";
  else
    method = "cat";

  /* Security: Refuse to download initrd if it is huge. */
  size = guestfs_filesize (g, path);
  if (size == -1 || size > 100000000) {
    error (g, _("size of %s unreasonable (%" PRIi64 " bytes)"),
           path, size);
    goto out;
  }

  if (mkdtemp (dir) == NULL) {
    perrorf (g, "mkdtemp");
    goto out;
  }

  initrd = safe_asprintf (g, "%s/initrd", dir);
  if (guestfs_download (g, path, initrd) == -1)
    goto out;

  /* Construct a command to extract named binaries from the initrd file. */
  guestfs___cmd_add_string_unquoted (cmd, "cd ");
  guestfs___cmd_add_string_quoted   (cmd, dir);
  guestfs___cmd_add_string_unquoted (cmd, " && ");
  guestfs___cmd_add_string_unquoted (cmd, method);
  guestfs___cmd_add_string_unquoted (cmd, " initrd | cpio --quiet -id");
  for (i = 0; initrd_binaries[i] != NULL; ++i) {
    guestfs___cmd_add_string_unquoted (cmd, " ");
    guestfs___cmd_add_string_quoted (cmd, initrd_binaries[i]);
  }

  r = guestfs___cmd_run (cmd);
  if (r == -1)
    goto out;
  if (!WIFEXITED (r) || WEXITSTATUS (r) != 0) {
    guestfs___external_command_failed (g, r, "cpio", path);
    goto out;
  }

  for (i = 0; initrd_binaries[i] != NULL; ++i) {
    CLEANUP_FREE char *bin =
      safe_asprintf (g, "%s/%s", dir, initrd_binaries[i]);

    if (is_regular_file (bin)) {
      int flags = g->verbose ? MAGIC_DEBUG : 0;
      flags |= MAGIC_ERROR | MAGIC_RAW;

      magic_t m = magic_open (flags);
      if (m == NULL) {
        perrorf (g, "magic_open");
        goto out;
      }

      if (magic_load (m, NULL) == -1) {
        perrorf (g, "magic_load: default magic database file");
        magic_close (m);
        goto out;
      }

      const char *line = magic_file (m, bin);
      if (line == NULL) {
        perrorf (g, "magic_file: %s", bin);
        magic_close (m);
        goto out;
      }

      CLEANUP_FREE char *elf_arch = match1 (g, line, re_file_elf);
      if (elf_arch != NULL) {
        ret = canonical_elf_arch (g, elf_arch);
        magic_close (m);
        goto out;
      }
      magic_close (m);
    }
  }
  error (g, "file_architecture: could not determine architecture of cpio archive");

 out:
  guestfs___recursive_remove_dir (g, dir);

  return ret;
}
Example #5
0
static int
disk_create_qcow2 (guestfs_h *g, const char *orig_filename, int64_t size,
                   const char *backingfile,
                   const struct guestfs_disk_create_argv *optargs)
{
  CLEANUP_FREE char *filename = NULL;
  const char *backingformat = NULL;
  const char *preallocation = NULL;
  const char *compat = NULL;
  int clustersize = -1;
  CLEANUP_FREE_STRINGSBUF DECLARE_STRINGSBUF (optionsv);
  CLEANUP_CMD_CLOSE struct command *cmd = guestfs___new_command (g);
  int r;

  /* If the filename is something like "file:foo" then qemu-img will
   * try to interpret that as "foo" in the file:/// protocol.  To
   * avoid that, if the path is relative prefix it with "./" since
   * qemu-img won't try to interpret such a path.
   */
  if (orig_filename[0] != '/')
    filename = safe_asprintf (g, "./%s", orig_filename);
  else
    filename = safe_strdup (g, orig_filename);

  if (optargs->bitmask & GUESTFS_DISK_CREATE_BACKINGFORMAT_BITMASK) {
    backingformat = optargs->backingformat;
    if (STRNEQ (backingformat, "raw") && STRNEQ (backingformat, "qcow2")) {
      error (g, _("invalid value for backingformat parameter '%s'"),
             backingformat);
      return -1;
    }
  }
  if (optargs->bitmask & GUESTFS_DISK_CREATE_PREALLOCATION_BITMASK) {
    preallocation = optargs->preallocation;
    if (STRNEQ (preallocation, "off") && STRNEQ (preallocation, "metadata")) {
      error (g, _("invalid value for preallocation parameter '%s'"),
             preallocation);
      return -1;
    }
  }
  if (optargs->bitmask & GUESTFS_DISK_CREATE_COMPAT_BITMASK) {
    compat = optargs->compat;
    if (STRNEQ (compat, "0.10") && STRNEQ (compat, "1.1")) {
      error (g, _("invalid value for compat parameter '%s'"), compat);
      return -1;
    }
  }
  if (optargs->bitmask & GUESTFS_DISK_CREATE_CLUSTERSIZE_BITMASK) {
    clustersize = optargs->clustersize;
    if (clustersize < 512 || clustersize > 2097152 ||
        !is_power_of_2 ((unsigned) clustersize)) {
      error (g, _("invalid value for clustersize parameter '%d'"),
             clustersize);
      return -1;
    }
  }

  /* Assemble the qemu-img command line. */
  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");

  /* -o parameter. */
  if (backingfile) {
    CLEANUP_FREE char *p = qemu_escape_param (g, backingfile);
    guestfs___add_sprintf (g, &optionsv, "backing_file=%s", p);
  }
  if (backingformat)
    guestfs___add_sprintf (g, &optionsv, "backing_fmt=%s", backingformat);
  if (preallocation)
    guestfs___add_sprintf (g, &optionsv, "preallocation=%s", preallocation);
  if (compat)
    guestfs___add_sprintf (g, &optionsv, "compat=%s", compat);
  if (clustersize >= 0)
    guestfs___add_sprintf (g, &optionsv, "cluster_size=%d", clustersize);
  guestfs___end_stringsbuf (g, &optionsv);

  if (optionsv.size > 1) {
    CLEANUP_FREE char *options = guestfs___join_strings (",", optionsv.argv);
    guestfs___cmd_add_arg (cmd, "-o");
    guestfs___cmd_add_arg (cmd, options);
  }

  /* Complete the command line. */
  guestfs___cmd_add_arg (cmd, filename);
  if (size >= 0)
    guestfs___cmd_add_arg_format (cmd, "%" PRIi64, size);

  r = guestfs___cmd_run (cmd);
  if (!WIFEXITED (r) || WEXITSTATUS (r) != 0) {
    guestfs___external_command_failed (g, r, "qemu-img", orig_filename);
    return -1;
  }

  return 0;
}