static int virNWFilterRuleDefToRuleInst(virNWFilterDefPtr def, virNWFilterRuleDefPtr rule, virNWFilterHashTablePtr vars, virNWFilterInstPtr inst) { virNWFilterRuleInstPtr ruleinst; int ret = -1; if (VIR_ALLOC(ruleinst) < 0) goto cleanup; ruleinst->chainSuffix = def->chainsuffix; ruleinst->chainPriority = def->chainPriority; ruleinst->def = rule; ruleinst->priority = rule->priority; if (!(ruleinst->vars = virNWFilterHashTableCreate(0))) goto cleanup; if (virNWFilterHashTablePutAll(vars, ruleinst->vars) < 0) goto cleanup; if (VIR_APPEND_ELEMENT(inst->rules, inst->nrules, ruleinst) < 0) goto cleanup; ruleinst = NULL; ret = 0; cleanup: virNWFilterRuleInstFree(ruleinst); return ret; }
static int xenParseXMInputDevs(virConfPtr conf, virDomainDefPtr def) { const char *str; if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) { if (xenConfigGetString(conf, "usbdevice", &str, NULL) < 0) return -1; if (str && (STREQ(str, "tablet") || STREQ(str, "mouse") || STREQ(str, "keyboard"))) { virDomainInputDefPtr input; if (VIR_ALLOC(input) < 0) return -1; input->bus = VIR_DOMAIN_INPUT_BUS_USB; if (STREQ(str, "mouse")) input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE; else if (STREQ(str, "tablet")) input->type = VIR_DOMAIN_INPUT_TYPE_TABLET; else if (STREQ(str, "keyboard")) input->type = VIR_DOMAIN_INPUT_TYPE_KBD; if (VIR_APPEND_ELEMENT(def->inputs, def->ninputs, input) < 0) { virDomainInputDefFree(input); return -1; } } } return 0; }
static int parallelsAddDiskVolume(virStoragePoolObjPtr pool, virDomainObjPtr dom, const char *diskName, const char *diskPath, const char *diskDescPath) { virStorageVolDefPtr def = NULL; if (VIR_ALLOC(def)) goto error; if (virAsprintf(&def->name, "%s-%s", dom->def->name, diskName) < 0) goto error; def->type = VIR_STORAGE_VOL_FILE; if (parallelsDiskDescParse(diskDescPath, def) < 0) goto error; if (!(def->target.path = realpath(diskPath, NULL))) goto no_memory; if (VIR_STRDUP(def->key, def->target.path) < 0) goto error; if (VIR_APPEND_ELEMENT(pool->volumes.objs, pool->volumes.count, def) < 0) goto error; return 0; no_memory: virReportOOMError(); error: virStorageVolDefFree(def); return -1; }
int virNetMessageAddFD(virNetMessagePtr msg, int fd) { int newfd = -1; if ((newfd = dup(fd)) < 0) { virReportSystemError(errno, _("Unable to duplicate FD %d"), fd); goto error; } if (virSetInherit(newfd, false) < 0) { virReportSystemError(errno, _("Cannot set close-on-exec %d"), newfd); goto error; } if (VIR_APPEND_ELEMENT(msg->fds, msg->nfds, newfd) < 0) goto error; return 0; error: VIR_FORCE_CLOSE(newfd); return -1; }
/** * virObjectEventQueuePush: * @evtQueue: the object event queue * @event: the event to add * * Internal function to push to the back of a virObjectEventQueue * * Returns: 0 on success, -1 on failure */ static int virObjectEventQueuePush(virObjectEventQueuePtr evtQueue, virObjectEventPtr event) { if (!evtQueue) return -1; if (VIR_APPEND_ELEMENT(evtQueue->events, evtQueue->count, event) < 0) return -1; return 0; }
static int xenParseXLInputDevs(virConfPtr conf, virDomainDefPtr def) { const char *str; virConfValuePtr val; if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) { val = virConfGetValue(conf, "usbdevice"); /* usbdevice can be defined as either a single string or a list */ if (val && val->type == VIR_CONF_LIST) { #ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST val = val->list; #else virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("multiple USB devices not supported")); return -1; #endif } /* otherwise val->next is NULL, so can be handled by the same code */ while (val) { if (val->type != VIR_CONF_STRING) { virReportError(VIR_ERR_INTERNAL_ERROR, _("config value %s was malformed"), "usbdevice"); return -1; } str = val->str; if (str && (STREQ(str, "tablet") || STREQ(str, "mouse") || STREQ(str, "keyboard"))) { virDomainInputDefPtr input; if (VIR_ALLOC(input) < 0) return -1; input->bus = VIR_DOMAIN_INPUT_BUS_USB; if (STREQ(str, "mouse")) input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE; else if (STREQ(str, "tablet")) input->type = VIR_DOMAIN_INPUT_TYPE_TABLET; else if (STREQ(str, "keyboard")) input->type = VIR_DOMAIN_INPUT_TYPE_KBD; if (VIR_APPEND_ELEMENT(def->inputs, def->ninputs, input) < 0) { virDomainInputDefFree(input); return -1; } } val = val->next; } } return 0; }
int virUSBDeviceListAdd(virUSBDeviceListPtr list, virUSBDevicePtr dev) { if (virUSBDeviceListFind(list, dev)) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Device %s is already in use"), dev->name); return -1; } return VIR_APPEND_ELEMENT(list->devs, list->count, dev); }
int virProcessGetPids(pid_t pid, size_t *npids, pid_t **pids) { int ret = -1; char *taskPath = NULL; DIR *dir = NULL; int value; struct dirent *ent; *npids = 0; *pids = NULL; if (virAsprintf(&taskPath, "/proc/%llu/task", (unsigned long long)pid) < 0) goto cleanup; if (!(dir = opendir(taskPath))) goto cleanup; while ((value = virDirRead(dir, &ent, taskPath)) > 0) { long long tmp; pid_t tmp_pid; /* Skip . and .. */ if (STRPREFIX(ent->d_name, ".")) continue; if (virStrToLong_ll(ent->d_name, NULL, 10, &tmp) < 0) goto cleanup; tmp_pid = tmp; if (VIR_APPEND_ELEMENT(*pids, *npids, tmp_pid) < 0) goto cleanup; } if (value < 0) goto cleanup; ret = 0; cleanup: if (dir) closedir(dir); VIR_FREE(taskPath); if (ret < 0) VIR_FREE(*pids); return ret; }
static int virISCSIGetTargets(char **const groups, void *data) { struct virISCSITargetList *list = data; char *target; if (VIR_STRDUP(target, groups[1]) < 0) return -1; if (VIR_APPEND_ELEMENT(list->targets, list->ntargets, target) < 0) { VIR_FREE(target); return -1; } return 0; }
static int virStorageBackendISCSIGetTargets(virStoragePoolObjPtr pool ATTRIBUTE_UNUSED, char **const groups, void *data) { struct virStorageBackendISCSITargetList *list = data; char *target; if (VIR_STRDUP(target, groups[1]) < 0) return -1; if (VIR_APPEND_ELEMENT(list->targets, list->ntargets, target) < 0) { VIR_FREE(target); return -1; } return 0; }
int virProcessGetPids(pid_t pid, size_t *npids, pid_t **pids) { int ret = -1; char *taskPath = NULL; DIR *dir = NULL; int value; struct dirent *ent; *npids = 0; *pids = NULL; if (virAsprintf(&taskPath, "/proc/%llu/task", (unsigned long long)pid) < 0) goto cleanup; if (virDirOpen(&dir, taskPath) < 0) goto cleanup; while ((value = virDirRead(dir, &ent, taskPath)) > 0) { long long tmp; pid_t tmp_pid; if (virStrToLong_ll(ent->d_name, NULL, 10, &tmp) < 0) goto cleanup; tmp_pid = tmp; if (VIR_APPEND_ELEMENT(*pids, *npids, tmp_pid) < 0) goto cleanup; } if (value < 0) goto cleanup; ret = 0; cleanup: VIR_DIR_CLOSE(dir); VIR_FREE(taskPath); if (ret < 0) VIR_FREE(*pids); return ret; }
int virSCSIDeviceSetUsedBy(virSCSIDevicePtr dev, const char *drvname, const char *domname) { virUsedByInfoPtr copy; if (VIR_ALLOC(copy) < 0) return -1; if (VIR_STRDUP(copy->drvname, drvname) < 0 || VIR_STRDUP(copy->domname, domname) < 0) goto cleanup; if (VIR_APPEND_ELEMENT(dev->used_by, dev->n_used_by, copy) < 0) goto cleanup; return 0; cleanup: virSCSIDeviceUsedByInfoFree(copy); return -1; }
static int lxcNetworkParseDataIPs(const char *name, virConfValuePtr value, lxcNetworkParseData *parseData) { int family = AF_INET; char **ipparts = NULL; virNetDevIPAddrPtr ip = NULL; if (VIR_ALLOC(ip) < 0) return -1; if (STREQ(name, "ipv6")) family = AF_INET6; ipparts = virStringSplit(value->str, "/", 2); if (virStringListLength((const char * const *)ipparts) != 2 || virSocketAddrParse(&ip->address, ipparts[0], family) < 0 || virStrToLong_ui(ipparts[1], NULL, 10, &ip->prefix) < 0) { virReportError(VIR_ERR_INVALID_ARG, _("Invalid CIDR address: '%s'"), value->str); virStringListFree(ipparts); VIR_FREE(ip); return -1; } virStringListFree(ipparts); if (VIR_APPEND_ELEMENT(parseData->ips, parseData->nips, ip) < 0) { VIR_FREE(ip); return -1; } return 0; }
static int lxcAddNetworkRouteDefinition(const char *address, int family, virNetworkRouteDefPtr **routes, size_t *nroutes) { virNetworkRouteDefPtr route = NULL; char *familyStr = NULL; char *zero = NULL; if (VIR_STRDUP(zero, family == AF_INET ? VIR_SOCKET_ADDR_IPV4_ALL : VIR_SOCKET_ADDR_IPV6_ALL) < 0) goto error; if (VIR_STRDUP(familyStr, family == AF_INET ? "ipv4" : "ipv6") < 0) goto error; if (!(route = virNetworkRouteDefCreate(_("Domain interface"), familyStr, zero, NULL, address, 0, false, 0, false))) goto error; if (VIR_APPEND_ELEMENT(*routes, *nroutes, route) < 0) goto error; VIR_FREE(familyStr); VIR_FREE(zero); return 0; error: VIR_FREE(familyStr); VIR_FREE(zero); virNetworkRouteDefFree(route); return -1; }
static int xenParseXLUSB(virConfPtr conf, virDomainDefPtr def) { virConfValuePtr list = virConfGetValue(conf, "usbdev"); virDomainHostdevDefPtr hostdev = NULL; if (list && list->type == VIR_CONF_LIST) { list = list->list; while (list) { char bus[3]; char device[3]; char *key; int busNum; int devNum; bus[0] = device[0] = '\0'; if ((list->type != VIR_CONF_STRING) || (list->str == NULL)) goto skipusb; /* usbdev=['hostbus=1,hostaddr=3'] */ key = list->str; while (key) { char *data; char *nextkey = strchr(key, ','); if (!(data = strchr(key, '='))) goto skipusb; data++; if (STRPREFIX(key, "hostbus=")) { int len = nextkey ? (nextkey - data) : sizeof(bus) - 1; if (virStrncpy(bus, data, len, sizeof(bus)) == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, _("bus %s too big for destination"), data); goto skipusb; } } else if (STRPREFIX(key, "hostaddr=")) { int len = nextkey ? (nextkey - data) : sizeof(device) - 1; if (virStrncpy(device, data, len, sizeof(device)) == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, _("device %s too big for destination"), data); goto skipusb; } } while (nextkey && (nextkey[0] == ',' || nextkey[0] == ' ' || nextkey[0] == '\t')) nextkey++; key = nextkey; } if (virStrToLong_i(bus, NULL, 16, &busNum) < 0) goto skipusb; if (virStrToLong_i(device, NULL, 16, &devNum) < 0) goto skipusb; if (!(hostdev = virDomainHostdevDefAlloc(NULL))) return -1; hostdev->managed = false; hostdev->source.subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB; hostdev->source.subsys.u.usb.bus = busNum; hostdev->source.subsys.u.usb.device = devNum; if (VIR_APPEND_ELEMENT(def->hostdevs, def->nhostdevs, hostdev) < 0) { virDomainHostdevDefFree(hostdev); return -1; } skipusb: list = list->next; } } return 0; }
/* * For details on xl disk config syntax, see * docs/misc/xl-disk-configuration.txt in the Xen sources. The important * section of text is: * * More formally, the string is a series of comma-separated keyword/value * pairs, flags and positional parameters. Parameters which are not bare * keywords and which do not contain "=" symbols are assigned to the * so-far-unspecified positional parameters, in the order below. The * positional parameters may also be specified explicitly by name. * * Each parameter may be specified at most once, either as a positional * parameter or a named parameter. Default values apply if the parameter * is not specified, or if it is specified with an empty value (whether * positionally or explicitly). * * Whitespace may appear before each parameter and will be ignored. * * The order of the positional parameters mentioned in the quoted text is: * * target,format,vdev,access * * The following options must be specified by key=value: * * devtype=<devtype> * backendtype=<backend-type> * * The following options are currently not supported: * * backend=<domain-name> * script=<script> * direct-io-safe * */ static int xenParseXLDisk(virConfPtr conf, virDomainDefPtr def) { int ret = -1; virConfValuePtr list = virConfGetValue(conf, "disk"); XLU_Config *xluconf; libxl_device_disk *libxldisk; virDomainDiskDefPtr disk = NULL; if (VIR_ALLOC(libxldisk) < 0) return -1; if (!(xluconf = xlu_cfg_init(stderr, "command line"))) goto cleanup; if (list && list->type == VIR_CONF_LIST) { list = list->list; while (list) { const char *disk_spec = list->str; if (list->type != VIR_CONF_STRING || list->str == NULL) goto skipdisk; libxl_device_disk_init(libxldisk); if (xlu_disk_parse(xluconf, 1, &disk_spec, libxldisk)) goto fail; if (!(disk = virDomainDiskDefNew(NULL))) goto fail; if (xenParseXLDiskSrc(disk, libxldisk->pdev_path) < 0) goto fail; if (VIR_STRDUP(disk->dst, libxldisk->vdev) < 0) goto fail; disk->src->readonly = !libxldisk->readwrite; disk->removable = libxldisk->removable; if (libxldisk->is_cdrom) { if (virDomainDiskSetDriver(disk, "qemu") < 0) goto fail; virDomainDiskSetType(disk, VIR_STORAGE_TYPE_FILE); disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM; if (!disk->src->path || STREQ(disk->src->path, "")) disk->src->format = VIR_STORAGE_FILE_NONE; else disk->src->format = VIR_STORAGE_FILE_RAW; } else { switch (libxldisk->format) { case LIBXL_DISK_FORMAT_QCOW: disk->src->format = VIR_STORAGE_FILE_QCOW; break; case LIBXL_DISK_FORMAT_QCOW2: disk->src->format = VIR_STORAGE_FILE_QCOW2; break; case LIBXL_DISK_FORMAT_VHD: disk->src->format = VIR_STORAGE_FILE_VHD; break; case LIBXL_DISK_FORMAT_RAW: case LIBXL_DISK_FORMAT_UNKNOWN: disk->src->format = VIR_STORAGE_FILE_RAW; break; case LIBXL_DISK_FORMAT_EMPTY: break; } switch (libxldisk->backend) { case LIBXL_DISK_BACKEND_QDISK: case LIBXL_DISK_BACKEND_UNKNOWN: if (virDomainDiskSetDriver(disk, "qemu") < 0) goto fail; if (virDomainDiskGetType(disk) == VIR_STORAGE_TYPE_NONE) virDomainDiskSetType(disk, VIR_STORAGE_TYPE_FILE); break; case LIBXL_DISK_BACKEND_TAP: if (virDomainDiskSetDriver(disk, "tap") < 0) goto fail; virDomainDiskSetType(disk, VIR_STORAGE_TYPE_FILE); break; case LIBXL_DISK_BACKEND_PHY: if (virDomainDiskSetDriver(disk, "phy") < 0) goto fail; virDomainDiskSetType(disk, VIR_STORAGE_TYPE_BLOCK); break; } } if (STRPREFIX(libxldisk->vdev, "xvd") || def->os.type != VIR_DOMAIN_OSTYPE_HVM) disk->bus = VIR_DOMAIN_DISK_BUS_XEN; else if (STRPREFIX(libxldisk->vdev, "sd")) disk->bus = VIR_DOMAIN_DISK_BUS_SCSI; else disk->bus = VIR_DOMAIN_DISK_BUS_IDE; if (VIR_APPEND_ELEMENT(def->disks, def->ndisks, disk) < 0) goto fail; libxl_device_disk_dispose(libxldisk); skipdisk: list = list->next; } } ret = 0; cleanup: virDomainDiskDefFree(disk); xlu_cfg_destroy(xluconf); VIR_FREE(libxldisk); return ret; fail: libxl_device_disk_dispose(libxldisk); goto cleanup; }
/** * virObjectEventCallbackListAddID: * @conn: pointer to the connection * @cbList: the list * @key: the optional key of the object to filter on * @filter: optional last-ditch filter callback * @filter_opaque: opaque data to pass to @filter * @klass: the base event class * @eventID: the event ID * @callback: the callback to add * @opaque: opaque data to pass to @callback * @freecb: callback to free @opaque * @legacy: true if callback is tracked by function instead of callbackID * @callbackID: filled with callback ID * @serverFilter: true if server supports object filtering * * Internal function to add a callback from a virObjectEventCallbackListPtr */ static int virObjectEventCallbackListAddID(virConnectPtr conn, virObjectEventCallbackListPtr cbList, const char *key, virObjectEventCallbackFilter filter, void *filter_opaque, virClassPtr klass, int eventID, virConnectObjectEventGenericCallback callback, void *opaque, virFreeCallback freecb, bool legacy, int *callbackID, bool serverFilter) { virObjectEventCallbackPtr cb; int ret = -1; int remoteID = -1; VIR_DEBUG("conn=%p cblist=%p key=%p filter=%p filter_opaque=%p " "klass=%p eventID=%d callback=%p opaque=%p " "legacy=%d callbackID=%p serverFilter=%d", conn, cbList, key, filter, filter_opaque, klass, eventID, callback, opaque, legacy, callbackID, serverFilter); /* Check incoming */ if (!cbList) return -1; /* If there is no additional filtering, then check if we already * have this callback on our list. */ if (!filter && virObjectEventCallbackLookup(conn, cbList, key, klass, eventID, callback, legacy, serverFilter ? &remoteID : NULL) != -1) { virReportError(VIR_ERR_INVALID_ARG, "%s", _("event callback already tracked")); return -1; } /* Allocate new cb */ if (VIR_ALLOC(cb) < 0) goto cleanup; cb->conn = virObjectRef(conn); *callbackID = cb->callbackID = cbList->nextID++; cb->cb = callback; cb->klass = klass; cb->eventID = eventID; cb->opaque = opaque; cb->freecb = freecb; cb->remoteID = remoteID; if (key) { cb->key_filter = true; if (VIR_STRDUP(cb->key, key) < 0) goto cleanup; } cb->filter = filter; cb->filter_opaque = filter_opaque; cb->legacy = legacy; if (VIR_APPEND_ELEMENT(cbList->callbacks, cbList->count, cb) < 0) goto cleanup; /* When additional filtering is being done, every client callback * is matched to exactly one server callback. */ if (filter) { ret = 1; } else { ret = virObjectEventCallbackListCount(conn, cbList, klass, eventID, key, serverFilter); if (serverFilter && remoteID < 0) ret++; } cleanup: virObjectEventCallbackFree(cb); return ret; }
static int bhyveParsePCINet(virDomainDefPtr def, virDomainXMLOptionPtr xmlopt, unsigned caps ATTRIBUTE_UNUSED, unsigned pcislot, unsigned pcibus, unsigned function, const char *config) { /* -s slot,virtio-net,tapN[,mac=xx:xx:xx:xx:xx:xx] */ virDomainNetDefPtr net = NULL; const char *separator = NULL; const char *mac = NULL; if (VIR_ALLOC(net) < 0) goto cleanup; /* Let's just assume it is VIR_DOMAIN_NET_TYPE_ETHERNET, it could also be * a bridge, but this is the most generic option. */ net->type = VIR_DOMAIN_NET_TYPE_ETHERNET; net->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; net->info.addr.pci.slot = pcislot; net->info.addr.pci.bus = pcibus; net->info.addr.pci.function = function; if (!config) goto error; if (!STRPREFIX(config, "tap")) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Only tap devices supported")); goto error; } separator = strchr(config, ','); if (VIR_STRNDUP(net->ifname, config, separator? separator - config : -1) < 0) goto error; if (!separator) goto cleanup; if (!STRPREFIX(++separator, "mac=")) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Only mac option can be specified for virt-net")); goto error; } mac = separator + 4; if (virMacAddrParse(mac, &net->mac) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("unable to parse mac address '%s'"), mac); goto cleanup; } cleanup: if (!mac) virDomainNetGenerateMAC(xmlopt, &net->mac); if (VIR_APPEND_ELEMENT(def->nets, def->nnets, net) < 0) goto error; return 0; error: virDomainNetDefFree(net); return -1; }
static int virStorageBackendRBDRefreshPool(virConnectPtr conn, virStoragePoolObjPtr pool) { size_t max_size = 1024; int ret = -1; int len = -1; int r = 0; char *name, *names = NULL; virStorageBackendRBDState ptr; ptr.cluster = NULL; ptr.ioctx = NULL; if (virStorageBackendRBDOpenRADOSConn(&ptr, conn, &pool->def->source) < 0) { goto cleanup; } if (virStorageBackendRBDOpenIoCTX(&ptr, pool) < 0) { goto cleanup; } struct rados_cluster_stat_t clusterstat; r = rados_cluster_stat(ptr.cluster, &clusterstat); if (r < 0) { virReportSystemError(-r, "%s", _("failed to stat the RADOS cluster")); goto cleanup; } struct rados_pool_stat_t poolstat; r = rados_ioctx_pool_stat(ptr.ioctx, &poolstat); if (r < 0) { virReportSystemError(-r, _("failed to stat the RADOS pool '%s'"), pool->def->source.name); goto cleanup; } pool->def->capacity = clusterstat.kb * 1024; pool->def->available = clusterstat.kb_avail * 1024; pool->def->allocation = poolstat.num_bytes; VIR_DEBUG("Utilization of RBD pool %s: (kb: %llu kb_avail: %llu num_bytes: %llu)", pool->def->source.name, (unsigned long long)clusterstat.kb, (unsigned long long)clusterstat.kb_avail, (unsigned long long)poolstat.num_bytes); while (true) { if (VIR_ALLOC_N(names, max_size) < 0) goto cleanup; len = rbd_list(ptr.ioctx, names, &max_size); if (len >= 0) break; if (len != -ERANGE) { VIR_WARN("%s", _("A problem occurred while listing RBD images")); goto cleanup; } VIR_FREE(names); } for (name = names; name < names + max_size;) { virStorageVolDefPtr vol; if (STREQ(name, "")) break; if (VIR_ALLOC(vol) < 0) goto cleanup; if (VIR_STRDUP(vol->name, name) < 0) { VIR_FREE(vol); goto cleanup; } name += strlen(name) + 1; if (volStorageBackendRBDRefreshVolInfo(vol, pool, &ptr) < 0) { virStorageVolDefFree(vol); goto cleanup; } if (VIR_APPEND_ELEMENT(pool->volumes.objs, pool->volumes.count, vol) < 0) { virStorageVolDefFree(vol); virStoragePoolObjClearVols(pool); goto cleanup; } } VIR_DEBUG("Found %zu images in RBD pool %s", pool->volumes.count, pool->def->source.name); ret = 0; cleanup: VIR_FREE(names); virStorageBackendRBDCloseRADOSConn(&ptr); return ret; }
static int virStorageBackendSCSINewLun(virStoragePoolObjPtr pool, uint32_t host ATTRIBUTE_UNUSED, uint32_t bus, uint32_t target, uint32_t lun, const char *dev) { virStorageVolDefPtr vol; char *devpath = NULL; int retval = 0; if (VIR_ALLOC(vol) < 0) { retval = -1; goto out; } vol->type = VIR_STORAGE_VOL_BLOCK; /* 'host' is dynamically allocated by the kernel, first come, * first served, per HBA. As such it isn't suitable for use * in the volume name. We only need uniqueness per-pool, so * just leave 'host' out */ if (virAsprintf(&(vol->name), "unit:%u:%u:%u", bus, target, lun) < 0) { retval = -1; goto free_vol; } if (virAsprintf(&devpath, "/dev/%s", dev) < 0) { retval = -1; goto free_vol; } VIR_DEBUG("Trying to create volume for '%s'", devpath); /* 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... */ if ((vol->target.path = virStorageBackendStablePath(pool, devpath, true)) == NULL) { retval = -1; goto free_vol; } if (STREQ(devpath, vol->target.path) && !(STREQ(pool->def->target.path, "/dev") || STREQ(pool->def->target.path, "/dev/"))) { VIR_DEBUG("No stable path found for '%s' in '%s'", devpath, pool->def->target.path); retval = -1; goto free_vol; } if (virStorageBackendSCSIUpdateVolTargetInfo(&vol->target, &vol->allocation, &vol->capacity) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Failed to update volume for '%s'"), devpath); retval = -1; goto free_vol; } if (!(vol->key = virStorageBackendSCSISerial(vol->target.path))) { retval = -1; goto free_vol; } pool->def->capacity += vol->capacity; pool->def->allocation += vol->allocation; if (VIR_APPEND_ELEMENT(pool->volumes.objs, pool->volumes.count, vol) < 0) { retval = -1; goto free_vol; } goto out; free_vol: virStorageVolDefFree(vol); out: VIR_FREE(devpath); return retval; }
static int testQemuDiskXMLToProps(const void *opaque) { struct testQemuDiskXMLToJSONData *data = (void *) opaque; virDomainDiskDefPtr disk = NULL; virStorageSourcePtr n; virJSONValuePtr formatProps = NULL; virJSONValuePtr storageProps = NULL; char *xmlpath = NULL; char *xmlstr = NULL; int ret = -1; if (virAsprintf(&xmlpath, "%s%s.xml", testQemuDiskXMLToJSONPath, data->name) < 0) goto cleanup; if (virTestLoadFile(xmlpath, &xmlstr) < 0) goto cleanup; /* qemu stores node names in the status XML portion */ if (!(disk = virDomainDiskDefParse(xmlstr, NULL, data->driver->xmlopt, VIR_DOMAIN_DEF_PARSE_STATUS))) goto cleanup; if (qemuCheckDiskConfig(disk, data->qemuCaps) < 0 || qemuDomainDeviceDefValidateDisk(disk, data->qemuCaps) < 0) { VIR_TEST_VERBOSE("invalid configuration for disk\n"); goto cleanup; } for (n = disk->src; virStorageSourceIsBacking(n); n = n->backingStore) { if (testQemuDiskXMLToJSONFakeSecrets(n) < 0) goto cleanup; if (qemuDomainValidateStorageSource(n, data->qemuCaps) < 0) goto cleanup; if (qemuDomainPrepareDiskSourceData(disk, n, NULL, data->qemuCaps) < 0) goto cleanup; if (!(formatProps = qemuBlockStorageSourceGetBlockdevProps(n)) || !(storageProps = qemuBlockStorageSourceGetBackendProps(n, false))) { if (!data->fail) { VIR_TEST_VERBOSE("failed to generate qemu blockdev props\n"); goto cleanup; } } else if (data->fail) { VIR_TEST_VERBOSE("qemu blockdev props should have failed\n"); goto cleanup; } if (VIR_APPEND_ELEMENT(data->props, data->nprops, formatProps) < 0 || VIR_APPEND_ELEMENT(data->props, data->nprops, storageProps) < 0) goto cleanup; } ret = 0; cleanup: virJSONValueFree(formatProps); virJSONValueFree(storageProps); virDomainDiskDefFree(disk); VIR_FREE(xmlpath); VIR_FREE(xmlstr); return ret; }
static int bhyveParseBhyveLPCArg(virDomainDefPtr def, unsigned caps ATTRIBUTE_UNUSED, const char *arg) { /* -l emulation[,config] */ const char *separator = NULL; const char *param = NULL; size_t last = 0; virDomainChrDefPtr chr = NULL; char *type = NULL; separator = strchr(arg, ','); param = separator + 1; if (!separator) goto error; if (VIR_STRNDUP(type, arg, separator - arg) < 0) goto error; /* Only support com%d */ if (STRPREFIX(type, "com") && type[4] == 0) { if (!(chr = virDomainChrDefNew(NULL))) goto error; chr->source->type = VIR_DOMAIN_CHR_TYPE_NMDM; chr->source->data.nmdm.master = NULL; chr->source->data.nmdm.slave = NULL; chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL; if (!STRPREFIX(param, "/dev/nmdm")) { virReportError(VIR_ERR_OPERATION_FAILED, _("Failed to set com port %s: does not start with " "'/dev/nmdm'."), type); goto error; } if (VIR_STRDUP(chr->source->data.nmdm.master, param) < 0) { virDomainChrDefFree(chr); goto error; } if (VIR_STRDUP(chr->source->data.nmdm.slave, chr->source->data.file.path) < 0) { virDomainChrDefFree(chr); goto error; } /* If the last character of the master is 'A', the slave will be 'B' * and vice versa */ last = strlen(chr->source->data.nmdm.master) - 1; switch (chr->source->data.file.path[last]) { case 'A': chr->source->data.nmdm.slave[last] = 'B'; break; case 'B': chr->source->data.nmdm.slave[last] = 'A'; break; default: virReportError(VIR_ERR_OPERATION_FAILED, _("Failed to set slave for %s: last letter not " "'A' or 'B'"), NULLSTR(chr->source->data.nmdm.master)); goto error; } switch (type[3]-'0') { case 1: case 2: chr->target.port = type[3] - '1'; break; default: virReportError(VIR_ERR_OPERATION_FAILED, _("Failed to parse %s: only com1 and com2" " supported."), type); goto error; break; } if (VIR_APPEND_ELEMENT(def->serials, def->nserials, chr) < 0) { virDomainChrDefFree(chr); goto error; } } VIR_FREE(type); return 0; error: virDomainChrDefFree(chr); VIR_FREE(type); return -1; }
static int openvzReadFSConf(virDomainDefPtr def, int veid) { int ret; virDomainFSDefPtr fs = NULL; char *veid_str = NULL; char *temp = NULL; const char *param; unsigned long long barrier, limit; ret = openvzReadVPSConfigParam(veid, "OSTEMPLATE", &temp); if (ret < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not read 'OSTEMPLATE' from config for container %d"), veid); goto error; } else if (ret > 0) { if (VIR_ALLOC(fs) < 0) goto error; fs->type = VIR_DOMAIN_FS_TYPE_TEMPLATE; if (VIR_STRDUP(fs->src, temp) < 0) goto error; } else { /* OSTEMPLATE was not found, VE was booted from a private dir directly */ ret = openvzReadVPSConfigParam(veid, "VE_PRIVATE", &temp); if (ret <= 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not read 'VE_PRIVATE' from config for container %d"), veid); goto error; } if (VIR_ALLOC(fs) < 0) goto error; if (virAsprintf(&veid_str, "%d", veid) < 0) goto error; fs->type = VIR_DOMAIN_FS_TYPE_MOUNT; if (!(fs->src = virStringReplace(temp, "$VEID", veid_str))) goto error; VIR_FREE(veid_str); } if (VIR_STRDUP(fs->dst, "/") < 0) goto error; param = "DISKSPACE"; ret = openvzReadVPSConfigParam(veid, param, &temp); if (ret > 0) { if (openvzParseBarrierLimit(temp, &barrier, &limit)) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not read '%s' from config for container %d"), param, veid); goto error; } else { /* Ensure that we can multiply by 1024 without overflowing. */ if (barrier > ULLONG_MAX / 1024 || limit > ULLONG_MAX / 1024) { virReportError(VIR_ERR_OVERFLOW, "%s", _("Unable to parse quota")); goto error; } fs->space_soft_limit = barrier * 1024; /* unit is bytes */ fs->space_hard_limit = limit * 1024; /* unit is bytes */ } } if (VIR_APPEND_ELEMENT(def->fss, def->nfss, fs) < 0) goto error; VIR_FREE(temp); return 0; error: VIR_FREE(temp); virDomainFSDefFree(fs); return -1; }
int virSecurityManagerGenLabel(virSecurityManagerPtr mgr, virDomainDefPtr vm) { int ret = -1; size_t i, j; virSecurityManagerPtr* sec_managers = NULL; virSecurityLabelDefPtr seclabel; bool generated = false; if (mgr == NULL || mgr->drv == NULL) return ret; if ((sec_managers = virSecurityManagerGetNested(mgr)) == NULL) return ret; virObjectLock(mgr); for (i = 0; i < vm->nseclabels; i++) { if (!vm->seclabels[i]->model) continue; for (j = 0; sec_managers[j]; j++) if (STREQ(vm->seclabels[i]->model, sec_managers[j]->drv->name)) break; if (!sec_managers[j]) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unable to find security driver for label %s"), vm->seclabels[i]->model); goto cleanup; } } for (i = 0; sec_managers[i]; i++) { generated = false; seclabel = virDomainDefGetSecurityLabelDef(vm, sec_managers[i]->drv->name); if (!seclabel) { if (!(seclabel = virSecurityLabelDefNew(sec_managers[i]->drv->name))) goto cleanup; generated = seclabel->implicit = true; } if (seclabel->type == VIR_DOMAIN_SECLABEL_DEFAULT) { if (sec_managers[i]->defaultConfined) { seclabel->type = VIR_DOMAIN_SECLABEL_DYNAMIC; } else { seclabel->type = VIR_DOMAIN_SECLABEL_NONE; seclabel->norelabel = true; } } if (seclabel->type == VIR_DOMAIN_SECLABEL_NONE) { if (sec_managers[i]->requireConfined) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Unconfined guests are not allowed on this host")); goto cleanup; } else if (vm->nseclabels && generated) { VIR_DEBUG("Skipping auto generated seclabel of type none"); virSecurityLabelDefFree(seclabel); seclabel = NULL; continue; } } if (!sec_managers[i]->drv->domainGenSecurityLabel) { virReportUnsupportedError(); virSecurityLabelDefFree(seclabel); seclabel = NULL; } else { /* The seclabel must be added to @vm prior calling domainGenSecurityLabel * which may require seclabel to be presented already */ if (generated && VIR_APPEND_ELEMENT(vm->seclabels, vm->nseclabels, seclabel) < 0) goto cleanup; if (sec_managers[i]->drv->domainGenSecurityLabel(sec_managers[i], vm) < 0) { if (VIR_DELETE_ELEMENT(vm->seclabels, vm->nseclabels -1, vm->nseclabels) < 0) vm->nseclabels--; goto cleanup; } seclabel = NULL; } } ret = 0; cleanup: virObjectUnlock(mgr); if (generated) virSecurityLabelDefFree(seclabel); VIR_FREE(sec_managers); return ret; }
/* * Attempt to create a new LUN * * Returns: * * 0 => Success * -1 => Failure due to some sort of OOM or other fatal issue found when * attempting to get/update information about a found volume * -2 => Failure to find a stable path, not fatal, caller can try another */ static int virStorageBackendSCSINewLun(virStoragePoolObjPtr pool, uint32_t host ATTRIBUTE_UNUSED, uint32_t bus, uint32_t target, uint32_t lun, const char *dev) { virStorageVolDefPtr vol = NULL; char *devpath = NULL; int retval = -1; /* Check if the pool is using a stable target path. The call to * virStorageBackendStablePath will fail if the pool target path * isn't stable and just return the strdup'd 'devpath' anyway. * This would be indistinguishable to failing to find the stable * path to the device if the virDirRead loop to search the * target pool path for our devpath had failed. */ if (!virStorageBackendPoolPathIsStable(pool->def->target.path) && !(STREQ(pool->def->target.path, "/dev") || STREQ(pool->def->target.path, "/dev/"))) { virReportError(VIR_ERR_INVALID_ARG, _("unable to use target path '%s' for dev '%s'"), NULLSTR(pool->def->target.path), dev); goto cleanup; } if (VIR_ALLOC(vol) < 0) goto cleanup; vol->type = VIR_STORAGE_VOL_BLOCK; /* 'host' is dynamically allocated by the kernel, first come, * first served, per HBA. As such it isn't suitable for use * in the volume name. We only need uniqueness per-pool, so * just leave 'host' out */ if (virAsprintf(&(vol->name), "unit:%u:%u:%u", bus, target, lun) < 0) goto cleanup; if (virAsprintf(&devpath, "/dev/%s", dev) < 0) goto cleanup; VIR_DEBUG("Trying to create volume for '%s'", devpath); /* 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... */ if ((vol->target.path = virStorageBackendStablePath(pool, devpath, true)) == NULL) goto cleanup; if (STREQ(devpath, vol->target.path) && !(STREQ(pool->def->target.path, "/dev") || STREQ(pool->def->target.path, "/dev/"))) { VIR_DEBUG("No stable path found for '%s' in '%s'", devpath, pool->def->target.path); retval = -2; goto cleanup; } /* Allow a volume read failure to ignore or skip this block file */ if ((retval = virStorageBackendUpdateVolInfo(vol, true, VIR_STORAGE_VOL_OPEN_DEFAULT, VIR_STORAGE_VOL_READ_NOERROR)) < 0) goto cleanup; if (!(vol->key = virStorageBackendSCSISerial(vol->target.path))) goto cleanup; pool->def->capacity += vol->target.capacity; pool->def->allocation += vol->target.allocation; if (VIR_APPEND_ELEMENT(pool->volumes.objs, pool->volumes.count, vol) < 0) goto cleanup; vol = NULL; retval = 0; cleanup: virStorageVolDefFree(vol); VIR_FREE(devpath); return retval; }
static int lxcNetworkWalkCallback(const char *name, virConfValuePtr value, void *data) { lxcNetworkParseData *parseData = data; int status; if (STREQ(name, "lxc.network.type")) { /* Store the previous NIC */ status = lxcAddNetworkDefinition(parseData); if (status < 0) return -1; else if (status > 0) parseData->networks++; else if (parseData->type != NULL && STREQ(parseData->type, "none")) parseData->privnet = false; /* Start a new network interface config */ parseData->type = NULL; parseData->link = NULL; parseData->mac = NULL; parseData->flag = NULL; parseData->macvlanmode = NULL; parseData->vlanid = NULL; parseData->name = NULL; parseData->ips = NULL; parseData->nips = 0; /* Keep the new value */ parseData->type = value->str; } else if (STREQ(name, "lxc.network.link")) parseData->link = value->str; else if (STREQ(name, "lxc.network.hwaddr")) parseData->mac = value->str; else if (STREQ(name, "lxc.network.flags")) parseData->flag = value->str; else if (STREQ(name, "lxc.network.macvlan.mode")) parseData->macvlanmode = value->str; else if (STREQ(name, "lxc.network.vlan.id")) parseData->vlanid = value->str; else if (STREQ(name, "lxc.network.name")) parseData->name = value->str; else if (STREQ(name, "lxc.network.ipv4") || STREQ(name, "lxc.network.ipv6")) { int family = AF_INET; char **ipparts = NULL; virDomainNetIpDefPtr ip = NULL; if (VIR_ALLOC(ip) < 0) return -1; if (STREQ(name, "lxc.network.ipv6")) family = AF_INET6; ipparts = virStringSplit(value->str, "/", 2); if (virStringListLength((const char * const *)ipparts) != 2 || virSocketAddrParse(&ip->address, ipparts[0], family) < 0 || virStrToLong_ui(ipparts[1], NULL, 10, &ip->prefix) < 0) { virReportError(VIR_ERR_INVALID_ARG, _("Invalid CIDR address: '%s'"), value->str); virStringFreeList(ipparts); VIR_FREE(ip); return -1; } virStringFreeList(ipparts); if (VIR_APPEND_ELEMENT(parseData->ips, parseData->nips, ip) < 0) { VIR_FREE(ip); return -1; } } else if (STREQ(name, "lxc.network.ipv4.gateway")) { parseData->gateway_ipv4 = value->str; } else if (STREQ(name, "lxc.network.ipv6.gateway")) { parseData->gateway_ipv6 = value->str; } else if (STRPREFIX(name, "lxc.network")) { VIR_WARN("Unhandled network property: %s = %s", name, value->str); } return 0; }
/** * virObjectEventCallbackListAddID: * @conn: pointer to the connection * @cbList: the list * @uuid: the optional uuid of the object to filter on * @filter: optional last-ditch filter callback * @filter_opaque: opaque data to pass to @filter * @klass: the base event class * @eventID: the event ID * @callback: the callback to add * @opaque: opaque data to pass to @callback * @freecb: callback to free @opaque * @legacy: true if callback is tracked by function instead of callbackID * @callbackID: filled with callback ID * @serverFilter: true if server supports object filtering * * Internal function to add a callback from a virObjectEventCallbackListPtr */ static int virObjectEventCallbackListAddID(virConnectPtr conn, virObjectEventCallbackListPtr cbList, unsigned char uuid[VIR_UUID_BUFLEN], virObjectEventCallbackFilter filter, void *filter_opaque, virClassPtr klass, int eventID, virConnectObjectEventGenericCallback callback, void *opaque, virFreeCallback freecb, bool legacy, int *callbackID, bool serverFilter) { virObjectEventCallbackPtr event; int ret = -1; int remoteID = -1; VIR_DEBUG("conn=%p cblist=%p uuid=%p filter=%p filter_opaque=%p " "klass=%p eventID=%d callback=%p opaque=%p " "legacy=%d callbackID=%p serverFilter=%d", conn, cbList, uuid, filter, filter_opaque, klass, eventID, callback, opaque, legacy, callbackID, serverFilter); /* Check incoming */ if (!cbList) return -1; /* If there is no additional filtering, then check if we already * have this callback on our list. */ if (!filter && virObjectEventCallbackLookup(conn, cbList, uuid, klass, eventID, callback, legacy, serverFilter ? &remoteID : NULL) != -1) { virReportError(VIR_ERR_INVALID_ARG, "%s", _("event callback already tracked")); return -1; } /* Allocate new event */ if (VIR_ALLOC(event) < 0) goto cleanup; event->conn = virObjectRef(conn); *callbackID = event->callbackID = cbList->nextID++; event->cb = callback; event->klass = klass; event->eventID = eventID; event->opaque = opaque; event->freecb = freecb; event->remoteID = remoteID; /* Only need 'uuid' for matching; 'id' can change as domain * switches between running and shutoff, and 'name' can change in * Xen migration. */ if (uuid) { event->uuid_filter = true; memcpy(event->uuid, uuid, VIR_UUID_BUFLEN); } event->filter = filter; event->filter_opaque = filter_opaque; event->legacy = legacy; if (VIR_APPEND_ELEMENT(cbList->callbacks, cbList->count, event) < 0) goto cleanup; /* When additional filtering is being done, every client callback * is matched to exactly one server callback. */ if (filter) { ret = 1; } else { ret = virObjectEventCallbackListCount(conn, cbList, klass, eventID, uuid, serverFilter); if (serverFilter && remoteID < 0) ret++; } cleanup: if (event) virObjectUnref(event->conn); VIR_FREE(event); return ret; }
static int virStorageBackendLogicalMakeVol(char **const groups, void *opaque) { struct virStorageBackendLogicalPoolVolData *data = opaque; virStoragePoolObjPtr pool = data->pool; virStorageVolDefPtr vol = NULL; bool is_new_vol = false; unsigned long long offset, size, length; const char *regex_unit = "(\\S+)\\((\\S+)\\)"; char *regex = NULL; regex_t *reg = NULL; regmatch_t *vars = NULL; char *p = NULL; size_t i; int err, nextents, nvars, ret = -1; const char *attrs = groups[9]; /* Skip inactive volume */ if (attrs[4] != 'a') return 0; /* * Skip thin pools(t). These show up in normal lvs output * but do not have a corresponding /dev/$vg/$lv device that * is created by udev. This breaks assumptions in later code. */ if (attrs[0] == 't') return 0; /* See if we're only looking for a specific volume */ if (data->vol != NULL) { vol = data->vol; if (STRNEQ(vol->name, groups[0])) return 0; } /* Or filling in more data on an existing volume */ if (vol == NULL) vol = virStorageVolDefFindByName(pool, groups[0]); /* Or a completely new volume */ if (vol == NULL) { if (VIR_ALLOC(vol) < 0) return -1; is_new_vol = true; vol->type = VIR_STORAGE_VOL_BLOCK; if (VIR_STRDUP(vol->name, groups[0]) < 0) goto cleanup; } if (vol->target.path == NULL) { if (virAsprintf(&vol->target.path, "%s/%s", pool->def->target.path, vol->name) < 0) goto cleanup; } /* Mark the (s) sparse/snapshot lv, e.g. the lv created using * the --virtualsize/-V option. We've already ignored the (t)hin * pool definition. In the manner libvirt defines these, the * thin pool is hidden to the lvs output, except as the name * in brackets [] described for the groups[1] (backingStore). */ if (attrs[0] == 's') vol->target.sparse = true; /* Skips the backingStore of lv created with "--virtualsize", * its original device "/dev/$vgname/$lvname_vorigin" is * just for lvm internal use, one should never use it. * * (lvs outputs "[$lvname_vorigin] for field "origin" if the * lv is created with "--virtualsize"). */ if (groups[1] && !STREQ(groups[1], "") && (groups[1][0] != '[')) { if (VIR_ALLOC(vol->target.backingStore) < 0) goto cleanup; if (virAsprintf(&vol->target.backingStore->path, "%s/%s", pool->def->target.path, groups[1]) < 0) goto cleanup; vol->target.backingStore->format = VIR_STORAGE_POOL_LOGICAL_LVM2; } if (!vol->key && VIR_STRDUP(vol->key, groups[2]) < 0) goto cleanup; if (virStorageBackendUpdateVolInfo(vol, true, false, VIR_STORAGE_VOL_OPEN_DEFAULT) < 0) goto cleanup; nextents = 1; if (STREQ(groups[4], VIR_STORAGE_VOL_LOGICAL_SEGTYPE_STRIPED)) { if (virStrToLong_i(groups[5], NULL, 10, &nextents) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("malformed volume extent stripes value")); goto cleanup; } } /* Finally fill in extents information */ if (VIR_REALLOC_N(vol->source.extents, vol->source.nextent + nextents) < 0) goto cleanup; if (virStrToLong_ull(groups[6], NULL, 10, &length) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("malformed volume extent length value")); goto cleanup; } if (virStrToLong_ull(groups[7], NULL, 10, &size) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("malformed volume extent size value")); goto cleanup; } if (virStrToLong_ull(groups[8], NULL, 10, &vol->target.allocation) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("malformed volume allocation value")); goto cleanup; } /* Now parse the "devices" field separately */ if (VIR_STRDUP(regex, regex_unit) < 0) goto cleanup; for (i = 1; i < nextents; i++) { if (VIR_REALLOC_N(regex, strlen(regex) + strlen(regex_unit) + 2) < 0) goto cleanup; /* "," is the separator of "devices" field */ strcat(regex, ","); strncat(regex, regex_unit, strlen(regex_unit)); } if (VIR_ALLOC(reg) < 0) goto cleanup; /* Each extent has a "path:offset" pair, and vars[0] will * be the whole matched string. */ nvars = (nextents * 2) + 1; if (VIR_ALLOC_N(vars, nvars) < 0) goto cleanup; err = regcomp(reg, regex, REG_EXTENDED); if (err != 0) { char error[100]; regerror(err, reg, error, sizeof(error)); virReportError(VIR_ERR_INTERNAL_ERROR, _("Failed to compile regex %s"), error); goto cleanup; } err = regexec(reg, groups[3], nvars, vars, 0); regfree(reg); if (err != 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("malformed volume extent devices value")); goto cleanup; } p = groups[3]; /* vars[0] is skipped */ for (i = 0; i < nextents; i++) { size_t j; int len; char *offset_str = NULL; j = (i * 2) + 1; len = vars[j].rm_eo - vars[j].rm_so; p[vars[j].rm_eo] = '\0'; if (VIR_STRNDUP(vol->source.extents[vol->source.nextent].path, p + vars[j].rm_so, len) < 0) goto cleanup; len = vars[j + 1].rm_eo - vars[j + 1].rm_so; if (VIR_STRNDUP(offset_str, p + vars[j + 1].rm_so, len) < 0) goto cleanup; if (virStrToLong_ull(offset_str, NULL, 10, &offset) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("malformed volume extent offset value")); VIR_FREE(offset_str); goto cleanup; } VIR_FREE(offset_str); vol->source.extents[vol->source.nextent].start = offset * size; vol->source.extents[vol->source.nextent].end = (offset * size) + length; vol->source.nextent++; } if (is_new_vol && VIR_APPEND_ELEMENT(pool->volumes.objs, pool->volumes.count, vol) < 0) goto cleanup; ret = 0; cleanup: VIR_FREE(regex); VIR_FREE(reg); VIR_FREE(vars); if (is_new_vol && (ret == -1)) virStorageVolDefFree(vol); return ret; }
static int virStorageBackendZFSParseVol(virStoragePoolObjPtr pool, virStorageVolDefPtr vol, const char *volume_string) { int ret = -1; char **tokens; size_t count; char **name_tokens = NULL; char *vol_name; bool is_new_vol = false; virStorageVolDefPtr volume = NULL; if (!(tokens = virStringSplitCount(volume_string, "\t", 0, &count))) return -1; if (count != 2) goto cleanup; if (!(name_tokens = virStringSplit(tokens[0], "/", 2))) goto cleanup; vol_name = name_tokens[1]; if (vol == NULL) volume = virStorageVolDefFindByName(pool, vol_name); else volume = vol; if (volume == NULL) { if (VIR_ALLOC(volume) < 0) goto cleanup; is_new_vol = true; volume->type = VIR_STORAGE_VOL_BLOCK; if (VIR_STRDUP(volume->name, vol_name) < 0) goto cleanup; } if (!volume->key && VIR_STRDUP(volume->key, tokens[0]) < 0) goto cleanup; if (volume->target.path == NULL) { if (virAsprintf(&volume->target.path, "%s/%s", pool->def->target.path, volume->name) < 0) goto cleanup; } if (virStrToLong_ull(tokens[1], NULL, 10, &volume->target.capacity) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("malformed volsize reported")); goto cleanup; } if (is_new_vol && VIR_APPEND_ELEMENT(pool->volumes.objs, pool->volumes.count, volume) < 0) goto cleanup; ret = 0; cleanup: virStringFreeList(tokens); virStringFreeList(name_tokens); if (is_new_vol) virStorageVolDefFree(volume); return ret; }
static int bhyveParsePCIDisk(virDomainDefPtr def, unsigned caps ATTRIBUTE_UNUSED, unsigned pcislot, unsigned pcibus, unsigned function, int bus, int device, unsigned *nvirtiodisk, unsigned *nahcidisk, char *config) { /* -s slot,virtio-blk|ahci-cd|ahci-hd,/path/to/file */ const char *separator = NULL; int idx = -1; virDomainDiskDefPtr disk = NULL; if (VIR_ALLOC(disk) < 0) goto cleanup; if (VIR_ALLOC(disk->src) < 0) goto error; disk->bus = bus; disk->device = device; disk->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; disk->info.addr.pci.slot = pcislot; disk->info.addr.pci.bus = pcibus; disk->info.addr.pci.function = function; if (STRPREFIX(config, "/dev/")) disk->src->type = VIR_STORAGE_TYPE_BLOCK; else disk->src->type = VIR_STORAGE_TYPE_FILE; if (!config) goto error; separator = strchr(config, ','); if (VIR_STRNDUP(disk->src->path, config, separator? separator - config : -1) < 0) goto error; if (bus == VIR_DOMAIN_DISK_BUS_VIRTIO) { idx = *nvirtiodisk; *nvirtiodisk += 1; if (VIR_STRDUP(disk->dst, "vda") < 0) goto error; } else if (bus == VIR_DOMAIN_DISK_BUS_SATA) { idx = *nahcidisk; *nahcidisk += 1; if (VIR_STRDUP(disk->dst, "sda") < 0) goto error; } if (idx > 'z' - 'a') { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("too many disks")); goto error; } disk->dst[2] = 'a' + idx; if (VIR_APPEND_ELEMENT(def->disks, def->ndisks, disk) < 0) goto error; cleanup: return 0; error: virDomainDiskDefFree(disk); return -1; }