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_int_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; /* Conservative whitelist. This can be extended with other * valid formats as required. */ if (STRNEQ (backingformat, "raw") && STRNEQ (backingformat, "qcow2") && STRNEQ (backingformat, "vmdk")) { error (g, _("invalid value for backingformat parameter '%s'"), backingformat); return -1; } } if (optargs->bitmask & GUESTFS_DISK_CREATE_PREALLOCATION_BITMASK) { if (STREQ (optargs->preallocation, "off") || STREQ (optargs->preallocation, "sparse")) preallocation = "off"; else if (STREQ (optargs->preallocation, "metadata")) preallocation = "metadata"; else if (STREQ (optargs->preallocation, "full")) /* Ugh: https://lists.gnu.org/archive/html/qemu-devel/2014-08/msg03863.html */ preallocation = "falloc"; else { 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_int_cmd_add_arg (cmd, "qemu-img"); guestfs_int_cmd_add_arg (cmd, "create"); guestfs_int_cmd_add_arg (cmd, "-f"); guestfs_int_cmd_add_arg (cmd, "qcow2"); /* -o parameter. */ if (backingfile) { CLEANUP_FREE char *p = qemu_escape_param (g, backingfile); guestfs_int_add_sprintf (g, &optionsv, "backing_file=%s", p); } if (backingformat) guestfs_int_add_sprintf (g, &optionsv, "backing_fmt=%s", backingformat); if (preallocation) guestfs_int_add_sprintf (g, &optionsv, "preallocation=%s", preallocation); if (compat) guestfs_int_add_sprintf (g, &optionsv, "compat=%s", compat); if (clustersize >= 0) guestfs_int_add_sprintf (g, &optionsv, "cluster_size=%d", clustersize); guestfs_int_end_stringsbuf (g, &optionsv); if (optionsv.size > 1) { CLEANUP_FREE char *options = guestfs_int_join_strings (",", optionsv.argv); guestfs_int_cmd_add_arg (cmd, "-o"); guestfs_int_cmd_add_arg (cmd, options); } /* Complete the command line. */ guestfs_int_cmd_add_arg (cmd, filename); if (size >= 0) guestfs_int_cmd_add_arg_format (cmd, "%" PRIi64, size); r = guestfs_int_cmd_run (cmd); if (!WIFEXITED (r) || WEXITSTATUS (r) != 0) { guestfs_int_external_command_failed (g, r, "qemu-img", orig_filename); return -1; } return 0; }
static int testCompareXMLToArgvFiles(const char *xml, const char *cmd, unsigned long long extraFlags, const char *migrateFrom) { char argvData[MAX_FILE]; char *expectargv = &(argvData[0]); char *actualargv = NULL; const char **argv = NULL; const char **qenv = NULL; const char **tmp = NULL; int ret = -1, len; unsigned long long flags; virDomainDefPtr vmdef = NULL; virDomainChrDef monitor_chr; virConnectPtr conn; if (!(conn = virGetConnect())) goto fail; if (virtTestLoadFile(cmd, &expectargv, MAX_FILE) < 0) goto fail; if (!(vmdef = virDomainDefParseFile(driver.caps, xml, VIR_DOMAIN_XML_INACTIVE))) goto fail; if (extraFlags & QEMUD_CMD_FLAG_DOMID) vmdef->id = 6; else vmdef->id = -1; memset(&monitor_chr, 0, sizeof(monitor_chr)); monitor_chr.type = VIR_DOMAIN_CHR_TYPE_UNIX; monitor_chr.data.nix.path = (char *)"/tmp/test-monitor"; monitor_chr.data.nix.listen = 1; if (!(monitor_chr.info.alias = strdup("monitor"))) goto fail; flags = QEMUD_CMD_FLAG_VNC_COLON | QEMUD_CMD_FLAG_NO_REBOOT | extraFlags; if (qemudCanonicalizeMachine(&driver, vmdef) < 0) goto fail; if (flags & QEMUD_CMD_FLAG_DEVICE) { qemuDomainPCIAddressSetPtr pciaddrs; if (!(pciaddrs = qemuDomainPCIAddressSetCreate(vmdef))) goto fail; if (qemuAssignDevicePCISlots(vmdef, pciaddrs) < 0) goto fail; qemuDomainPCIAddressSetFree(pciaddrs); } if (qemudBuildCommandLine(conn, &driver, vmdef, &monitor_chr, 0, flags, &argv, &qenv, NULL, NULL, migrateFrom, NULL) < 0) goto fail; len = 1; /* for trailing newline */ tmp = qenv; while (*tmp) { len += strlen(*tmp) + 1; tmp++; } tmp = argv; while (*tmp) { len += strlen(*tmp) + 1; tmp++; } if ((actualargv = malloc(sizeof(*actualargv)*len)) == NULL) goto fail; actualargv[0] = '\0'; tmp = qenv; while (*tmp) { if (actualargv[0]) strcat(actualargv, " "); strcat(actualargv, *tmp); tmp++; } tmp = argv; while (*tmp) { if (actualargv[0]) strcat(actualargv, " "); strcat(actualargv, *tmp); tmp++; } strcat(actualargv, "\n"); if (STRNEQ(expectargv, actualargv)) { virtTestDifference(stderr, expectargv, actualargv); goto fail; } ret = 0; fail: free(actualargv); if (argv) { tmp = argv; while (*tmp) { free(*(char**)tmp); tmp++; } free(argv); } if (qenv) { tmp = qenv; while (*tmp) { free(*(char**)tmp); tmp++; } free(qenv); } virDomainDefFree(vmdef); virUnrefConnect(conn); return ret; }
char * complete_dest_paths_generator (const char *text, int state) { #ifdef HAVE_LIBREADLINE static size_t len, index; static struct word *words = NULL; static size_t nr_words = 0; guestfs_error_handler_cb old_error_cb; void *old_error_cb_data; /* Temporarily replace the error handler so that messages don't * get printed to stderr while we are issuing commands. */ #define SAVE_ERROR_CB \ old_error_cb = guestfs_get_error_handler (g, &old_error_cb_data); \ guestfs_set_error_handler (g, NULL, NULL); /* Restore error handler. */ #define RESTORE_ERROR_CB \ guestfs_set_error_handler (g, old_error_cb, old_error_cb_data); if (!state) { char **strs; len = strlen (text); index = 0; if (words) free_words (words, nr_words); words = NULL; nr_words = 0; SAVE_ERROR_CB /* Silently do nothing if an allocation fails */ #define APPEND_STRS_AND_FREE \ do { \ if (strs) { \ size_t i; \ size_t n = count_strings (strs); \ \ if ( n > 0 && ! xalloc_oversized (nr_words + n, sizeof (struct word))) { \ struct word *w; \ w = realloc (words, sizeof (struct word) * (nr_words + n)); \ \ if (w == NULL) { \ free_words (words, nr_words); \ words = NULL; \ nr_words = 0; \ } else { \ words = w; \ for (i = 0; i < n; ++i) { \ words[nr_words].name = strs[i]; \ words[nr_words].is_dir = 0; \ nr_words++; \ } \ } \ } \ free (strs); \ } \ } while (0) /* Is it a device? */ if (len < 5 || STREQLEN (text, "/dev/", 5)) { /* Get a list of everything that can possibly begin with /dev/ */ strs = guestfs_list_devices (g); APPEND_STRS_AND_FREE; strs = guestfs_list_partitions (g); APPEND_STRS_AND_FREE; strs = guestfs_lvs (g); APPEND_STRS_AND_FREE; strs = guestfs_list_dm_devices (g); APPEND_STRS_AND_FREE; strs = guestfs_list_md_devices (g); APPEND_STRS_AND_FREE; } if (len < 1 || text[0] == '/') { /* If we've got a partial path already, we need to list everything * in that directory, otherwise list everything in / */ char *p, *dir; struct guestfs_dirent_list *dirents; p = strrchr (text, '/'); dir = p && p > text ? strndup (text, p - text) : strdup ("/"); if (dir) { dirents = guestfs_readdir (g, dir); /* Prepend directory to names before adding them to the list * of words. */ if (dirents) { size_t i; for (i = 0; i < dirents->len; ++i) { int err; if (STRNEQ (dirents->val[i].name, ".") && STRNEQ (dirents->val[i].name, "..")) { if (STREQ (dir, "/")) err = asprintf (&p, "/%s", dirents->val[i].name); else err = asprintf (&p, "%s/%s", dir, dirents->val[i].name); if (err >= 0) { if (!xalloc_oversized (nr_words+1, sizeof (struct word))) { struct word *w; w = realloc (words, sizeof (struct word) * (nr_words+1)); if (w == NULL) { free_words (words, nr_words); words = NULL; nr_words = 0; } else { words = w; words[nr_words].name = p; words[nr_words].is_dir = dirents->val[i].ftyp == 'd'; nr_words++; } } } } } guestfs_free_dirent_list (dirents); } } } /* else ... In theory we could complete other things here such as VG * names. At the moment we don't do that. */ RESTORE_ERROR_CB }
char * do_initrd_cat (const char *path, const char *filename, size_t *size_r) { char tmpdir[] = "/tmp/initrd-cat-XXXXXX"; CLEANUP_FREE char *cmd = NULL; struct stat statbuf; int fd, r; char *ret = NULL; CLEANUP_FREE char *fullpath = NULL; if (mkdtemp (tmpdir) == NULL) { reply_with_perror ("mkdtemp"); return NULL; } /* Extract file into temporary directory. This may create subdirs. * It's also possible that this doesn't create anything at all * (eg. if the named file does not exist in the cpio archive) -- * cpio is silent in this case. */ /* "zcat /sysroot/<path> | cpio --quiet -id file", but paths must be quoted */ if (asprintf_nowarn (&cmd, "cd %Q && zcat %R | cpio --quiet -id %Q", tmpdir, path, filename) == -1) { reply_with_perror ("asprintf"); rmdir (tmpdir); return NULL; } r = system (cmd); if (r == -1) { reply_with_perror ("command failed: %s", cmd); rmdir (tmpdir); return NULL; } if (WEXITSTATUS (r) != 0) { reply_with_perror ("command failed with return code %d", WEXITSTATUS (r)); rmdir (tmpdir); return NULL; } /* Construct the expected name of the extracted file. */ if (asprintf (&fullpath, "%s/%s", tmpdir, filename) == -1) { reply_with_perror ("asprintf"); rmdir (tmpdir); return NULL; } /* See if we got a file. */ fd = open (fullpath, O_RDONLY|O_CLOEXEC); if (fd == -1) { reply_with_perror ("open: %s:%s", path, filename); rmdir (tmpdir); return NULL; } /* From this point, we know the file exists, so we require full * cleanup. */ if (fstat (fd, &statbuf) == -1) { reply_with_perror ("fstat: %s:%s", path, filename); goto cleanup; } /* The actual limit on messages is smaller than this. This * check just limits the amount of memory we'll try and allocate * here. If the message is larger than the real limit, that will * be caught later when we try to serialize the message. */ if (statbuf.st_size >= GUESTFS_MESSAGE_MAX) { reply_with_error ("%s:%s: file is too large for the protocol", path, filename); goto cleanup; } ret = malloc (statbuf.st_size); if (ret == NULL) { reply_with_perror ("malloc"); goto cleanup; } if (xread (fd, ret, statbuf.st_size) == -1) { reply_with_perror ("read: %s:%s", path, filename); free (ret); ret = NULL; goto cleanup; } if (close (fd) == -1) { reply_with_perror ("close: %s:%s", path, filename); free (ret); ret = NULL; goto cleanup; } fd = -1; /* Mustn't touch *size_r until we are sure that we won't return any * error (RHBZ#589039). */ *size_r = statbuf.st_size; cleanup: if (fd >= 0) close (fd); /* Remove the file. */ if (unlink (fullpath) == -1) { fprintf (stderr, "unlink: %s: %m\n", fullpath); /* non-fatal */ } /* Remove the directories up to and including the temp directory. */ do { char *p = strrchr (fullpath, '/'); if (!p) break; *p = '\0'; if (rmdir (fullpath) == -1) { fprintf (stderr, "rmdir: %s: %m\n", fullpath); /* non-fatal */ } } while (STRNEQ (fullpath, tmpdir)); return ret; }
static int testCompareXMLToArgvFiles(const char *xml, const char *cmdline, virBitmapPtr extraFlags, const char *migrateFrom, int migrateFd, bool json, bool expectError) { char *expectargv = NULL; int len; char *actualargv = NULL; int ret = -1; virDomainDefPtr vmdef = NULL; virDomainChrSourceDef monitor_chr; virConnectPtr conn; char *log = NULL; char *emulator = NULL; virCommandPtr cmd = NULL; if (!(conn = virGetConnect())) goto fail; len = virtTestLoadFile(cmdline, &expectargv); if (len < 0) goto fail; if (len && expectargv[len - 1] == '\n') expectargv[len - 1] = '\0'; if (!(vmdef = virDomainDefParseFile(driver.caps, xml, QEMU_EXPECTED_VIRT_TYPES, VIR_DOMAIN_XML_INACTIVE))) goto fail; /* * For test purposes, we may want to fake emulator's output by providing * our own script instead of a real emulator. For this to work we need to * specify a relative path in <emulator/> element, which, however, is not * allowed by RelaxNG schema for domain XML. To work around it we add an * extra '/' at the beginning of relative emulator path so that it looks * like, e.g., "/./qemu.sh" or "/../emulator/qemu.sh" instead of * "./qemu.sh" or "../emulator/qemu.sh" respectively. The following code * detects such paths, strips the extra '/' and makes the path absolute. */ if (vmdef->emulator && STRPREFIX(vmdef->emulator, "/.")) { if (!(emulator = strdup(vmdef->emulator + 1))) goto fail; free(vmdef->emulator); vmdef->emulator = NULL; if (virAsprintf(&vmdef->emulator, "%s/qemuxml2argvdata/%s", abs_srcdir, emulator) < 0) goto fail; } if (qemuCapsGet(extraFlags, QEMU_CAPS_DOMID)) vmdef->id = 6; else vmdef->id = -1; memset(&monitor_chr, 0, sizeof(monitor_chr)); monitor_chr.type = VIR_DOMAIN_CHR_TYPE_UNIX; monitor_chr.data.nix.path = (char *)"/tmp/test-monitor"; monitor_chr.data.nix.listen = true; qemuCapsSetList(extraFlags, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, QEMU_CAPS_LAST); if (qemudCanonicalizeMachine(&driver, vmdef) < 0) goto fail; if (qemuCapsGet(extraFlags, QEMU_CAPS_DEVICE)) { qemuDomainPCIAddressSetPtr pciaddrs; if (!(pciaddrs = qemuDomainPCIAddressSetCreate(vmdef))) goto fail; if (qemuAssignDevicePCISlots(vmdef, pciaddrs) < 0) goto fail; qemuDomainPCIAddressSetFree(pciaddrs); } free(virtTestLogContentAndReset()); virResetLastError(); /* We do not call qemuCapsExtractVersionInfo() before calling * qemuBuildCommandLine(), so we should set QEMU_CAPS_PCI_MULTIBUS for * x86_64 and i686 architectures here. */ if (STREQLEN(vmdef->os.arch, "x86_64", 6) || STREQLEN(vmdef->os.arch, "i686", 4)) { qemuCapsSet(extraFlags, QEMU_CAPS_PCI_MULTIBUS); } if (qemuAssignDeviceAliases(vmdef, extraFlags) < 0) goto fail; if (!(cmd = qemuBuildCommandLine(conn, &driver, vmdef, &monitor_chr, json, extraFlags, migrateFrom, migrateFd, NULL, VIR_NETDEV_VPORT_PROFILE_OP_NO_OP))) goto fail; if (!!virGetLastError() != expectError) { if (virTestGetDebug() && (log = virtTestLogContentAndReset())) fprintf(stderr, "\n%s", log); goto fail; } if (expectError) { /* need to suppress the errors */ virResetLastError(); } if (!(actualargv = virCommandToString(cmd))) goto fail; if (emulator) { /* Skip the abs_srcdir portion of replacement emulator. */ char *start_skip = strstr(actualargv, abs_srcdir); char *end_skip = strstr(actualargv, emulator); if (!start_skip || !end_skip) goto fail; memmove(start_skip, end_skip, strlen(end_skip) + 1); } if (STRNEQ(expectargv, actualargv)) { virtTestDifference(stderr, expectargv, actualargv); goto fail; } ret = 0; fail: free(log); free(emulator); free(expectargv); free(actualargv); virCommandFree(cmd); virDomainDefFree(vmdef); virUnrefConnect(conn); return ret; }
/* Align def->disks to def->domain. Sort the list of def->disks, * filling in any missing disks or snapshot state defaults given by * the domain, with a fallback to a passed in default. Convert paths * to disk targets for uniformity. Issue an error and return -1 if * any def->disks[n]->name appears more than once or does not map to * dom->disks. If require_match, also require that existing * def->disks snapshot states do not override explicit def->dom * settings. */ int virDomainSnapshotAlignDisks(virDomainSnapshotDefPtr def, int default_snapshot, bool require_match) { int ret = -1; virBitmapPtr map = NULL; int i; int ndisks; bool inuse; if (!def->dom) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("missing domain in snapshot")); goto cleanup; } if (def->ndisks > def->dom->ndisks) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("too many disk snapshot requests for domain")); goto cleanup; } /* Unlikely to have a guest without disks but technically possible. */ if (!def->dom->ndisks) { ret = 0; goto cleanup; } if (!(map = virBitmapNew(def->dom->ndisks))) { virReportOOMError(); goto cleanup; } /* Double check requested disks. */ for (i = 0; i < def->ndisks; i++) { virDomainSnapshotDiskDefPtr disk = &def->disks[i]; int idx = virDomainDiskIndexByName(def->dom, disk->name, false); int disk_snapshot; if (idx < 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("no disk named '%s'"), disk->name); goto cleanup; } disk_snapshot = def->dom->disks[idx]->snapshot; if (virBitmapGetBit(map, idx, &inuse) < 0 || inuse) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("disk '%s' specified twice"), disk->name); goto cleanup; } ignore_value(virBitmapSetBit(map, idx)); disk->index = idx; if (!disk_snapshot) disk_snapshot = default_snapshot; if (!disk->snapshot) { disk->snapshot = disk_snapshot; } else if (disk_snapshot && require_match && disk->snapshot != disk_snapshot) { const char *tmp; tmp = virDomainSnapshotLocationTypeToString(disk_snapshot); virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("disk '%s' must use snapshot mode '%s'"), disk->name, tmp); goto cleanup; } if (disk->file && disk->snapshot != VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("file '%s' for disk '%s' requires " "use of external snapshot mode"), disk->file, disk->name); goto cleanup; } if (STRNEQ(disk->name, def->dom->disks[idx]->dst)) { VIR_FREE(disk->name); if (!(disk->name = strdup(def->dom->disks[idx]->dst))) { virReportOOMError(); goto cleanup; } } } /* Provide defaults for all remaining disks. */ ndisks = def->ndisks; if (VIR_EXPAND_N(def->disks, def->ndisks, def->dom->ndisks - def->ndisks) < 0) { virReportOOMError(); goto cleanup; } for (i = 0; i < def->dom->ndisks; i++) { virDomainSnapshotDiskDefPtr disk; ignore_value(virBitmapGetBit(map, i, &inuse)); if (inuse) continue; disk = &def->disks[ndisks++]; if (!(disk->name = strdup(def->dom->disks[i]->dst))) { virReportOOMError(); goto cleanup; } disk->index = i; disk->snapshot = def->dom->disks[i]->snapshot; if (!disk->snapshot) disk->snapshot = default_snapshot; } qsort(&def->disks[0], def->ndisks, sizeof(def->disks[0]), disksorter); /* Generate any default external file names, but only if the * backing file is a regular file. */ for (i = 0; i < def->ndisks; i++) { virDomainSnapshotDiskDefPtr disk = &def->disks[i]; if (disk->snapshot == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL && !disk->file) { const char *original = def->dom->disks[i]->src; const char *tmp; struct stat sb; if (!original) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("cannot generate external snapshot name " "for disk '%s' without source"), disk->name); goto cleanup; } if (stat(original, &sb) < 0 || !S_ISREG(sb.st_mode)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("source for disk '%s' is not a regular " "file; refusing to generate external " "snapshot name"), disk->name); goto cleanup; } tmp = strrchr(original, '.'); if (!tmp || strchr(tmp, '/')) { ignore_value(virAsprintf(&disk->file, "%s.%s", original, def->name)); } else { if ((tmp - original) > INT_MAX) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("integer overflow")); goto cleanup; } ignore_value(virAsprintf(&disk->file, "%.*s.%s", (int) (tmp - original), original, def->name)); } if (!disk->file) { virReportOOMError(); goto cleanup; } } } ret = 0; cleanup: virBitmapFree(map); return ret; }
static int testJSONAddRemove(const void *data) { const struct testInfo *info = data; virJSONValuePtr json; virJSONValuePtr name = NULL; char *result = NULL; int ret = -1; json = virJSONValueFromString(info->doc); if (!json) { if (virTestGetVerbose()) fprintf(stderr, "Fail to parse %s\n", info->doc); ret = -1; goto cleanup; } switch (virJSONValueObjectRemoveKey(json, "name", &name)) { case 1: if (!info->pass) { if (virTestGetVerbose()) fprintf(stderr, "should not remove from non-object %s\n", info->doc); goto cleanup; } break; case -1: if (!info->pass) ret = 0; else if (virTestGetVerbose()) fprintf(stderr, "Fail to recognize non-object %s\n", info->doc); goto cleanup; default: if (virTestGetVerbose()) fprintf(stderr, "unexpected result when removing from %s\n", info->doc); goto cleanup; } if (STRNEQ_NULLABLE(virJSONValueGetString(name), "sample")) { if (virTestGetVerbose()) fprintf(stderr, "unexpected value after removing name: %s\n", NULLSTR(virJSONValueGetString(name))); goto cleanup; } if (virJSONValueObjectRemoveKey(json, "name", NULL)) { if (virTestGetVerbose()) fprintf(stderr, "%s", "unexpected success when removing missing key\n"); goto cleanup; } if (virJSONValueObjectAppendString(json, "newname", "foo") < 0) { if (virTestGetVerbose()) fprintf(stderr, "%s", "unexpected failure adding new key\n"); goto cleanup; } if (!(result = virJSONValueToString(json, false))) { if (virTestGetVerbose()) fprintf(stderr, "%s", "failed to stringize result\n"); goto cleanup; } if (STRNEQ(info->expect, result)) { if (virTestGetVerbose()) virtTestDifference(stderr, info->expect, result); goto cleanup; } ret = 0; cleanup: virJSONValueFree(json); virJSONValueFree(name); VIR_FREE(result); return ret; }
static int parallelsLoadNetwork(parallelsConnPtr privconn, virJSONValuePtr jobj) { int ret = -1; virNetworkObjPtr net = NULL; virNetworkDefPtr def; const char *tmp; /* MD5_DIGEST_SIZE = VIR_UUID_BUFLEN = 16 */ unsigned char md5[MD5_DIGEST_SIZE]; if (VIR_ALLOC(def) < 0) goto cleanup; if (!(tmp = virJSONValueObjectGetString(jobj, "Network ID"))) { parallelsParseError(); goto cleanup; } if (VIR_STRDUP(def->name, tmp) < 0) goto cleanup; /* Network names are unique in Parallels Cloud Server, so we can make * a UUID from it */ md5_buffer(tmp, strlen(tmp), md5); memcpy(def->uuid, md5, VIR_UUID_BUFLEN); def->uuid_specified = 1; if (!(tmp = virJSONValueObjectGetString(jobj, "Type"))) { parallelsParseError(); goto cleanup; } if (STREQ(tmp, PARALLELS_BRIDGED_NETWORK_TYPE)) { def->forward.type = VIR_NETWORK_FORWARD_BRIDGE; if (parallelsGetBridgedNetInfo(def, jobj) < 0) { /* Only mandatory networks are required to be configured completely */ if (STRNEQ(def->name, PARALLELS_REQUIRED_BRIDGED_NETWORK)) ret = 0; goto cleanup; } } else if (STREQ(tmp, PARALLELS_HOSTONLY_NETWORK_TYPE)) { def->forward.type = VIR_NETWORK_FORWARD_NONE; if (parallelsGetHostOnlyNetInfo(def, def->name) < 0) { /* Only mandatory networks are required to be configured completely */ if (STRNEQ(def->name, PARALLELS_REQUIRED_HOSTONLY_NETWORK)) ret = 0; goto cleanup; } } else { parallelsParseError(); goto cleanup; } if (!(net = virNetworkAssignDef(privconn->networks, def, 0))) goto cleanup; def = NULL; net->active = 1; net->autostart = 1; ret = 0; cleanup: virNetworkObjEndAPI(&net); virNetworkDefFree(def); return ret; }
static int testCompareXMLToArgvFiles(const char *xml, const char *cmdline, virQEMUCapsPtr extraFlags, const char *migrateFrom, int migrateFd, virQemuXML2ArgvTestFlags flags) { char *expectargv = NULL; int len; char *actualargv = NULL; int ret = -1; virDomainDefPtr vmdef = NULL; virDomainChrSourceDef monitor_chr; virConnectPtr conn; char *log = NULL; virCommandPtr cmd = NULL; if (!(conn = virGetConnect())) goto out; conn->secretDriver = &fakeSecretDriver; if (!(vmdef = virDomainDefParseFile(xml, driver.caps, driver.xmlopt, QEMU_EXPECTED_VIRT_TYPES, VIR_DOMAIN_XML_INACTIVE))) { if (flags & FLAG_EXPECT_PARSE_ERROR) goto ok; goto out; } if (virQEMUCapsGet(extraFlags, QEMU_CAPS_DOMID)) vmdef->id = 6; else vmdef->id = -1; memset(&monitor_chr, 0, sizeof(monitor_chr)); monitor_chr.type = VIR_DOMAIN_CHR_TYPE_UNIX; monitor_chr.data.nix.path = (char *)"/tmp/test-monitor"; monitor_chr.data.nix.listen = true; virQEMUCapsSetList(extraFlags, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, QEMU_CAPS_NO_ACPI, QEMU_CAPS_LAST); if (STREQ(vmdef->os.machine, "pc") && STREQ(vmdef->emulator, "/usr/bin/qemu-system-x86_64")) { VIR_FREE(vmdef->os.machine); if (VIR_STRDUP(vmdef->os.machine, "pc-0.11") < 0) goto out; } if (virQEMUCapsGet(extraFlags, QEMU_CAPS_DEVICE)) { if (qemuDomainAssignAddresses(vmdef, extraFlags, NULL)) { if (flags & FLAG_EXPECT_ERROR) goto ok; goto out; } } log = virtTestLogContentAndReset(); VIR_FREE(log); virResetLastError(); if (vmdef->os.arch == VIR_ARCH_X86_64 || vmdef->os.arch == VIR_ARCH_I686) { virQEMUCapsSet(extraFlags, QEMU_CAPS_PCI_MULTIBUS); } if (qemuAssignDeviceAliases(vmdef, extraFlags) < 0) goto out; if (!(cmd = qemuBuildCommandLine(conn, &driver, vmdef, &monitor_chr, (flags & FLAG_JSON), extraFlags, migrateFrom, migrateFd, NULL, VIR_NETDEV_VPORT_PROFILE_OP_NO_OP, &testCallbacks))) { if (flags & FLAG_EXPECT_FAILURE) { ret = 0; if (virTestGetDebug() > 1) fprintf(stderr, "Got expected error: %s\n", virGetLastErrorMessage()); virResetLastError(); } goto out; } else if (flags & FLAG_EXPECT_FAILURE) { if (virTestGetDebug()) fprintf(stderr, "qemuBuildCommandLine should have failed\n"); goto out; } if (!!virGetLastError() != !!(flags & FLAG_EXPECT_ERROR)) { if (virTestGetDebug() && (log = virtTestLogContentAndReset())) fprintf(stderr, "\n%s", log); goto out; } if (!(actualargv = virCommandToString(cmd))) goto out; len = virtTestLoadFile(cmdline, &expectargv); if (len < 0) goto out; if (len && expectargv[len - 1] == '\n') expectargv[len - 1] = '\0'; if (STRNEQ(expectargv, actualargv)) { virtTestDifference(stderr, expectargv, actualargv); goto out; } ok: if (flags & FLAG_EXPECT_ERROR) { /* need to suppress the errors */ virResetLastError(); } ret = 0; out: VIR_FREE(log); VIR_FREE(expectargv); VIR_FREE(actualargv); virCommandFree(cmd); virDomainDefFree(vmdef); virObjectUnref(conn); return ret; }
static virDrvOpenStatus vmwareOpen(virConnectPtr conn, virConnectAuthPtr auth ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED) { struct vmware_driver *driver; char * vmrun = NULL; if (conn->uri == NULL) { /* @TODO accept */ return VIR_DRV_OPEN_DECLINED; } else { if (conn->uri->scheme == NULL || (STRNEQ(conn->uri->scheme, "vmwareplayer") && STRNEQ(conn->uri->scheme, "vmwarews"))) return VIR_DRV_OPEN_DECLINED; /* If server name is given, its for remote driver */ if (conn->uri->server != NULL) return VIR_DRV_OPEN_DECLINED; /* If path isn't /session, then they typoed, so tell them correct path */ if (conn->uri->path == NULL || STRNEQ(conn->uri->path, "/session")) { vmwareError(VIR_ERR_INTERNAL_ERROR, _("unexpected VMware URI path '%s', try vmwareplayer:///session or vmwarews:///session"), NULLSTR(conn->uri->path)); return VIR_DRV_OPEN_ERROR; } } /* We now know the URI is definitely for this driver, so beyond * here, don't return DECLINED, always use ERROR */ vmrun = virFindFileInPath(VMRUN); if (vmrun == NULL) { vmwareError(VIR_ERR_INTERNAL_ERROR, _("%s utility is missing"), VMRUN); return VIR_DRV_OPEN_ERROR; } else { VIR_FREE(vmrun); } if (VIR_ALLOC(driver) < 0) { virReportOOMError(); return VIR_DRV_OPEN_ERROR; } if (virMutexInit(&driver->lock) < 0) goto cleanup; driver->type = STRNEQ(conn->uri->scheme, "vmwareplayer") ? TYPE_WORKSTATION : TYPE_PLAYER; if (virDomainObjListInit(&driver->domains) < 0) goto cleanup; if (!(driver->caps = vmwareCapsInit())) goto cleanup; driver->caps->privateDataAllocFunc = vmwareDataAllocFunc; driver->caps->privateDataFreeFunc = vmwareDataFreeFunc; if (vmwareLoadDomains(driver) < 0) goto cleanup; if (vmwareExtractVersion(driver) < 0) goto cleanup; conn->privateData = driver; return VIR_DRV_OPEN_SUCCESS; cleanup: vmwareFreeDriver(driver); return VIR_DRV_OPEN_ERROR; };
static int SELinuxGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, virDomainDefPtr def) { int rc = -1; char *mcs = NULL; char *scontext = NULL; int c1 = 0; int c2 = 0; context_t ctx = NULL; const char *range; if ((def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) && !def->seclabel.baselabel && def->seclabel.model) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("security model already defined for VM")); return rc; } if (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC && def->seclabel.label) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("security label already defined for VM")); return rc; } if (def->seclabel.imagelabel) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("security image label already defined for VM")); return rc; } if (def->seclabel.model && STRNEQ(def->seclabel.model, SECURITY_SELINUX_NAME)) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, _("security label model %s is not supported with selinux"), def->seclabel.model); return rc; } switch (def->seclabel.type) { case VIR_DOMAIN_SECLABEL_STATIC: if (!(ctx = context_new(def->seclabel.label)) ) { virReportSystemError(errno, _("unable to allocate socket security context '%s'"), def->seclabel.label); return rc; } range = context_range_get(ctx); if (!range || !(mcs = strdup(range))) { virReportOOMError(); goto cleanup; } break; case VIR_DOMAIN_SECLABEL_DYNAMIC: do { c1 = virRandomBits(10); c2 = virRandomBits(10); if ( c1 == c2 ) { if (virAsprintf(&mcs, "s0:c%d", c1) < 0) { virReportOOMError(); goto cleanup; } } else { if (c1 > c2) { c1 ^= c2; c2 ^= c1; c1 ^= c2; } if (virAsprintf(&mcs, "s0:c%d,c%d", c1, c2) < 0) { virReportOOMError(); goto cleanup; } } } while (mcsAdd(mcs) == -1); def->seclabel.label = SELinuxGenNewContext(def->seclabel.baselabel ? def->seclabel.baselabel : default_domain_context, mcs); if (! def->seclabel.label) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, _("cannot generate selinux context for %s"), mcs); goto cleanup; } break; case VIR_DOMAIN_SECLABEL_NONE: /* no op */ break; default: virSecurityReportError(VIR_ERR_INTERNAL_ERROR, _("unexpected security label type '%s'"), virDomainSeclabelTypeToString(def->seclabel.type)); goto cleanup; } if (!def->seclabel.norelabel) { def->seclabel.imagelabel = SELinuxGenNewContext(default_image_context, mcs); if (!def->seclabel.imagelabel) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, _("cannot generate selinux context for %s"), mcs); goto cleanup; } } if (!def->seclabel.model && !(def->seclabel.model = strdup(SECURITY_SELINUX_NAME))) { virReportOOMError(); goto cleanup; } rc = 0; cleanup: if (rc != 0) { if (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) VIR_FREE(def->seclabel.label); VIR_FREE(def->seclabel.imagelabel); if (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC && !def->seclabel.baselabel) VIR_FREE(def->seclabel.model); } if (ctx) context_free(ctx); VIR_FREE(scontext); VIR_FREE(mcs); VIR_DEBUG("model=%s label=%s imagelabel=%s baselabel=%s", NULLSTR(def->seclabel.model), NULLSTR(def->seclabel.label), NULLSTR(def->seclabel.imagelabel), NULLSTR(def->seclabel.baselabel)); return rc; }
static virDrvOpenStatus openvzOpen(virConnectPtr conn, virConnectAuthPtr auth ATTRIBUTE_UNUSED, unsigned int flags) { struct openvz_driver *driver; virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR); if (conn->uri == NULL) { if (!virFileExists("/proc/vz")) return VIR_DRV_OPEN_DECLINED; if (access("/proc/vz", W_OK) < 0) return VIR_DRV_OPEN_DECLINED; if (!(conn->uri = virURIParse("openvz:///system"))) return VIR_DRV_OPEN_ERROR; } else { /* If scheme isn't 'openvz', then its for another driver */ if (conn->uri->scheme == NULL || STRNEQ (conn->uri->scheme, "openvz")) return VIR_DRV_OPEN_DECLINED; /* If server name is given, its for remote driver */ if (conn->uri->server != NULL) return VIR_DRV_OPEN_DECLINED; /* If path isn't /system, then they typoed, so tell them correct path */ if (conn->uri->path == NULL || STRNEQ (conn->uri->path, "/system")) { openvzError(VIR_ERR_INTERNAL_ERROR, _("unexpected OpenVZ URI path '%s', try openvz:///system"), conn->uri->path); return VIR_DRV_OPEN_ERROR; } if (!virFileExists("/proc/vz")) { openvzError(VIR_ERR_INTERNAL_ERROR, "%s", _("OpenVZ control file /proc/vz does not exist")); return VIR_DRV_OPEN_ERROR; } if (access("/proc/vz", W_OK) < 0) { openvzError(VIR_ERR_INTERNAL_ERROR, "%s", _("OpenVZ control file /proc/vz is not accessible")); return VIR_DRV_OPEN_ERROR; } } /* We now know the URI is definitely for this driver, so beyond * here, don't return DECLINED, always use ERROR */ if (VIR_ALLOC(driver) < 0) { virReportOOMError(); return VIR_DRV_OPEN_ERROR; } if (virDomainObjListInit(&driver->domains) < 0) goto cleanup; if (!(driver->caps = openvzCapsInit())) goto cleanup; if (openvzLoadDomains(driver) < 0) goto cleanup; if (openvzExtractVersion(driver) < 0) goto cleanup; conn->privateData = driver; return VIR_DRV_OPEN_SUCCESS; cleanup: openvzFreeDriver(driver); return VIR_DRV_OPEN_ERROR; };
static bool testSELinuxCheckCon(context_t con, const char *user, const char *role, const char *type, int sensMin, int sensMax ATTRIBUTE_UNUSED, int catMin, int catMax) { const char *range; char *tmp; int gotSens; int gotCatOne; int gotCatTwo; if (STRNEQ(context_user_get(con), user)) { fprintf(stderr, "Expect user %s got %s\n", user, context_user_get(con)); return false; } if (STRNEQ(context_role_get(con), role)) { fprintf(stderr, "Expect role %s got %s\n", role, context_role_get(con)); return false; } if (STRNEQ(context_type_get(con), type)) { fprintf(stderr, "Expect type %s got %s\n", type, context_type_get(con)); return false; } range = context_range_get(con); if (range[0] != 's') { fprintf(stderr, "Malformed range %s, cannot find sensitivity\n", range); return false; } if (virStrToLong_i(range + 1, &tmp, 10, &gotSens) < 0 || !tmp) { fprintf(stderr, "Malformed range %s, cannot parse sensitivity\n", range + 1); return false; } if (*tmp != ':') { fprintf(stderr, "Malformed range %s, too many sensitivity values\n", tmp); return false; } tmp++; if (*tmp != 'c') { fprintf(stderr, "Malformed range %s, cannot find first category\n", tmp); return false; } tmp++; if (virStrToLong_i(tmp, &tmp, 10, &gotCatOne) < 0) { fprintf(stderr, "Malformed range %s, cannot parse category one\n", tmp); return false; } if (tmp && *tmp == ',') tmp++; if (tmp && *tmp == 'c') { tmp++; if (virStrToLong_i(tmp, &tmp, 10, &gotCatTwo) < 0) { fprintf(stderr, "Malformed range %s, cannot parse category two\n", tmp); return false; } if (*tmp != '\0') { fprintf(stderr, "Malformed range %s, junk after second category\n", tmp); return false; } if (gotCatOne == gotCatTwo) { fprintf(stderr, "Saw category pair %d,%d where cats were equal\n", gotCatOne, gotCatTwo); return false; } } else { gotCatTwo = gotCatOne; } if (gotSens != sensMin) { fprintf(stderr, "Sensitivity %d is not equal to min %d\n", gotSens, sensMin); return false; } if (gotCatOne < catMin || gotCatOne > catMax) { fprintf(stderr, "Category one %d is out of range %d-%d\n", gotCatTwo, catMin, catMax); return false; } if (gotCatTwo < catMin || gotCatTwo > catMax) { fprintf(stderr, "Category two %d is out of range %d-%d\n", gotCatTwo, catMin, catMax); return false; } if (gotCatOne > gotCatTwo) { fprintf(stderr, "Category one %d is greater than category two %d\n", gotCatOne, gotCatTwo); return false; } return true; }
/* Build supermin appliance from supermin_path to $TMPDIR/.guestfs-$UID. * * Returns: * 0 = built * -1 = error (aborts launch) */ static int build_supermin_appliance (guestfs_h *g, const char *supermin_path, uid_t uid, char **kernel, char **initrd, char **appliance) { CLEANUP_FREE char *tmpdir = guestfs_get_cachedir (g); struct stat statbuf; size_t len; /* len must be longer than the length of any pathname we can * generate in this function. */ len = strlen (tmpdir) + 128; char cachedir[len]; snprintf (cachedir, len, "%s/.guestfs-%ju", tmpdir, (uintmax_t) uid); char lockfile[len]; snprintf (lockfile, len, "%s/lock", cachedir); char appliancedir[len]; snprintf (appliancedir, len, "%s/appliance.d", cachedir); ignore_value (mkdir (cachedir, 0755)); ignore_value (chmod (cachedir, 0755)); /* RHBZ#921292 */ /* See if the cache directory exists and passes some simple checks * to make sure it has not been tampered with. */ if (lstat (cachedir, &statbuf) == -1) return 0; if (statbuf.st_uid != uid) { error (g, _("security: cached appliance %s is not owned by UID %ju"), cachedir, (uintmax_t) uid); return -1; } if (!S_ISDIR (statbuf.st_mode)) { error (g, _("security: cached appliance %s is not a directory (mode %o)"), cachedir, statbuf.st_mode); return -1; } if ((statbuf.st_mode & 0022) != 0) { error (g, _("security: cached appliance %s is writable by group or other (mode %o)"), cachedir, statbuf.st_mode); return -1; } (void) utimes (cachedir, NULL); if (g->verbose) guestfs_int_print_timestamped_message (g, "begin building supermin appliance"); /* Build the appliance if it needs to be built. */ if (g->verbose) guestfs_int_print_timestamped_message (g, "run supermin"); if (run_supermin_build (g, lockfile, appliancedir, supermin_path) == -1) return -1; if (g->verbose) guestfs_int_print_timestamped_message (g, "finished building supermin appliance"); /* Return the appliance filenames. */ *kernel = safe_malloc (g, len); *initrd = safe_malloc (g, len); *appliance = safe_malloc (g, len); snprintf (*kernel, len, "%s/kernel", appliancedir); snprintf (*initrd, len, "%s/initrd", appliancedir); snprintf (*appliance, len, "%s/root", appliancedir); /* Touch the files so they don't get deleted (as they are in /var/tmp). */ (void) utimes (*kernel, NULL); (void) utimes (*initrd, NULL); /* Checking backend != "uml" is a big hack. UML encodes the mtime * of the original backing file (in this case, the appliance) in the * COW file, and checks it when adding it to the VM. If there are * multiple threads running and one touches the appliance here, it * will disturb the mtime and UML will give an error. * * We can get rid of this hack as soon as UML fixes the * ubdN=cow,original parsing bug, since we won't need to run * uml_mkcow separately, so there is no possible race. * * XXX */ if (STRNEQ (g->backend, "uml")) (void) utimes (*appliance, NULL); return 0; }
int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg, const char *filename) { virConfPtr conf = NULL; virConfValuePtr p; int ret = -1; size_t i; /* Just check the file is readable before opening it, otherwise * libvirt emits an error. */ if (access(filename, R_OK) == -1) { VIR_INFO("Could not read qemu config file %s", filename); return 0; } if (!(conf = virConfReadFile(filename, 0))) goto cleanup; #define CHECK_TYPE(name, typ) \ if (p && p->type != (typ)) { \ virReportError(VIR_ERR_INTERNAL_ERROR, \ "%s: %s: expected type " #typ, \ filename, (name)); \ goto cleanup; \ } #define CHECK_TYPE_ALT(name, type1, type2) \ if (p && (p->type != (type1) && p->type != (type2))) { \ virReportError(VIR_ERR_INTERNAL_ERROR, \ "%s: %s: expected type " #type1, \ filename, (name)); \ goto cleanup; \ } #define GET_VALUE_LONG(NAME, VAR) \ p = virConfGetValue(conf, NAME); \ CHECK_TYPE_ALT(NAME, VIR_CONF_LONG, VIR_CONF_ULONG); \ if (p) \ VAR = p->l; #define GET_VALUE_ULONG(NAME, VAR) \ p = virConfGetValue(conf, NAME); \ CHECK_TYPE(NAME, VIR_CONF_ULONG); \ if (p) \ VAR = p->l; #define GET_VALUE_BOOL(NAME, VAR) \ p = virConfGetValue(conf, NAME); \ CHECK_TYPE(NAME, VIR_CONF_ULONG); \ if (p) \ VAR = p->l != 0; #define GET_VALUE_STR(NAME, VAR) \ p = virConfGetValue(conf, NAME); \ CHECK_TYPE(NAME, VIR_CONF_STRING); \ if (p && p->str) { \ VIR_FREE(VAR); \ if (VIR_STRDUP(VAR, p->str) < 0) \ goto cleanup; \ } GET_VALUE_BOOL("vnc_auto_unix_socket", cfg->vncAutoUnixSocket); GET_VALUE_BOOL("vnc_tls", cfg->vncTLS); GET_VALUE_BOOL("vnc_tls_x509_verify", cfg->vncTLSx509verify); GET_VALUE_STR("vnc_tls_x509_cert_dir", cfg->vncTLSx509certdir); GET_VALUE_STR("vnc_listen", cfg->vncListen); GET_VALUE_STR("vnc_password", cfg->vncPassword); GET_VALUE_BOOL("vnc_sasl", cfg->vncSASL); GET_VALUE_STR("vnc_sasl_dir", cfg->vncSASLdir); GET_VALUE_BOOL("vnc_allow_host_audio", cfg->vncAllowHostAudio); GET_VALUE_BOOL("nographics_allow_host_audio", cfg->nogfxAllowHostAudio); p = virConfGetValue(conf, "security_driver"); if (p && p->type == VIR_CONF_LIST) { size_t len, j; virConfValuePtr pp; /* Calc length and check items */ for (len = 0, pp = p->list; pp; len++, pp = pp->next) { if (pp->type != VIR_CONF_STRING) { virReportError(VIR_ERR_CONF_SYNTAX, "%s", _("security_driver must be a list of strings")); goto cleanup; } } if (VIR_ALLOC_N(cfg->securityDriverNames, len + 1) < 0) goto cleanup; for (i = 0, pp = p->list; pp; i++, pp = pp->next) { for (j = 0; j < i; j++) { if (STREQ(pp->str, cfg->securityDriverNames[j])) { virReportError(VIR_ERR_CONF_SYNTAX, _("Duplicate security driver %s"), pp->str); goto cleanup; } } if (VIR_STRDUP(cfg->securityDriverNames[i], pp->str) < 0) goto cleanup; } cfg->securityDriverNames[len] = NULL; } else { CHECK_TYPE("security_driver", VIR_CONF_STRING); if (p && p->str) { if (VIR_ALLOC_N(cfg->securityDriverNames, 2) < 0) goto cleanup; if (VIR_STRDUP(cfg->securityDriverNames[0], p->str) < 0) goto cleanup; cfg->securityDriverNames[1] = NULL; } } GET_VALUE_BOOL("security_default_confined", cfg->securityDefaultConfined); GET_VALUE_BOOL("security_require_confined", cfg->securityRequireConfined); GET_VALUE_BOOL("spice_tls", cfg->spiceTLS); GET_VALUE_STR("spice_tls_x509_cert_dir", cfg->spiceTLSx509certdir); GET_VALUE_BOOL("spice_sasl", cfg->spiceSASL); GET_VALUE_STR("spice_sasl_dir", cfg->spiceSASLdir); GET_VALUE_STR("spice_listen", cfg->spiceListen); GET_VALUE_STR("spice_password", cfg->spicePassword); GET_VALUE_ULONG("remote_websocket_port_min", cfg->webSocketPortMin); if (cfg->webSocketPortMin < QEMU_WEBSOCKET_PORT_MIN) { /* if the port is too low, we can't get the display name * to tell to vnc (usually subtract 5700, e.g. localhost:1 * for port 5701) */ virReportError(VIR_ERR_INTERNAL_ERROR, _("%s: remote_websocket_port_min: port must be greater " "than or equal to %d"), filename, QEMU_WEBSOCKET_PORT_MIN); goto cleanup; } GET_VALUE_ULONG("remote_websocket_port_max", cfg->webSocketPortMax); if (cfg->webSocketPortMax > QEMU_WEBSOCKET_PORT_MAX || cfg->webSocketPortMax < cfg->webSocketPortMin) { virReportError(VIR_ERR_INTERNAL_ERROR, _("%s: remote_websocket_port_max: port must be between " "the minimal port and %d"), filename, QEMU_WEBSOCKET_PORT_MAX); goto cleanup; } if (cfg->webSocketPortMin > cfg->webSocketPortMax) { virReportError(VIR_ERR_INTERNAL_ERROR, _("%s: remote_websocket_port_min: min port must not be " "greater than max port"), filename); goto cleanup; } GET_VALUE_ULONG("remote_display_port_min", cfg->remotePortMin); if (cfg->remotePortMin < QEMU_REMOTE_PORT_MIN) { /* if the port is too low, we can't get the display name * to tell to vnc (usually subtract 5900, e.g. localhost:1 * for port 5901) */ virReportError(VIR_ERR_INTERNAL_ERROR, _("%s: remote_display_port_min: port must be greater " "than or equal to %d"), filename, QEMU_REMOTE_PORT_MIN); goto cleanup; } GET_VALUE_ULONG("remote_display_port_max", cfg->remotePortMax); if (cfg->remotePortMax > QEMU_REMOTE_PORT_MAX || cfg->remotePortMax < cfg->remotePortMin) { virReportError(VIR_ERR_INTERNAL_ERROR, _("%s: remote_display_port_max: port must be between " "the minimal port and %d"), filename, QEMU_REMOTE_PORT_MAX); goto cleanup; } if (cfg->remotePortMin > cfg->remotePortMax) { virReportError(VIR_ERR_INTERNAL_ERROR, _("%s: remote_display_port_min: min port must not be " "greater than max port"), filename); goto cleanup; } GET_VALUE_ULONG("migration_port_min", cfg->migrationPortMin); if (cfg->migrationPortMin <= 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("%s: migration_port_min: port must be greater than 0"), filename); goto cleanup; } GET_VALUE_ULONG("migration_port_max", cfg->migrationPortMax); if (cfg->migrationPortMax > 65535 || cfg->migrationPortMax < cfg->migrationPortMin) { virReportError(VIR_ERR_INTERNAL_ERROR, _("%s: migration_port_max: port must be between " "the minimal port %d and 65535"), filename, cfg->migrationPortMin); goto cleanup; } p = virConfGetValue(conf, "user"); CHECK_TYPE("user", VIR_CONF_STRING); if (p && p->str && virGetUserID(p->str, &cfg->user) < 0) goto cleanup; p = virConfGetValue(conf, "group"); CHECK_TYPE("group", VIR_CONF_STRING); if (p && p->str && virGetGroupID(p->str, &cfg->group) < 0) goto cleanup; GET_VALUE_BOOL("dynamic_ownership", cfg->dynamicOwnership); p = virConfGetValue(conf, "cgroup_controllers"); CHECK_TYPE("cgroup_controllers", VIR_CONF_LIST); if (p) { cfg->cgroupControllers = 0; virConfValuePtr pp; for (i = 0, pp = p->list; pp; ++i, pp = pp->next) { int ctl; if (pp->type != VIR_CONF_STRING) { virReportError(VIR_ERR_CONF_SYNTAX, "%s", _("cgroup_controllers must be a " "list of strings")); goto cleanup; } if ((ctl = virCgroupControllerTypeFromString(pp->str)) < 0) { virReportError(VIR_ERR_CONF_SYNTAX, _("Unknown cgroup controller '%s'"), pp->str); goto cleanup; } cfg->cgroupControllers |= (1 << ctl); } } p = virConfGetValue(conf, "cgroup_device_acl"); CHECK_TYPE("cgroup_device_acl", VIR_CONF_LIST); if (p) { int len = 0; virConfValuePtr pp; for (pp = p->list; pp; pp = pp->next) len++; if (VIR_ALLOC_N(cfg->cgroupDeviceACL, 1+len) < 0) goto cleanup; for (i = 0, pp = p->list; pp; ++i, pp = pp->next) { if (pp->type != VIR_CONF_STRING) { virReportError(VIR_ERR_CONF_SYNTAX, "%s", _("cgroup_device_acl must be a " "list of strings")); goto cleanup; } if (VIR_STRDUP(cfg->cgroupDeviceACL[i], pp->str) < 0) goto cleanup; } cfg->cgroupDeviceACL[i] = NULL; } GET_VALUE_STR("save_image_format", cfg->saveImageFormat); GET_VALUE_STR("dump_image_format", cfg->dumpImageFormat); GET_VALUE_STR("snapshot_image_format", cfg->snapshotImageFormat); GET_VALUE_STR("auto_dump_path", cfg->autoDumpPath); GET_VALUE_BOOL("auto_dump_bypass_cache", cfg->autoDumpBypassCache); GET_VALUE_BOOL("auto_start_bypass_cache", cfg->autoStartBypassCache); /* Some crazy backcompat. Back in the old days, this was just a pure * string. We must continue supporting it. These days however, this may be * an array of strings. */ p = virConfGetValue(conf, "hugetlbfs_mount"); if (p) { /* There already might be something autodetected. Avoid leaking it. */ while (cfg->nhugetlbfs) { cfg->nhugetlbfs--; VIR_FREE(cfg->hugetlbfs[cfg->nhugetlbfs].mnt_dir); } VIR_FREE(cfg->hugetlbfs); if (p->type == VIR_CONF_LIST) { size_t len = 0; virConfValuePtr pp = p->list; /* Calc length and check items */ while (pp) { if (pp->type != VIR_CONF_STRING) { virReportError(VIR_ERR_CONF_SYNTAX, "%s", _("hugetlbfs_mount must be a list of strings")); goto cleanup; } len++; pp = pp->next; } if (len && VIR_ALLOC_N(cfg->hugetlbfs, len) < 0) goto cleanup; cfg->nhugetlbfs = len; pp = p->list; len = 0; while (pp) { if (virQEMUDriverConfigHugeTLBFSInit(&cfg->hugetlbfs[len], pp->str, !len) < 0) goto cleanup; len++; pp = pp->next; } } else { CHECK_TYPE("hugetlbfs_mount", VIR_CONF_STRING); if (STRNEQ(p->str, "")) { if (VIR_ALLOC_N(cfg->hugetlbfs, 1) < 0) goto cleanup; cfg->nhugetlbfs = 1; if (virQEMUDriverConfigHugeTLBFSInit(&cfg->hugetlbfs[0], p->str, true) < 0) goto cleanup; } } } GET_VALUE_STR("bridge_helper", cfg->bridgeHelperName); GET_VALUE_BOOL("mac_filter", cfg->macFilter); GET_VALUE_BOOL("relaxed_acs_check", cfg->relaxedACS); GET_VALUE_BOOL("clear_emulator_capabilities", cfg->clearEmulatorCapabilities); GET_VALUE_BOOL("allow_disk_format_probing", cfg->allowDiskFormatProbing); GET_VALUE_BOOL("set_process_name", cfg->setProcessName); GET_VALUE_ULONG("max_processes", cfg->maxProcesses); GET_VALUE_ULONG("max_files", cfg->maxFiles); GET_VALUE_STR("lock_manager", cfg->lockManagerName); GET_VALUE_ULONG("max_queued", cfg->maxQueuedJobs); GET_VALUE_LONG("keepalive_interval", cfg->keepAliveInterval); GET_VALUE_ULONG("keepalive_count", cfg->keepAliveCount); GET_VALUE_LONG("seccomp_sandbox", cfg->seccompSandbox); GET_VALUE_STR("migration_host", cfg->migrateHost); virStringStripIPv6Brackets(cfg->migrateHost); if (cfg->migrateHost && (STRPREFIX(cfg->migrateHost, "localhost") || virSocketAddrIsNumericLocalhost(cfg->migrateHost))) { virReportError(VIR_ERR_CONF_SYNTAX, _("migration_host must not be the address of" " the local machine: %s"), cfg->migrateHost); goto cleanup; } GET_VALUE_STR("migration_address", cfg->migrationAddress); virStringStripIPv6Brackets(cfg->migrationAddress); if (cfg->migrationAddress && (STRPREFIX(cfg->migrationAddress, "localhost") || virSocketAddrIsNumericLocalhost(cfg->migrationAddress))) { virReportError(VIR_ERR_CONF_SYNTAX, _("migration_address must not be the address of" " the local machine: %s"), cfg->migrationAddress); goto cleanup; } GET_VALUE_BOOL("log_timestamp", cfg->logTimestamp); if ((p = virConfGetValue(conf, "nvram"))) { size_t len; virConfValuePtr pp; CHECK_TYPE("nvram", VIR_CONF_LIST); while (cfg->nloader) { VIR_FREE(cfg->loader[cfg->nloader - 1]); VIR_FREE(cfg->nvram[cfg->nloader - 1]); cfg->nloader--; } VIR_FREE(cfg->loader); VIR_FREE(cfg->nvram); /* Calc length and check items */ for (len = 0, pp = p->list; pp; len++, pp = pp->next) { if (pp->type != VIR_CONF_STRING) { virReportError(VIR_ERR_CONF_SYNTAX, "%s", _("nvram must be a list of strings")); goto cleanup; } } if (len && (VIR_ALLOC_N(cfg->loader, len) < 0 || VIR_ALLOC_N(cfg->nvram, len) < 0)) goto cleanup; cfg->nloader = len; for (i = 0, pp = p->list; pp; i++, pp = pp->next) { if (virQEMUDriverConfigNVRAMParse(pp->str, &cfg->loader[i], &cfg->nvram[i]) < 0) goto cleanup; } } ret = 0; cleanup: virConfFree(conf); return ret; }
/* virNetDevVPortProfileMerge() - merge the attributes in mods into * orig. If anything that is set in mods has already been set in orig * *and doesn't match*, log an error and return -1, otherwise return 0. */ static int virNetDevVPortProfileMerge(virNetDevVPortProfilePtr orig, virNetDevVPortProfilePtr mods) { enum virNetDevVPortProfile otype; if (!orig || !mods) return 0; otype = orig->virtPortType; if (mods->virtPortType != VIR_NETDEV_VPORT_PROFILE_NONE) { if (otype != VIR_NETDEV_VPORT_PROFILE_NONE && otype != mods->virtPortType) { virReportError(VIR_ERR_XML_ERROR, _("attempt to merge virtualports " "with mismatched types (%s and %s)"), virNetDevVPortTypeToString(otype), virNetDevVPortTypeToString(mods->virtPortType)); return -1; } otype = orig->virtPortType = mods->virtPortType; } if (mods->managerID_specified && (otype == VIR_NETDEV_VPORT_PROFILE_8021QBG || otype == VIR_NETDEV_VPORT_PROFILE_NONE)) { if (orig->managerID_specified && (orig->managerID != mods->managerID)) { virReportError(VIR_ERR_XML_ERROR, _("attempt to merge virtualports " "with mismatched managerids (%d and %d)"), orig->managerID, mods->managerID); return -1; } orig->managerID = mods->managerID; orig->managerID_specified = true; } if (mods->typeID_specified && (otype == VIR_NETDEV_VPORT_PROFILE_8021QBG || otype == VIR_NETDEV_VPORT_PROFILE_NONE)) { if (orig->typeID_specified && (orig->typeID != mods->typeID)) { virReportError(VIR_ERR_XML_ERROR, _("attempt to merge virtualports " "with mismatched typeids (%d and %d)"), orig->typeID, mods->typeID); return -1; } orig->typeID = mods->typeID; orig->typeID_specified = true; } if (mods->typeIDVersion_specified && (otype == VIR_NETDEV_VPORT_PROFILE_8021QBG || otype == VIR_NETDEV_VPORT_PROFILE_NONE)) { if (orig->typeIDVersion_specified && (orig->typeIDVersion != mods->typeIDVersion)) { virReportError(VIR_ERR_XML_ERROR, _("attempt to merge virtualports with " "mismatched typeidversions (%d and %d)"), orig->typeIDVersion, mods->typeIDVersion); return -1; } orig->typeIDVersion = mods->typeIDVersion; orig->typeIDVersion_specified = true; } if (mods->instanceID_specified && (otype == VIR_NETDEV_VPORT_PROFILE_8021QBG || otype == VIR_NETDEV_VPORT_PROFILE_NONE)) { if (orig->instanceID_specified && memcmp(orig->instanceID, mods->instanceID, sizeof(orig->instanceID))) { char origuuid[VIR_UUID_STRING_BUFLEN]; char modsuuid[VIR_UUID_STRING_BUFLEN]; virReportError(VIR_ERR_XML_ERROR, _("attempt to merge virtualports with " "mismatched instanceids ('%s' and '%s')"), virUUIDFormat(orig->instanceID, origuuid), virUUIDFormat(mods->instanceID, modsuuid)); return -1; } memcpy(orig->instanceID, mods->instanceID, sizeof(orig->instanceID)); orig->instanceID_specified = true; } if (mods->interfaceID_specified && (otype == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH || otype == VIR_NETDEV_VPORT_PROFILE_NONE)) { if (orig->interfaceID_specified && memcmp(orig->interfaceID, mods->interfaceID, sizeof(orig->interfaceID))) { char origuuid[VIR_UUID_STRING_BUFLEN]; char modsuuid[VIR_UUID_STRING_BUFLEN]; virReportError(VIR_ERR_XML_ERROR, _("attempt to merge virtualports with " "mismatched interfaceids ('%s' and '%s')"), virUUIDFormat(orig->interfaceID, origuuid), virUUIDFormat(mods->interfaceID, modsuuid)); return -1; } memcpy(orig->interfaceID, mods->interfaceID, sizeof(orig->interfaceID)); orig->interfaceID_specified = true; } if (mods->profileID[0] && (otype == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH || otype == VIR_NETDEV_VPORT_PROFILE_8021QBH || otype == VIR_NETDEV_VPORT_PROFILE_NONE)) { if (orig->profileID[0] && STRNEQ(orig->profileID, mods->profileID)) { virReportError(VIR_ERR_XML_ERROR, _("attempt to merge virtualports with " "mismatched profileids ('%s' and '%s')"), orig->profileID, mods->profileID); return -1; } if (virStrcpyStatic(orig->profileID, mods->profileID) == NULL) { /* this should never happen - it indicates mods->profileID * isn't properly null terminated. */ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("corrupted profileid string")); return -1; } } return 0; }
static char * getSocketPath(const char *name) { char *rundir = virGetUserRuntimeDirectory(); char *sock_path = NULL; size_t i = 0; virURIPtr uri = NULL; if (name) { if (!(uri = virURIParse(name))) goto error; if (STRNEQ(uri->scheme, "admin") || uri->server || uri->user || uri->fragment) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Invalid connection name '%s'"), name); goto error; } for (i = 0; i < uri->paramsCount; i++) { virURIParamPtr param = &uri->params[i]; if (STREQ(param->name, "socket")) { VIR_FREE(sock_path); if (VIR_STRDUP(sock_path, param->value) < 0) goto error; } else { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unknown URI parameter '%s'"), param->name); goto error; } } } if (!sock_path) { if (!uri || !uri->path || STREQ(uri->path, "/system")) { if (VIR_STRDUP(sock_path, LIBVIRTD_ADMIN_UNIX_SOCKET) < 0) goto error; } else if (STREQ_NULLABLE(uri->path, "/session")) { if (!rundir) goto error; if (virAsprintf(&sock_path, "%s%s", rundir, LIBVIRTD_ADMIN_SOCK_NAME) < 0) goto error; } else { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Invalid URI path '%s'"), uri->path); goto error; } } cleanup: VIR_FREE(rundir); virURIFree(uri); return sock_path; error: VIR_FREE(sock_path); goto cleanup; }
static int parse (const char *arg, char **path_ret, char **protocol_ret, char ***server_ret, char **username_ret, char **password_ret) { CLEANUP_XMLFREEURI xmlURIPtr uri = NULL; CLEANUP_FREE char *socket = NULL; char *path; uri = xmlParseURI (arg); if (!uri) { fprintf (stderr, _("%s: --add: could not parse URI '%s'\n"), getprogname (), arg); return -1; } /* Note we don't do much checking of the parsed URI, since the * underlying function 'guestfs_add_drive_opts' will check for us. * So just the basics here. */ if (uri->scheme == NULL || STREQ (uri->scheme, "")) { /* Probably can never happen. */ fprintf (stderr, _("%s: %s: scheme of URI is NULL or empty\n"), getprogname (), arg); return -1; } socket = query_get (uri, "socket"); if (uri->server && STRNEQ (uri->server, "") && socket) { fprintf (stderr, _("%s: %s: cannot both a server name and a socket query parameter\n"), getprogname (), arg); return -1; } /* Is this needed? XXX if (socket && socket[0] != '/') { fprintf (stderr, _("%s: --add %s: socket query parameter must be an absolute path\n"), getprogname (), arg); return -1; } */ *protocol_ret = strdup (uri->scheme); if (*protocol_ret == NULL) { perror ("strdup: protocol"); return -1; } if (make_server (uri, socket, server_ret) == -1) { free (*protocol_ret); return -1; } *password_ret = NULL; *username_ret = NULL; if (uri->user && STRNEQ (uri->user, "")) { char *p = strchr (uri->user, ':'); if (p != NULL) { if (STRNEQ (p+1, "")) { *password_ret = strdup (p+1); if (*password_ret == NULL) { perror ("strdup: password"); free (*protocol_ret); guestfs_int_free_string_list (*server_ret); return -1; } } *p = '\0'; } *username_ret = strdup (uri->user); if (*username_ret == NULL) { perror ("strdup: username"); free (*password_ret); free (*protocol_ret); guestfs_int_free_string_list (*server_ret); return -1; } } /* We may have to adjust the path depending on the protocol. For * example ceph/rbd URIs look like rbd:///pool/disk, but the * exportname expected will be "pool/disk". Here, uri->path will be * "/pool/disk" so we have to knock off the leading '/' character. */ path = uri->path; if (path && path[0] == '/' && (STREQ (uri->scheme, "gluster") || STREQ (uri->scheme, "iscsi") || STREQ (uri->scheme, "rbd") || STREQ (uri->scheme, "sheepdog"))) path++; *path_ret = strdup (path ? path : ""); if (*path_ret == NULL) { perror ("strdup: path"); free (*protocol_ret); guestfs_int_free_string_list (*server_ret); free (*username_ret); free (*password_ret); return -1; } return 0; }
/* Remote control server. */ void rc_listen (void) { char sockpath[128]; pid_t pid; struct sockaddr_un addr; int sock, s; size_t i; FILE *fp; XDR xdr, xdr2; guestfish_hello hello; guestfish_call call; guestfish_reply reply; char **argv; size_t argc; memset (&hello, 0, sizeof hello); memset (&call, 0, sizeof call); pid = fork (); if (pid == -1) { perror ("fork"); exit (EXIT_FAILURE); } if (pid > 0) { /* Parent process. */ if (!remote_control_csh) printf ("GUESTFISH_PID=%d; export GUESTFISH_PID\n", pid); else printf ("setenv GUESTFISH_PID %d\n", pid); fflush (stdout); _exit (0); } /* Child process. * * Create the listening socket for accepting commands. * * Unfortunately there is a small but unavoidable race here. We * don't know the PID until after we've forked, so we cannot be * sure the socket is created from the point of view of the parent * (if the child is very slow). */ pid = getpid (); create_sockpath (pid, sockpath, sizeof sockpath, &addr); sock = socket (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); if (sock == -1) { perror ("socket"); exit (EXIT_FAILURE); } unlink (sockpath); if (bind (sock, (struct sockaddr *) &addr, sizeof addr) == -1) { perror (sockpath); exit (EXIT_FAILURE); } if (listen (sock, 4) == -1) { perror ("listen"); exit (EXIT_FAILURE); } /* Read commands and execute them. */ while (!quit) { /* Before waiting, close stdout and substitute /dev/null. This is * necessary so that eval `guestfish --listen` doesn't block * forever. */ close_stdout (); s = accept4 (sock, NULL, NULL, SOCK_CLOEXEC); if (s == -1) perror ("accept"); else { receive_stdout(s); fp = fdopen (s, "r+"); xdrstdio_create (&xdr, fp, XDR_DECODE); if (!xdr_guestfish_hello (&xdr, &hello)) { fprintf (stderr, _("guestfish: protocol error: could not read 'hello' message\n")); goto error; } if (STRNEQ (hello.vers, PACKAGE_VERSION)) { fprintf (stderr, _("guestfish: protocol error: version mismatch, server version '%s' does not match client version '%s'. The two versions must match exactly.\n"), PACKAGE_VERSION, hello.vers); xdr_free ((xdrproc_t) xdr_guestfish_hello, (char *) &hello); goto error; } xdr_free ((xdrproc_t) xdr_guestfish_hello, (char *) &hello); while (xdr_guestfish_call (&xdr, &call)) { /* We have to extend and NULL-terminate the argv array. */ argc = call.args.args_len; argv = realloc (call.args.args_val, (argc+1) * sizeof (char *)); if (argv == NULL) { perror ("realloc"); exit (EXIT_FAILURE); } call.args.args_val = argv; argv[argc] = NULL; if (verbose) { fprintf (stderr, "guestfish(%d): %s", pid, call.cmd); for (i = 0; i < argc; ++i) fprintf (stderr, " %s", argv[i]); fprintf (stderr, "\n"); } /* Run the command. */ reply.r = issue_command (call.cmd, argv, NULL, 0); xdr_free ((xdrproc_t) xdr_guestfish_call, (char *) &call); /* RHBZ#802389: If the command is quit, close the handle right * away. Note that the main while loop will exit preventing * 'g' from being reused. */ if (quit) { guestfs_close (g); g = NULL; } /* Send the reply. */ xdrstdio_create (&xdr2, fp, XDR_ENCODE); (void) xdr_guestfish_reply (&xdr2, &reply); xdr_destroy (&xdr2); /* Exit on error? */ if (call.exit_on_error && reply.r == -1) { unlink (sockpath); exit (EXIT_FAILURE); } } error: xdr_destroy (&xdr); /* NB. This doesn't close 'fp'. */ fclose (fp); /* Closes the underlying socket 's'. */ } } unlink (sockpath); close (sock); /* This returns to 'fish.c', where it jumps to global cleanups and exits. */ }
int main (int argc, char *argv[]) { guestfs_h *g; struct guestfs_internal_mountable *mountable; const char *devices[] = { "/dev/VG/LV", NULL }; const char *feature[] = { "btrfs", NULL }; g = guestfs_create (); if (g == NULL) { perror ("could not create handle"); exit (EXIT_FAILURE); } if (guestfs_add_drive_scratch (g, 1024*1024*1024, -1) == -1) { error: guestfs_close (g); exit (EXIT_FAILURE); } if (guestfs_launch (g) == -1) goto error; if (!guestfs_feature_available (g, (char **) feature)) { printf ("skipping test because btrfs is not available\n"); guestfs_close (g); exit (77); } if (!guestfs_filesystem_available (g, "btrfs")) { printf ("skipping test because btrfs filesystem is not available\n"); guestfs_close (g); exit (77); } if (guestfs_part_disk (g, "/dev/sda", "mbr") == -1) goto error; if (guestfs_pvcreate (g, "/dev/sda1") == -1) goto error; const char *pvs[] = { "/dev/sda1", NULL }; if (guestfs_vgcreate (g, "VG", (char **) pvs) == -1) goto error; if (guestfs_lvcreate (g, "LV", "VG", 900) == -1) goto error; if (guestfs_mkfs_btrfs (g, (char * const *)devices, -1) == -1) goto error; if (guestfs_mount (g, "/dev/VG/LV", "/") == -1) goto error; if (guestfs_btrfs_subvolume_create (g, "/sv") == -1) goto error; mountable = guestfs_internal_parse_mountable (g, "/dev/VG/LV"); if (mountable == NULL) goto error; if (mountable->im_type != MOUNTABLE_DEVICE || STRNEQ ("/dev/VG/LV", mountable->im_device)) { fprintf (stderr, "incorrectly parsed /dev/VG/LV: im_device=%s\n", mountable->im_device); goto error; } guestfs_free_internal_mountable (mountable); mountable = guestfs_internal_parse_mountable (g, "btrfsvol:/dev/VG/LV/sv"); if (mountable == NULL) goto error; if (mountable->im_type != MOUNTABLE_BTRFSVOL || STRNEQ ("/dev/VG/LV", mountable->im_device) || STRNEQ ("sv", mountable->im_volume)) { fprintf (stderr, "incorrectly parsed /dev/VG/LV/sv: im_device=%s, im_volume=%s\n", mountable->im_device, mountable->im_volume); goto error; } guestfs_free_internal_mountable (mountable); guestfs_close (g); exit (EXIT_SUCCESS); }
static virCPUDefPtr genericBaseline(virCPUDefPtr *cpus, unsigned int ncpus, const char **models, unsigned int nmodels) { virCPUDefPtr cpu = NULL; virCPUFeatureDefPtr features = NULL; unsigned int nfeatures; unsigned int count; unsigned int i, j; if (models) { bool found = false; for (i = 0; i < nmodels; i++) { if (STREQ(cpus[0]->model, models[i])) { found = true; break; } } if (!found) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, _("CPU model '%s' is not support by hypervisor"), cpus[0]->model); goto error; } } if (VIR_ALLOC(cpu) < 0 || !(cpu->arch = strdup(cpus[0]->arch)) || !(cpu->model = strdup(cpus[0]->model)) || VIR_ALLOC_N(features, cpus[0]->nfeatures) < 0) goto no_memory; cpu->type = VIR_CPU_TYPE_HOST; count = nfeatures = cpus[0]->nfeatures; for (i = 0; i < nfeatures; i++) features[i].name = cpus[0]->features[i].name; for (i = 1; i < ncpus; i++) { virHashTablePtr hash; if (STRNEQ(cpu->arch, cpus[i]->arch)) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, _("CPUs have incompatible architectures: '%s' != '%s'"), cpu->arch, cpus[i]->arch); goto error; } if (STRNEQ(cpu->model, cpus[i]->model)) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, _("CPU models don't match: '%s' != '%s'"), cpu->model, cpus[i]->model); goto error; } if (!(hash = genericHashFeatures(cpus[i]))) goto no_memory; for (j = 0; j < nfeatures; j++) { if (features[j].name && !virHashLookup(hash, features[j].name)) { features[j].name = NULL; count--; } } virHashFree(hash); } if (VIR_ALLOC_N(cpu->features, count) < 0) goto no_memory; cpu->nfeatures = count; j = 0; for (i = 0; i < nfeatures; i++) { if (!features[i].name) continue; if (!(cpu->features[j++].name = strdup(features[i].name))) goto no_memory; } cleanup: VIR_FREE(features); return cpu; no_memory: virReportOOMError(); error: virCPUDefFree(cpu); cpu = NULL; goto cleanup; }
/* Takes optional arguments, consult optargs_bitmask. */ int do_tune2fs (const char *device, /* only required parameter */ int force, int maxmountcount, int mountcount, const char *errorbehavior, int64_t group, int intervalbetweenchecks, int reservedblockspercentage, const char *lastmounteddirectory, int64_t reservedblockscount, int64_t user) { const char *argv[MAX_ARGS]; size_t i = 0; int r; CLEANUP_FREE char *err = NULL; char maxmountcount_s[64]; char mountcount_s[64]; char group_s[64]; char intervalbetweenchecks_s[64]; char reservedblockspercentage_s[64]; char reservedblockscount_s[64]; char user_s[64]; ADD_ARG (argv, i, str_tune2fs); if (optargs_bitmask & GUESTFS_TUNE2FS_FORCE_BITMASK) { if (force) ADD_ARG (argv, i, "-f"); } if (optargs_bitmask & GUESTFS_TUNE2FS_MAXMOUNTCOUNT_BITMASK) { if (maxmountcount < 0) { reply_with_error ("maxmountcount cannot be negative"); return -1; } ADD_ARG (argv, i, "-c"); snprintf (maxmountcount_s, sizeof maxmountcount_s, "%d", maxmountcount); ADD_ARG (argv, i, maxmountcount_s); } if (optargs_bitmask & GUESTFS_TUNE2FS_MOUNTCOUNT_BITMASK) { if (mountcount < 0) { reply_with_error ("mountcount cannot be negative"); return -1; } ADD_ARG (argv, i, "-C"); snprintf (mountcount_s, sizeof mountcount_s, "%d", mountcount); ADD_ARG (argv, i, mountcount_s); } if (optargs_bitmask & GUESTFS_TUNE2FS_ERRORBEHAVIOR_BITMASK) { if (STRNEQ (errorbehavior, "continue") && STRNEQ (errorbehavior, "remount-ro") && STRNEQ (errorbehavior, "panic")) { reply_with_error ("invalid errorbehavior parameter: %s", errorbehavior); return -1; } ADD_ARG (argv, i, "-e"); ADD_ARG (argv, i, errorbehavior); } if (optargs_bitmask & GUESTFS_TUNE2FS_GROUP_BITMASK) { if (group < 0) { reply_with_error ("group cannot be negative"); return -1; } ADD_ARG (argv, i, "-g"); snprintf (group_s, sizeof group_s, "%" PRIi64, group); ADD_ARG (argv, i, group_s); } if (optargs_bitmask & GUESTFS_TUNE2FS_INTERVALBETWEENCHECKS_BITMASK) { if (intervalbetweenchecks < 0) { reply_with_error ("intervalbetweenchecks cannot be negative"); return -1; } ADD_ARG (argv, i, "-i"); if (intervalbetweenchecks > 0) { /* -i <NN>s is not documented in the man page, but has been * supported in tune2fs for several years. */ snprintf (intervalbetweenchecks_s, sizeof intervalbetweenchecks_s, "%ds", intervalbetweenchecks); ADD_ARG (argv, i, intervalbetweenchecks_s); } else ADD_ARG (argv, i, "0"); } if (optargs_bitmask & GUESTFS_TUNE2FS_RESERVEDBLOCKSPERCENTAGE_BITMASK) { if (reservedblockspercentage < 0) { reply_with_error ("reservedblockspercentage cannot be negative"); return -1; } ADD_ARG (argv, i, "-m"); snprintf (reservedblockspercentage_s, sizeof reservedblockspercentage_s, "%d", reservedblockspercentage); ADD_ARG (argv, i, reservedblockspercentage_s); } if (optargs_bitmask & GUESTFS_TUNE2FS_LASTMOUNTEDDIRECTORY_BITMASK) { ADD_ARG (argv, i, "-M"); ADD_ARG (argv, i, lastmounteddirectory); } if (optargs_bitmask & GUESTFS_TUNE2FS_RESERVEDBLOCKSCOUNT_BITMASK) { if (reservedblockscount < 0) { reply_with_error ("reservedblockscount cannot be negative"); return -1; } ADD_ARG (argv, i, "-r"); snprintf (reservedblockscount_s, sizeof reservedblockscount_s, "%" PRIi64, reservedblockscount); ADD_ARG (argv, i, reservedblockscount_s); } if (optargs_bitmask & GUESTFS_TUNE2FS_USER_BITMASK) { if (user < 0) { reply_with_error ("user cannot be negative"); return -1; } ADD_ARG (argv, i, "-u"); snprintf (user_s, sizeof user_s, "%" PRIi64, user); ADD_ARG (argv, i, user_s); } ADD_ARG (argv, i, device); ADD_ARG (argv, i, NULL); r = commandv (NULL, &err, argv); if (r == -1) { reply_with_error ("%s: %s", device, err); return -1; } return 0; }
bool virCPUDefIsEqual(virCPUDefPtr src, virCPUDefPtr dst) { bool identical = false; int i; if (!src && !dst) return true; if ((src && !dst) || (!src && dst)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Target CPU does not match source")); goto cleanup; } if (src->type != dst->type) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target CPU type %s does not match source %s"), virCPUTypeToString(dst->type), virCPUTypeToString(src->type)); goto cleanup; } if (src->mode != dst->mode) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target CPU mode %s does not match source %s"), virCPUModeTypeToString(dst->mode), virCPUModeTypeToString(src->mode)); goto cleanup; } if (STRNEQ_NULLABLE(src->arch, dst->arch)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target CPU arch %s does not match source %s"), NULLSTR(dst->arch), NULLSTR(src->arch)); goto cleanup; } if (STRNEQ_NULLABLE(src->model, dst->model)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target CPU model %s does not match source %s"), NULLSTR(dst->model), NULLSTR(src->model)); goto cleanup; } if (STRNEQ_NULLABLE(src->vendor, dst->vendor)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target CPU vendor %s does not match source %s"), NULLSTR(dst->vendor), NULLSTR(src->vendor)); goto cleanup; } if (STRNEQ_NULLABLE(src->vendor_id, dst->vendor_id)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target CPU model %s does not match source %s"), NULLSTR(dst->vendor_id), NULLSTR(src->vendor_id)); goto cleanup; } if (src->sockets != dst->sockets) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target CPU sockets %d does not match source %d"), dst->sockets, src->sockets); goto cleanup; } if (src->cores != dst->cores) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target CPU cores %d does not match source %d"), dst->cores, src->cores); goto cleanup; } if (src->threads != dst->threads) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target CPU threads %d does not match source %d"), dst->threads, src->threads); goto cleanup; } if (src->nfeatures != dst->nfeatures) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target CPU feature count %zu does not match source %zu"), dst->nfeatures, src->nfeatures); goto cleanup; } for (i = 0 ; i < src->nfeatures ; i++) { if (STRNEQ(src->features[i].name, dst->features[i].name)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target CPU feature %s does not match source %s"), dst->features[i].name, src->features[i].name); goto cleanup; } if (src->features[i].policy != dst->features[i].policy) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target CPU feature policy %s does not match source %s"), virCPUFeaturePolicyTypeToString(dst->features[i].policy), virCPUFeaturePolicyTypeToString(src->features[i].policy)); goto cleanup; } } identical = true; cleanup: return identical; }
int openvzLoadDomains(struct openvz_driver *driver) { int veid, ret; char *status; char uuidstr[VIR_UUID_STRING_BUFLEN]; virDomainObjPtr dom = NULL; virDomainDefPtr def = NULL; char *temp = NULL; char *outbuf = NULL; char *line; virCommandPtr cmd = NULL; unsigned int vcpus = 0; if (openvzAssignUUIDs() < 0) return -1; cmd = virCommandNewArgList(VZLIST, "-a", "-ovpsid,status", "-H", NULL); virCommandSetOutputBuffer(cmd, &outbuf); if (virCommandRun(cmd, NULL) < 0) goto cleanup; line = outbuf; while (line[0] != '\0') { unsigned int flags = 0; if (virStrToLong_i(line, &status, 10, &veid) < 0 || *status++ != ' ' || (line = strchr(status, '\n')) == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Failed to parse vzlist output")); goto cleanup; } *line++ = '\0'; if (!(def = virDomainDefNew())) goto cleanup; def->virtType = VIR_DOMAIN_VIRT_OPENVZ; if (STREQ(status, "stopped")) def->id = -1; else def->id = veid; if (virAsprintf(&def->name, "%i", veid) < 0) goto cleanup; openvzGetVPSUUID(veid, uuidstr, sizeof(uuidstr)); ret = virUUIDParse(uuidstr, def->uuid); if (ret == -1) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("UUID in config file malformed")); goto cleanup; } def->os.type = VIR_DOMAIN_OSTYPE_EXE; if (VIR_STRDUP(def->os.init, "/sbin/init") < 0) goto cleanup; ret = openvzReadVPSConfigParam(veid, "CPUS", &temp); if (ret < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not read config for container %d"), veid); goto cleanup; } else if (ret > 0) { vcpus = strtoI(temp); } if (ret == 0 || vcpus == 0) vcpus = openvzGetNodeCPUs(); def->maxvcpus = vcpus; def->vcpus = vcpus; /* XXX load rest of VM config data .... */ openvzReadNetworkConf(def, veid); openvzReadFSConf(def, veid); openvzReadMemConf(def, veid); virUUIDFormat(def->uuid, uuidstr); flags = VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE; if (STRNEQ(status, "stopped")) flags |= VIR_DOMAIN_OBJ_LIST_ADD_LIVE; if (!(dom = virDomainObjListAdd(driver->domains, def, driver->xmlopt, flags, NULL))) goto cleanup; if (STREQ(status, "stopped")) { virDomainObjSetState(dom, VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_UNKNOWN); dom->pid = -1; } else { virDomainObjSetState(dom, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_UNKNOWN); dom->pid = veid; } /* XXX OpenVZ doesn't appear to have concept of a transient domain */ dom->persistent = 1; virObjectUnlock(dom); dom = NULL; def = NULL; } virCommandFree(cmd); VIR_FREE(temp); VIR_FREE(outbuf); return 0; cleanup: virCommandFree(cmd); VIR_FREE(temp); VIR_FREE(outbuf); virObjectUnref(dom); virDomainDefFree(def); return -1; }
static int testStorageChain(const void *args) { const struct testChainData *data = args; int ret = -1; virStorageFileMetadataPtr meta; virStorageFileMetadataPtr elt; size_t i = 0; meta = virStorageFileGetMetadata(data->start, data->format, -1, -1, (data->flags & ALLOW_PROBE) != 0); if (!meta) { if (data->flags & EXP_FAIL) { virResetLastError(); ret = 0; } goto cleanup; } else if (data->flags & EXP_FAIL) { fprintf(stderr, "call should have failed\n"); goto cleanup; } if (data->flags & EXP_WARN) { if (!virGetLastError()) { fprintf(stderr, "call should have warned\n"); goto cleanup; } virResetLastError(); } else if (virGetLastError()) { fprintf(stderr, "call should not have warned\n"); goto cleanup; } elt = meta; while (elt) { char *expect = NULL; char *actual = NULL; if (i == data->nfiles) { fprintf(stderr, "probed chain was too long\n"); goto cleanup; } if (virAsprintf(&expect, "store:%s\nraw:%s\ndirectory:%s\nother:%d %d %lld %d", NULLSTR(data->files[i]->expBackingStore), NULLSTR(data->files[i]->expBackingStoreRaw), NULLSTR(data->files[i]->expDirectory), data->files[i]->expFormat, data->files[i]->expIsFile, data->files[i]->expCapacity, data->files[i]->expEncrypted) < 0 || virAsprintf(&actual, "store:%s\nraw:%s\ndirectory:%s\nother:%d %d %lld %d", NULLSTR(elt->backingStore), NULLSTR(elt->backingStoreRaw), NULLSTR(elt->directory), elt->backingStoreFormat, elt->backingStoreIsFile, elt->capacity, !!elt->encryption) < 0) { VIR_FREE(expect); VIR_FREE(actual); goto cleanup; } if (STRNEQ(expect, actual)) { virtTestDifference(stderr, expect, actual); VIR_FREE(expect); VIR_FREE(actual); goto cleanup; } VIR_FREE(expect); VIR_FREE(actual); elt = elt->backingMeta; i++; } if (i != data->nfiles) { fprintf(stderr, "probed chain was too short\n"); goto cleanup; } ret = 0; cleanup: virStorageFileFreeMetadata(meta); return ret; }
static int virStorageBackendDiskMakeDataVol(virStoragePoolObjPtr pool, char **const groups, virStorageVolDefPtr vol) { char *tmp, *devpath; if (vol == NULL) { if (VIR_ALLOC(vol) < 0) { virReportOOMError(); return -1; } if (VIR_REALLOC_N(pool->volumes.objs, pool->volumes.count+1) < 0) { virReportOOMError(); virStorageVolDefFree(vol); return -1; } pool->volumes.objs[pool->volumes.count++] = vol; /* Prepended path will be same for all partitions, so we can * strip the path to form a reasonable pool-unique name */ tmp = strrchr(groups[0], '/'); if ((vol->name = strdup(tmp ? tmp + 1 : groups[0])) == NULL) { virReportOOMError(); return -1; } } if (vol->target.path == NULL) { if ((devpath = strdup(groups[0])) == NULL) { virReportOOMError(); return -1; } /* Now figure out the stable path * * XXX this method is O(N) because it scans the pool target * dir every time its run. Should figure out a more efficient * way of doing this... */ vol->target.path = virStorageBackendStablePath(pool, devpath, true); VIR_FREE(devpath); if (vol->target.path == NULL) return -1; } if (vol->key == NULL) { /* XXX base off a unique key of the underlying disk */ if ((vol->key = strdup(vol->target.path)) == NULL) { virReportOOMError(); return -1; } } if (vol->source.extents == NULL) { if (VIR_ALLOC(vol->source.extents) < 0) { virReportOOMError(); return -1; } vol->source.nextent = 1; if (virStrToLong_ull(groups[3], NULL, 10, &vol->source.extents[0].start) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot parse device start location")); return -1; } if (virStrToLong_ull(groups[4], NULL, 10, &vol->source.extents[0].end) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot parse device end location")); return -1; } if ((vol->source.extents[0].path = strdup(pool->def->source.devices[0].path)) == NULL) { virReportOOMError(); return -1; } } /* Refresh allocation/capacity/perms */ if (virStorageBackendUpdateVolInfo(vol, 1) < 0) return -1; /* set partition type */ if (STREQ(groups[1], "normal")) vol->target.type = VIR_STORAGE_VOL_DISK_TYPE_PRIMARY; else if (STREQ(groups[1], "logical")) vol->target.type = VIR_STORAGE_VOL_DISK_TYPE_LOGICAL; else if (STREQ(groups[1], "extended")) vol->target.type = VIR_STORAGE_VOL_DISK_TYPE_EXTENDED; else vol->target.type = VIR_STORAGE_VOL_DISK_TYPE_NONE; vol->type = VIR_STORAGE_VOL_BLOCK; /* The above gets allocation wrong for * extended partitions, so overwrite it */ vol->allocation = vol->capacity = (vol->source.extents[0].end - vol->source.extents[0].start); if (STRNEQ(groups[2], "metadata")) pool->def->allocation += vol->allocation; if (vol->source.extents[0].end > pool->def->capacity) pool->def->capacity = vol->source.extents[0].end; return 0; }
static int testCompareStatusXMLToXMLFiles(const void *opaque) { const struct testInfo *data = opaque; virBuffer buf = VIR_BUFFER_INITIALIZER; xmlDocPtr xml = NULL; virDomainObjPtr obj = NULL; char *expect = NULL; char *actual = NULL; char *source = NULL; int ret = -1; int keepBlanksDefault = xmlKeepBlanksDefault(0); /* construct faked source status XML */ virBufferAdd(&buf, testStatusXMLPrefix, -1); virBufferAdjustIndent(&buf, 2); virBufferAddStr(&buf, data->inFile); virBufferAdjustIndent(&buf, -2); virBufferAdd(&buf, testStatusXMLSuffix, -1); if (!(source = virBufferContentAndReset(&buf))) { fprintf(stderr, "Failed to create the source XML"); goto cleanup; } /* construct the expect string */ virBufferAdd(&buf, testStatusXMLPrefix, -1); virBufferAdjustIndent(&buf, 2); virBufferAddStr(&buf, data->outActiveFile); virBufferAdjustIndent(&buf, -2); virBufferAdd(&buf, testStatusXMLSuffix, -1); if (!(expect = virBufferContentAndReset(&buf))) { fprintf(stderr, "Failed to create the expect XML"); goto cleanup; } /* parse the fake source status XML */ if (!(xml = virXMLParseString(source, "(domain_status_test_XML)")) || !(obj = virDomainObjParseNode(xml, xmlDocGetRootElement(xml), driver.caps, driver.xmlopt, VIR_DOMAIN_DEF_PARSE_STATUS | VIR_DOMAIN_DEF_PARSE_ACTUAL_NET | VIR_DOMAIN_DEF_PARSE_PCI_ORIG_STATES | VIR_DOMAIN_DEF_PARSE_CLOCK_ADJUST))) { fprintf(stderr, "Failed to parse domain status XML:\n%s", source); goto cleanup; } /* format it back */ if (!(actual = virDomainObjFormat(driver.xmlopt, obj, VIR_DOMAIN_DEF_FORMAT_SECURE))) { fprintf(stderr, "Failed to format domain status XML"); goto cleanup; } if (STRNEQ(actual, expect)) { virtTestDifferenceFull(stderr, expect, data->outActiveName, actual, data->inName); goto cleanup; } ret = 0; cleanup: xmlKeepBlanksDefault(keepBlanksDefault); xmlFreeDoc(xml); virObjectUnref(obj); VIR_FREE(expect); VIR_FREE(actual); VIR_FREE(source); return ret; }
static int testCompareXMLToArgvFiles(const char *xml, const char *cmdfile, virQemuXML2ArgvTestFlags flags) { char *expectxml = NULL; char *actualxml = NULL; char *cmd = NULL; char *log = NULL; int ret = -1; virDomainDefPtr vmdef = NULL; if (virtTestLoadFile(cmdfile, &cmd) < 0) goto fail; if (virtTestLoadFile(xml, &expectxml) < 0) goto fail; if (!(vmdef = qemuParseCommandLineString(driver.caps, driver.xmlopt, cmd, NULL, NULL, NULL))) goto fail; if (!virtTestOOMActive()) { if ((log = virtTestLogContentAndReset()) == NULL) goto fail; if (flags & FLAG_EXPECT_WARNING) { if (*log) { VIR_TEST_DEBUG("Got expected warning from " "qemuParseCommandLineString:\n%s", log); } else { VIR_TEST_DEBUG("qemuParseCommandLineString " "should have logged a warning\n"); goto fail; } } else { /* didn't expect a warning */ if (*log) { VIR_TEST_DEBUG("Got unexpected warning from " "qemuParseCommandLineString:\n%s", log); goto fail; } } } if (!virDomainDefCheckABIStability(vmdef, vmdef)) { VIR_TEST_DEBUG("ABI stability check failed on %s", xml); goto fail; } if (!(actualxml = virDomainDefFormat(vmdef, driver.caps, 0))) goto fail; if (blankProblemElements(expectxml) < 0 || blankProblemElements(actualxml) < 0) goto fail; if (STRNEQ(expectxml, actualxml)) { virtTestDifference(stderr, expectxml, actualxml); goto fail; } ret = 0; fail: VIR_FREE(expectxml); VIR_FREE(actualxml); VIR_FREE(cmd); VIR_FREE(log); virDomainDefFree(vmdef); return ret; }
/* * The gdb target_xfer_memory() has a hook installed to re-route * all memory accesses back here; reads of 1 or 4 bytes come primarily * from text disassembly requests, and are diverted to the text cache. */ int gdb_readmem_callback(ulong addr, void *buf, int len, int write) { char locbuf[SIZEOF_32BIT], *p1; uint32_t *p2; int memtype; if (write) return FALSE; if (pc->cur_req->flags & GNU_NO_READMEM) return TRUE; if (pc->curcmd_flags & MEMTYPE_UVADDR) memtype = UVADDR; else if (pc->curcmd_flags & MEMTYPE_FILEADDR) memtype = FILEADDR; else if (!IS_KVADDR(addr)) { if (STREQ(pc->curcmd, "gdb") && STRNEQ(pc->cur_req->buf, "x/")) { memtype = UVADDR; } else { if (CRASHDEBUG(1)) console("gdb_readmem_callback: %lx %d FAILED\n", addr, len); return FALSE; } } else memtype = KVADDR; if (CRASHDEBUG(1)) console("gdb_readmem_callback[%d]: %lx %d\n", memtype, addr, len); if (memtype == FILEADDR) return(readmem(pc->curcmd_private, memtype, buf, len, "gdb_readmem_callback", RETURN_ON_ERROR)); switch (len) { case SIZEOF_8BIT: p1 = (char *)buf; if ((memtype == KVADDR) && text_value_cache_byte(addr, (unsigned char *)p1)) return TRUE; if (!readmem(addr, memtype, locbuf, SIZEOF_32BIT, "gdb_readmem_callback", RETURN_ON_ERROR)) return FALSE; *p1 = locbuf[0]; if (memtype == KVADDR) { p2 = (uint32_t *)locbuf; text_value_cache(addr, *p2, 0); } return TRUE; case SIZEOF_32BIT: if ((memtype == KVADDR) && text_value_cache(addr, 0, buf)) return TRUE; if (!readmem(addr, memtype, buf, SIZEOF_32BIT, "gdb_readmem callback", RETURN_ON_ERROR)) return FALSE; if (memtype == KVADDR) text_value_cache(addr, (uint32_t)*((uint32_t *)buf), NULL); return TRUE; } return(readmem(addr, memtype, buf, len, "gdb_readmem_callback", RETURN_ON_ERROR)); }
/** @brief Find the requested firmware in the specified FDD file. * */ FDD_STATIC boolean_t xiaFddFindFirmware(const char *filename, const char *ftype, double ptmin, double ptmax, unsigned int nother, char **others, const char *mode, FILE **fp, boolean_t *exact, char rawFilename[MAXFILENAME_LEN]) /* Returns TRUE_ if the file was found FALSE_ otherwise */ /* const char *filename; Input: name of the file that is the fdd */ /* const char *ftype; Input: firmware type to retrieve */ /* double ptmin; Input: min peaking time for this firmware */ /* double ptmax; Input: max peaking time for this firmware */ /* unsigned short nother; Input: number of elements in the array of other specifiers */ /* const char **others; Input: array of stings contianing firmware options */ /* const char *mode; Input: what mode to open the FDD file */ /* FILE **fp; Output: pointer to the file, if found */ /* boolean_t *exact; Output: was this an exact match to the types? */ { char newFile[MAXFILENAME_LEN]; char *cstatus = NULL; boolean_t found = FALSE_; int status; unsigned int i; unsigned int j; unsigned int nmatch; /* local variable used to decrement the number of type matches */ unsigned short nkey; /* Min and max ptime read from fdd */ double fddmin; double fddmax; ASSERT(filename != NULL); *fp = dxp_find_file(filename, mode, newFile); if (!*fp) { sprintf(info_string,"Error finding the FDD file: %s", filename); xiaFddLogError("xiaFddFindFirmware", info_string, XIA_OPEN_FILE); return FALSE_; } rewind(*fp); /* Skip past anything that doesn't equal the first section line. */ do { cstatus = fdd_md_fgets(line, XIA_LINE_LEN, *fp); } while (!STRNEQ(line, section)); /* Skip over the original filename entry */ cstatus = fdd_md_fgets(rawFilename, XIA_LINE_LEN, *fp); fdd__StringChomp(rawFilename); sprintf(info_string, "rawFilename = %s", rawFilename); xiaFddLogDebug("xiaFddFindFirmware", info_string); /* Located the FDD file, now start the search */ cstatus = fdd_md_fgets(line, XIA_LINE_LEN, *fp); while ((!found)&&(cstatus!=NULL)) { /* Second line contains the firmware type, strip off delimiters */ token = strtok(line, delim); if (STREQ(token, ftype)) { sprintf(info_string, "Matched token: '%s'", token); xiaFddLogDebug("xiaFddFindFirmware", info_string); /* Read in the number of keywords */ cstatus = fdd_md_fgets(line, XIA_LINE_LEN, *fp); nkey = (unsigned short) strtol(line, NULL, 10); /* Reset the number of matches */ nmatch = nother; for (i=0; i < nkey; i++) { /* Read in the keywords and check for matches */ cstatus = fdd_md_fgets(line, XIA_LINE_LEN, *fp); /* Strip off spaces and endline characters */ token = strtok(line, delim); for (j = 0; j < nother; j++) { if STREQ(token,others[j]) { nmatch--; break; } } if (nmatch==0) { found = TRUE_; if (nkey == nother) *exact = TRUE_; break; } } /* case of no other keywords */ if (nkey == 0) { found = TRUE_; *exact = TRUE_; } } else {