/* 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; }
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; }
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; }
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; }
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; }