int nodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames) { virDeviceMonitorStatePtr driver = dev->conn->devMonPrivateData; virNodeDeviceObjPtr obj; virNodeDevCapsDefPtr caps; int ncaps = 0; int ret = -1; nodeDeviceLock(driver); obj = virNodeDeviceFindByName(&driver->devs, dev->name); nodeDeviceUnlock(driver); if (!obj) { virReportError(VIR_ERR_NO_NODE_DEVICE, _("no node device with matching name '%s'"), dev->name); goto cleanup; } for (caps = obj->def->caps; caps && ncaps < maxnames; caps = caps->next) { names[ncaps] = strdup(virNodeDevCapTypeToString(caps->type)); if (names[ncaps++] == NULL) { virReportOOMError(); goto cleanup; } } ret = ncaps; cleanup: if (obj) virNodeDeviceObjUnlock(obj); if (ret == -1) { --ncaps; while (--ncaps >= 0) VIR_FREE(names[ncaps]); } return ret; }
virNetServerProgramPtr virNetServerProgramNew(unsigned program, unsigned version, virNetServerProgramProcPtr procs, size_t nprocs) { virNetServerProgramPtr prog; if (VIR_ALLOC(prog) < 0) { virReportOOMError(); return NULL; } prog->refs = 1; prog->program = program; prog->version = version; prog->procs = procs; prog->nprocs = nprocs; VIR_DEBUG("prog=%p refs=%d", prog, prog->refs); return prog; }
static int xenInotifyXenCacheLookup(virConnectPtr conn, const char *filename, char **name, unsigned char *uuid) { xenUnifiedPrivatePtr priv = conn->privateData; xenXMConfCachePtr entry; if (!(entry = virHashLookup(priv->configCache, filename))) { VIR_DEBUG("No config found for %s", filename); return -1; } *name = strdup(entry->def->name); memcpy(uuid, entry->def->uuid, VIR_UUID_BUFLEN); if (!*name) { VIR_DEBUG("Error getting dom from def"); virReportOOMError(); return -1; } return 0; }
static int daemonUnixSocketPaths(struct daemonConfig *config, bool privileged, char **sockfile, char **rosockfile) { if (config->unix_sock_dir) { if (virAsprintf(sockfile, "%s/libvirt-sock", config->unix_sock_dir) < 0) goto no_memory; if (privileged && virAsprintf(rosockfile, "%s/libvirt-sock-ro", config->unix_sock_dir) < 0) goto no_memory; } else { if (privileged) { if (!(*sockfile = strdup(LOCALSTATEDIR "/run/libvirt/libvirt-sock"))) goto no_memory; if (!(*rosockfile = strdup(LOCALSTATEDIR "/run/libvirt/libvirt-sock-ro"))) goto no_memory; } else { char *userdir = NULL; if (!(userdir = virGetUserDirectory(geteuid()))) goto error; if (virAsprintf(sockfile, "@%s/.libvirt/libvirt-sock", userdir) < 0) { VIR_FREE(userdir); goto no_memory; } VIR_FREE(userdir); } } return 0; no_memory: virReportOOMError(); error: return -1; }
static int qcowXGetBackingStore(char **res, const unsigned char *buf, size_t buf_size) { unsigned long long offset; unsigned long size; *res = NULL; if (buf_size < 4+4+8+4) return BACKING_STORE_INVALID; offset = (((unsigned long long)buf[4+4] << 56) | ((unsigned long long)buf[4+4+1] << 48) | ((unsigned long long)buf[4+4+2] << 40) | ((unsigned long long)buf[4+4+3] << 32) | ((unsigned long long)buf[4+4+4] << 24) | ((unsigned long long)buf[4+4+5] << 16) | ((unsigned long long)buf[4+4+6] << 8) | buf[4+4+7]); /* QCowHeader.backing_file_offset */ if (offset > buf_size) return BACKING_STORE_INVALID; size = ((buf[4+4+8] << 24) | (buf[4+4+8+1] << 16) | (buf[4+4+8+2] << 8) | buf[4+4+8+3]); /* QCowHeader.backing_file_size */ if (size == 0) return BACKING_STORE_OK; if (offset + size > buf_size || offset + size < offset) return BACKING_STORE_INVALID; if (size + 1 == 0) return BACKING_STORE_INVALID; if (VIR_ALLOC_N(*res, size + 1) < 0) { virReportOOMError(); return BACKING_STORE_ERROR; } memcpy(*res, buf + offset, size); (*res)[size] = '\0'; return BACKING_STORE_OK; }
virNetClientProgramPtr virNetClientProgramNew(unsigned program, unsigned version, virNetClientProgramEventPtr events, size_t nevents, void *eventOpaque) { virNetClientProgramPtr prog; if (VIR_ALLOC(prog) < 0) { virReportOOMError(); return NULL; } prog->refs = 1; prog->program = program; prog->version = version; prog->events = events; prog->nevents = nevents; prog->eventOpaque = eventOpaque; return prog; }
/* * Linux maintains cpu bit map under cpu/online. For example, if * cpuid=5's flag is not set and max cpu is 7, the map file shows * 0-4,6-7. This function parses it and returns cpumap. */ static virBitmapPtr linuxParseCPUmap(int max_cpuid, const char *path) { virBitmapPtr map = NULL; char *str = NULL; if (virFileReadAll(path, 5 * VIR_DOMAIN_CPUMASK_LEN, &str) < 0) { virReportOOMError(); goto error; } if (virBitmapParse(str, 0, &map, max_cpuid) < 0) goto error; VIR_FREE(str); return map; error: VIR_FREE(str); virBitmapFree(map); return NULL; }
static int virInterfaceDefParseBondItfs(virInterfaceDefPtr def, xmlXPathContextPtr ctxt) { xmlNodePtr *interfaces = NULL; xmlNodePtr bond = ctxt->node; virInterfaceDefPtr itf; int nbItf, i; int ret = 0; nbItf = virXPathNodeSet("./interface", ctxt, &interfaces); if (nbItf <= 0) { virInterfaceReportError(VIR_ERR_XML_ERROR, "%s", _("bond has no interfaces")); ret = -1; goto error; } if (VIR_ALLOC_N(def->data.bond.itf, nbItf) < 0) { virReportOOMError(); ret = -1; goto error; } def->data.bond.nbItf = nbItf; for (i = 0; i < nbItf;i++) { ctxt->node = interfaces[i]; itf = virInterfaceDefParseXML(ctxt, VIR_INTERFACE_TYPE_BOND); if (itf == NULL) { ret = -1; def->data.bond.nbItf = i; goto error; } def->data.bond.itf[i] = itf; } error: VIR_FREE(interfaces); ctxt->node = bond; return(ret); }
static int ppcVendorLoad(xmlXPathContextPtr ctxt, struct ppc_map *map) { struct ppc_vendor *vendor = NULL; if (VIR_ALLOC(vendor) < 0) { virReportOOMError(); return -1; } vendor->name = virXPathString("string(@name)", ctxt); if (!vendor->name) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing CPU vendor name")); goto ignore; } if (ppcVendorFind(map, vendor->name)) { virReportError(VIR_ERR_INTERNAL_ERROR, _("CPU vendor %s already defined"), vendor->name); goto ignore; } if (!map->vendors) { map->vendors = vendor; } else { vendor->next = map->vendors; map->vendors = vendor; } cleanup: return 0; ignore: ppcVendorFree(vendor); goto cleanup; }
static int lxcProcGetattr(const char *path, struct stat *stbuf) { int res; char *mempath = NULL; struct stat sb; memset(stbuf, 0, sizeof(struct stat)); if (virAsprintf(&mempath, "/proc/%s", path) < 0) { virReportOOMError(); return -errno; } res = 0; if (STREQ(path, "/")) { stbuf->st_mode = S_IFDIR | 0755; stbuf->st_nlink = 2; } else if (STREQ(path, fuse_meminfo_path)) { if (stat(mempath, &sb) < 0) { res = -errno; goto cleanup; } stbuf->st_mode = sb.st_mode; stbuf->st_nlink = 1; stbuf->st_blksize = sb.st_blksize; stbuf->st_blocks = sb.st_blocks; stbuf->st_size = sb.st_size; stbuf->st_atime = sb.st_atime; stbuf->st_ctime = sb.st_ctime; stbuf->st_mtime = sb.st_mtime; } else res = -ENOENT; cleanup: VIR_FREE(mempath); return res; }
int virNetMessageDecodeNumFDs(virNetMessagePtr msg) { XDR xdr; unsigned int numFDs; int ret = -1; size_t i; xdrmem_create(&xdr, msg->buffer + msg->bufferOffset, msg->bufferLength - msg->bufferOffset, XDR_DECODE); if (!xdr_u_int(&xdr, &numFDs)) { virReportError(VIR_ERR_RPC, "%s", _("Unable to decode number of FDs")); goto cleanup; } msg->bufferOffset += xdr_getpos(&xdr); if (numFDs > VIR_NET_MESSAGE_NUM_FDS_MAX) { virReportError(VIR_ERR_RPC, _("Received too many FDs %d, expected %d maximum"), numFDs, VIR_NET_MESSAGE_NUM_FDS_MAX); goto cleanup; } msg->nfds = numFDs; if (VIR_ALLOC_N(msg->fds, msg->nfds) < 0) { virReportOOMError(); goto cleanup; } for (i = 0 ; i < msg->nfds ; i++) msg->fds[i] = -1; VIR_DEBUG("Got %zu FDs from peer", msg->nfds); ret = 0; cleanup: xdr_destroy(&xdr); return ret; }
/* Create a private tty using the private devpts at PTMX, returning * the master in *TTYMASTER and the name of the slave, _from the * perspective of the guest after remounting file systems_, in * *TTYNAME. Heavily borrowed from glibc, but doesn't require that * devpts == "/dev/pts" */ static int lxcCreateTty(char *ptmx, int *ttymaster, char **ttyName) { int ret = -1; int ptyno; int unlock = 0; if ((*ttymaster = open(ptmx, O_RDWR|O_NOCTTY|O_NONBLOCK)) < 0) goto cleanup; if (ioctl(*ttymaster, TIOCSPTLCK, &unlock) < 0) goto cleanup; if (ioctl(*ttymaster, TIOCGPTN, &ptyno) < 0) goto cleanup; /* If mount() succeeded at honoring newinstance, then the kernel * was new enough to also honor the mode=0620,gid=5 options, which * guarantee that the new pty already has correct permissions; so * while glibc has to fstat(), fchmod(), and fchown() for older * kernels, we can skip those steps. ptyno shouldn't currently be * anything other than 0, but let's play it safe. */ if (virAsprintf(ttyName, "/dev/pts/%d", ptyno) < 0) { virReportOOMError(); errno = ENOMEM; goto cleanup; } ret = 0; cleanup: if (ret != 0) { VIR_FORCE_CLOSE(*ttymaster); VIR_FREE(*ttyName); } return ret; }
virKeepAlivePtr virKeepAliveNew(int interval, unsigned int count, void *client, virKeepAliveSendFunc sendCB, virKeepAliveDeadFunc deadCB, virKeepAliveFreeFunc freeCB) { virKeepAlivePtr ka; VIR_DEBUG("client=%p, interval=%d, count=%u", client, interval, count); if (VIR_ALLOC(ka) < 0) { virReportOOMError(); return NULL; } if (virMutexInit(&ka->lock) < 0) { VIR_FREE(ka); return NULL; } ka->refs = 1; ka->interval = interval; ka->count = count; ka->countToDeath = count; ka->timer = -1; ka->client = client; ka->sendCB = sendCB; ka->deadCB = deadCB; ka->freeCB = freeCB; PROBE(RPC_KEEPALIVE_NEW, "ka=%p client=%p refs=%d", ka, ka->client, ka->refs); return ka; }
int virNetDevVPortProfileMerge3(virNetDevVPortProfilePtr *result, virNetDevVPortProfilePtr fromInterface, virNetDevVPortProfilePtr fromNetwork, virNetDevVPortProfilePtr fromPortgroup) { int ret = -1; *result = NULL; if ((!fromInterface || (fromInterface->virtPortType == VIR_NETDEV_VPORT_PROFILE_NONE)) && (!fromNetwork || (fromNetwork->virtPortType == VIR_NETDEV_VPORT_PROFILE_NONE)) && (!fromPortgroup || (fromPortgroup->virtPortType == VIR_NETDEV_VPORT_PROFILE_NONE))) { return 0; } /* at least one of the source profiles is non-empty */ if (VIR_ALLOC(*result) < 0) { virReportOOMError(); return ret; } /* start with the interface's profile. There are no pointers in a * virtualPortProfile, so a shallow copy is sufficient. */ if (fromInterface) **result = *fromInterface; if (virNetDevVPortProfileMerge(*result, fromNetwork) < 0) goto error; if (virNetDevVPortProfileMerge(*result, fromPortgroup) < 0) goto error; ret = 0; error: if (ret < 0) VIR_FREE(*result); return ret; }
static virNetworkObjPtr parallelsAddRoutedNetwork(parallelsConnPtr privconn) { virNetworkObjPtr net; virNetworkDefPtr def; if (VIR_ALLOC(def) < 0) goto no_memory; def->forward.type = VIR_NETWORK_FORWARD_ROUTE; if (!(def->name = strdup(PARALLELS_ROUTED_NETWORK_NAME))) goto no_memory; if (virUUIDParse(PARALLELS_ROUTED_NETWORK_UUID, def->uuid) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Can't parse UUID")); goto cleanup; } def->uuid_specified = 1; if (!(net = virNetworkAssignDef(&privconn->networks, def, false))) { virNetworkDefFree(def); goto cleanup; } net->active = 1; net->persistent = 1; net->autostart = 1; virNetworkObjUnlock(net); return net; no_memory: virReportOOMError(); cleanup: virNetworkDefFree(def); return NULL; }
static char *openvzGetOSType(virDomainPtr dom) { struct openvz_driver *driver = dom->conn->privateData; virDomainObjPtr vm; char *ret = NULL; openvzDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); openvzDriverUnlock(driver); if (!vm) { openvzError(VIR_ERR_NO_DOMAIN, NULL); goto cleanup; } if (!(ret = strdup(vm->def->os.type))) virReportOOMError(); cleanup: if (vm) virDomainObjUnlock(vm); return ret; }
char * qparam_get_query (const struct qparam_set *ps) { virBuffer buf = VIR_BUFFER_INITIALIZER; int i, amp = 0; for (i = 0; i < ps->n; ++i) { if (!ps->p[i].ignore) { if (amp) virBufferAddChar (&buf, '&'); virBufferStrcat (&buf, ps->p[i].name, "=", NULL); virBufferURIEncodeString (&buf, ps->p[i].value); amp = 1; } } if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); virReportOOMError(); return NULL; } return virBufferContentAndReset(&buf); }
virCPUDefPtr virCPUDefCopy(const virCPUDefPtr cpu) { virCPUDefPtr copy; unsigned int i; if (!cpu) return NULL; if (VIR_ALLOC(copy) < 0 || (cpu->arch && !(copy->arch = strdup(cpu->arch))) || (cpu->model && !(copy->model = strdup(cpu->model))) || (cpu->vendor && !(copy->vendor = strdup(cpu->vendor))) || VIR_ALLOC_N(copy->features, cpu->nfeatures) < 0) goto no_memory; copy->nfeatures_max = cpu->nfeatures; copy->type = cpu->type; copy->match = cpu->match; copy->sockets = cpu->sockets; copy->cores = cpu->cores; copy->threads = cpu->threads; copy->nfeatures = cpu->nfeatures; for (i = 0; i < copy->nfeatures; i++) { copy->features[i].policy = cpu->features[i].policy; if (!(copy->features[i].name = strdup(cpu->features[i].name))) goto no_memory; } return copy; no_memory: virReportOOMError(); virCPUDefFree(copy); return NULL; }
static int parallelsDiskDescParseNode(xmlDocPtr xml, xmlNodePtr root, virStorageVolDefPtr def) { xmlXPathContextPtr ctxt = NULL; int ret = -1; if (STRNEQ((const char *)root->name, "Parallels_disk_image")) { virReportError(VIR_ERR_XML_ERROR, "%s", _("unknown root element for storage pool")); goto cleanup; } ctxt = xmlXPathNewContext(xml); if (ctxt == NULL) { virReportOOMError(); goto cleanup; } ctxt->node = root; if (virXPathULongLong("string(./Disk_Parameters/Disk_size)", ctxt, &def->target.capacity) < 0) { virReportError(VIR_ERR_XML_ERROR, "%s", _("failed to get disk size from " "the disk descriptor xml")); goto cleanup; } def->target.capacity <<= 9; def->target.allocation = def->target.capacity; ret = 0; cleanup: xmlXPathFreeContext(ctxt); return ret; }
static int lxcContainerMountNewFS(virDomainDefPtr vmDef) { int i; /* Pull in rest of container's mounts */ for (i = 0 ; i < vmDef->nfss ; i++) { char *src; if (STREQ(vmDef->fss[i]->dst, "/")) continue; // XXX fix if (vmDef->fss[i]->type != VIR_DOMAIN_FS_TYPE_MOUNT) continue; if (virAsprintf(&src, "/.oldroot/%s", vmDef->fss[i]->src) < 0) { virReportOOMError(); return -1; } if (virFileMakePath(vmDef->fss[i]->dst) != 0) { virReportSystemError(errno, _("Failed to create %s"), vmDef->fss[i]->dst); VIR_FREE(src); return -1; } if (mount(src, vmDef->fss[i]->dst, NULL, MS_BIND, NULL) < 0) { virReportSystemError(errno, _("Failed to mount %s at %s"), src, vmDef->fss[i]->dst); VIR_FREE(src); return -1; } VIR_FREE(src); } 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_REALLOC_N(pool->volumes.objs, pool->volumes.count + 1) < 0) goto error; pool->volumes.objs[pool->volumes.count++] = def; return 0; no_memory: virReportOOMError(); error: virStorageVolDefFree(def); return -1; }
static int parallelsFindVolumes(virStoragePoolObjPtr pool) { DIR *dir; struct dirent *ent; char *path = NULL; int ret = -1; if (!(dir = opendir(pool->def->target.path))) { virReportSystemError(errno, _("cannot open path '%s'"), pool->def->target.path); return -1; } while ((ent = readdir(dir)) != NULL) { if (!virFileHasSuffix(ent->d_name, ".xml")) continue; if (!(path = virFileBuildPath(pool->def->target.path, ent->d_name, NULL))) { virReportOOMError(); goto cleanup; } if (!parallelsStorageVolDefineXML(pool, NULL, path, false)) goto cleanup; VIR_FREE(path); } ret = 0; cleanup: VIR_FREE(path); closedir(dir); return ret; }
/** * Create a full filename with path to the lock file based on * name/path of corresponding device * * @dev path of the character device * * Returns a modified name that the caller has to free, or NULL * on error. */ static char *virChrdevLockFilePath(const char *dev) { char *path = NULL; char *sanitizedPath = NULL; char *devCopy; char *filename; char *p; if (!(devCopy = strdup(dev))) { virReportOOMError(); goto cleanup; } /* skip the leading "/dev/" */ filename = STRSKIP(devCopy, "/dev"); if (!filename) filename = devCopy; /* substitute path forward slashes for underscores */ p = filename; while (*p) { if (*p == '/') *p = '_'; ++p; } if (virAsprintf(&path, "%s/LCK..%s", VIR_CHRDEV_LOCK_FILE_PATH, filename) < 0) goto cleanup; sanitizedPath = virFileSanitizePath(path); cleanup: VIR_FREE(path); VIR_FREE(devCopy); return sanitizedPath; }
/* Parse config values of the form barrier:limit into barrier and limit */ static int openvzParseBarrierLimit(const char* value, unsigned long long *barrier, unsigned long long *limit) { char *token; char *saveptr = NULL; char *str = strdup(value); if (str == NULL) { virReportOOMError(); goto error; } token = strtok_r(str, ":", &saveptr); if (token == NULL) { goto error; } else { if (barrier != NULL) { if (virStrToLong_ull(token, NULL, 10, barrier)) goto error; } } token = strtok_r(NULL, ":", &saveptr); if (token == NULL) { goto error; } else { if (limit != NULL) { if (virStrToLong_ull(token, NULL, 10, limit)) goto error; } } return 0; error: VIR_FREE(str); return -1; }
static char * virSysinfoParseDelimited(const char *base, const char *name, char **value, char delim1, char delim2) { const char *start; char *end; if (delim1 != delim2 && (start = strstr(base, name)) && (start = strchr(start, delim1))) { start += 1; end = strchrnul(start, delim2); virSkipSpaces(&start); if (!((*value) = strndup(start, end - start))) { virReportOOMError(); goto error; } virTrimSpaces(*value, NULL); return end; } error: return NULL; }
static char * vmwareGetOSType(virDomainPtr dom) { struct vmware_driver *driver = dom->conn->privateData; virDomainObjPtr vm; char *ret = NULL; vmwareDriverLock(driver); vm = virDomainObjListFindByUUID(driver->domains, dom->uuid); vmwareDriverUnlock(driver); if (!vm) { virReportError(VIR_ERR_NO_DOMAIN, NULL); goto cleanup; } if (!(ret = strdup(vm->def->os.type))) virReportOOMError(); cleanup: if (vm) virObjectUnlock(vm); return ret; }
static virStorageSourcePtr testStorageFileGetMetadata(const char *path, int format, uid_t uid, gid_t gid, bool allow_probe) { virStorageSourcePtr ret = NULL; if (VIR_ALLOC(ret) < 0) return NULL; ret->type = VIR_STORAGE_TYPE_FILE; ret->format = format; if (VIR_STRDUP(ret->relPath, path) < 0) goto error; if (!(ret->relDir = mdir_name(path))) { virReportOOMError(); goto error; } if (!(ret->path = canonicalize_file_name(path))) { virReportError(VIR_ERR_INTERNAL_ERROR, "failed to resolve '%s'", path); goto error; } if (virStorageFileGetMetadata(ret, uid, gid, allow_probe) < 0) goto error; return ret; error: virStorageSourceFree(ret); return NULL; }
static int virFDStreamOpenInternal(virStreamPtr st, int fd, virCommandPtr cmd, int errfd, unsigned long long length) { struct virFDStreamData *fdst; VIR_DEBUG("st=%p fd=%d cmd=%p errfd=%d length=%llu", st, fd, cmd, errfd, length); if ((st->flags & VIR_STREAM_NONBLOCK) && virSetNonBlock(fd) < 0) return -1; if (VIR_ALLOC(fdst) < 0) { virReportOOMError(); return -1; } fdst->fd = fd; fdst->cmd = cmd; fdst->errfd = errfd; fdst->length = length; if (virMutexInit(&fdst->lock) < 0) { VIR_FREE(fdst); streamsReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Unable to initialize mutex")); return -1; } st->driver = &virFDStreamDrv; st->privateData = fdst; return 0; }
static virDomainEventPtr virDomainEventTrayChangeNew(int id, const char *name, unsigned char *uuid, const char *devAlias, int reason) { virDomainEventPtr ev = virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_TRAY_CHANGE, id, name, uuid); if (ev) { if (!(ev->data.trayChange.devAlias = strdup(devAlias))) goto error; ev->data.trayChange.reason = reason; } return ev; error: virReportOOMError(); virDomainEventFree(ev); return NULL; }
static int virNetServerAddClient(virNetServerPtr srv, virNetServerClientPtr client) { virObjectLock(srv); if (srv->nclients >= srv->nclients_max) { virReportError(VIR_ERR_RPC, _("Too many active clients (%zu), dropping connection from %s"), srv->nclients_max, virNetServerClientRemoteAddrString(client)); goto error; } if (virNetServerClientInit(client) < 0) goto error; if (VIR_EXPAND_N(srv->clients, srv->nclients, 1) < 0) { virReportOOMError(); goto error; } srv->clients[srv->nclients-1] = client; virObjectRef(client); virNetServerClientSetDispatcher(client, virNetServerDispatchNewMessage, srv); virNetServerClientInitKeepAlive(client, srv->keepaliveInterval, srv->keepaliveCount); virObjectUnlock(srv); return 0; error: virObjectUnlock(srv); return -1; }