The virGetLastError() and virConnGetLastError() methods are not even remotely thread safe, and the virCopyLastError/virConnCopyLastError methods don't help in this goal, being open to a race condition. This patch changes the internal impl of the global error object to store its virError instance in a thread local variable. All errors are now reported against the global error object. In the public API entry points, we explicitly reset the global error object to ensure no stale errors are hanging around. In all error paths we also set a generic error, if the internal driver forget to set an explicit error. Finally we also copy the global error to the per connection error object for back-compatability, though the global object remains non-threadsafe for application access. src/datatypes.c | 31 src/datatypes.h | 15 src/libvirt.c | 3276 ++++++++++++++++++++++++++++++++--------------- src/virterror.c | 258 +++ src/virterror_internal.h | 5 tests/cpuset | 2 tests/read-bufsiz | 2 tests/start | 4 tests/undefine | 8 tests/vcpupin | 4 10 files changed, 2507 insertions(+), 1098 deletions(-) Daniel diff --git a/src/datatypes.c b/src/datatypes.c --- a/src/datatypes.c +++ b/src/datatypes.c @@ -195,8 +195,6 @@ virReleaseConnect(virConnectPtr conn) { virHashFree(conn->nodeDevices, (virHashDeallocator) virNodeDeviceFree); virResetError(&conn->err); - if (virLastErr.conn == conn) - virLastErr.conn = NULL; xmlFreeURI(conn->uri); @@ -219,7 +217,7 @@ virUnrefConnect(virConnectPtr conn) { int refs; if ((!VIR_IS_CONNECT(conn))) { - virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); return(-1); } virMutexLock(&conn->lock); @@ -253,7 +251,7 @@ virGetDomain(virConnectPtr conn, const c virDomainPtr ret = NULL; if ((!VIR_IS_CONNECT(conn)) || (name == NULL) || (uuid == NULL)) { - virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); return(NULL); } virMutexLock(&conn->lock); @@ -323,10 +321,6 @@ virReleaseDomain(virDomainPtr domain) { virLibConnError(conn, VIR_ERR_INTERNAL_ERROR, _("domain missing from connection hash table")); - if (conn->err.dom == domain) - conn->err.dom = NULL; - if (virLastErr.dom == domain) - virLastErr.dom = NULL; domain->magic = -1; domain->id = -1; VIR_FREE(domain->name); @@ -358,7 +352,7 @@ virUnrefDomain(virDomainPtr domain) { int refs; if (!VIR_IS_CONNECTED_DOMAIN(domain)) { - virLibConnError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); return(-1); } virMutexLock(&domain->conn->lock); @@ -393,7 +387,7 @@ virGetNetwork(virConnectPtr conn, const virNetworkPtr ret = NULL; if ((!VIR_IS_CONNECT(conn)) || (name == NULL) || (uuid == NULL)) { - virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); return(NULL); } virMutexLock(&conn->lock); @@ -459,11 +453,6 @@ virReleaseNetwork(virNetworkPtr network) virLibConnError(conn, VIR_ERR_INTERNAL_ERROR, _("network missing from connection hash table")); - if (conn->err.net == network) - conn->err.net = NULL; - if (virLastErr.net == network) - virLastErr.net = NULL; - network->magic = -1; VIR_FREE(network->name); VIR_FREE(network); @@ -494,7 +483,7 @@ virUnrefNetwork(virNetworkPtr network) { int refs; if (!VIR_IS_CONNECTED_NETWORK(network)) { - virLibConnError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); return(-1); } virMutexLock(&network->conn->lock); @@ -530,7 +519,7 @@ virGetStoragePool(virConnectPtr conn, co virStoragePoolPtr ret = NULL; if ((!VIR_IS_CONNECT(conn)) || (name == NULL) || (uuid == NULL)) { - virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); return(NULL); } virMutexLock(&conn->lock); @@ -627,7 +616,7 @@ virUnrefStoragePool(virStoragePoolPtr po int refs; if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) { - virLibConnError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); return(-1); } virMutexLock(&pool->conn->lock); @@ -664,7 +653,7 @@ virGetStorageVol(virConnectPtr conn, con virStorageVolPtr ret = NULL; if ((!VIR_IS_CONNECT(conn)) || (name == NULL) || (key == NULL)) { - virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); return(NULL); } virMutexLock(&conn->lock); @@ -765,7 +754,7 @@ virUnrefStorageVol(virStorageVolPtr vol) int refs; if (!VIR_IS_CONNECTED_STORAGE_VOL(vol)) { - virLibConnError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); return(-1); } virMutexLock(&vol->conn->lock); @@ -801,7 +790,7 @@ virGetNodeDevice(virConnectPtr conn, con virNodeDevicePtr ret = NULL; if ((!VIR_IS_CONNECT(conn)) || (name == NULL)) { - virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); return(NULL); } virMutexLock(&conn->lock); diff --git a/src/datatypes.h b/src/datatypes.h --- a/src/datatypes.h +++ b/src/datatypes.h @@ -95,6 +95,10 @@ * Internal structure associated to a connection */ struct _virConnect { + /* All the variables from here, until the 'lock' declaration + * are setup at time of connection open, and never changed + * since. Thus no need to lock when accessing them + */ unsigned int magic; /* specific value to check */ int flags; /* a set of connection flags */ xmlURIPtr uri; /* connection URI */ @@ -114,11 +118,6 @@ struct _virConnect { void * storagePrivateData; void * devMonPrivateData; - /* Per-connection error. */ - virError err; /* the last error */ - virErrorFunc handler; /* associated handlet */ - void *userData; /* the user data */ - /* * The lock mutex must be acquired before accessing/changing * any of members following this point, or changing the ref @@ -126,6 +125,12 @@ struct _virConnect { * this connection */ virMutex lock; + + /* Per-connection error. */ + virError err; /* the last error */ + virErrorFunc handler; /* associated handlet */ + void *userData; /* the user data */ + virHashTablePtr domains; /* hash table for known domains */ virHashTablePtr networks; /* hash table for known domains */ virHashTablePtr storagePools;/* hash table for known storage pools */ diff --git a/src/libvirt.c b/src/libvirt.c --- a/src/libvirt.c +++ b/src/libvirt.c @@ -256,7 +256,8 @@ virInitialize(void) initialized = 1; - if (virThreadInitialize() < 0) + if (virThreadInitialize() < 0 || + virErrorInitialize() < 0) return -1; #ifdef ENABLE_DEBUG @@ -847,6 +848,8 @@ do_open (const char *name, int i, res; virConnectPtr ret; + virResetLastError(); + ret = virGetConnect(); if (ret == NULL) return NULL; @@ -1000,17 +1003,8 @@ do_open (const char *name, failed: if (ret->driver) ret->driver->close (ret); - /* If no global error was set, copy any error set - in the connection object we're about to dispose of */ - if (virLastErr.code == VIR_ERR_OK) { - memcpy(&virLastErr, &ret->err, sizeof(ret->err)); - memset(&ret->err, 0, sizeof(ret->err)); - } - - /* Still no error set, then raise a generic error */ - if (virLastErr.code == VIR_ERR_OK) - virLibConnError (NULL, VIR_ERR_INTERNAL_ERROR, - _("unable to open connection")); + /* Ensure a global error is set in case driver forgot */ + virSetGlobalError(); virUnrefConnect(ret); @@ -1105,8 +1099,12 @@ virConnectClose(virConnectPtr conn) { DEBUG("conn=%p", conn); - if (!VIR_IS_CONNECT(conn)) - return (-1); + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + return (-1); + } if (conn->networkDriver) conn->networkDriver->close (conn); @@ -1128,12 +1126,20 @@ virConnectClose(virConnectPtr conn) int virDrvSupportsFeature (virConnectPtr conn, int feature) { + int ret; DEBUG("conn=%p, feature=%d", conn, feature); - if (!VIR_IS_CONNECT(conn)) - return (-1); - - return VIR_DRV_SUPPORTS_FEATURE (conn->driver, conn, feature); + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + return (-1); + } + + ret = VIR_DRV_SUPPORTS_FEATURE (conn->driver, conn, feature); + /* Copy to connection error object for back compatability */ + virSetConnError(conn); + return ret; } /** @@ -1153,6 +1159,8 @@ virConnectGetType(virConnectPtr conn) const char *ret; DEBUG("conn=%p", conn); + virResetLastError(); + if (!VIR_IS_CONNECT(conn)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); return (NULL); @@ -1183,20 +1191,30 @@ virConnectGetVersion(virConnectPtr conn, { DEBUG("conn=%p, hvVer=%p", conn, hvVer); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); - return (-1); + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + return -1; } if (hvVer == NULL) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); - } - - if (conn->driver->version) - return conn->driver->version (conn, hvVer); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + if (conn->driver->version) { + int ret = conn->driver->version (conn, hvVer); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return -1; } @@ -1217,15 +1235,25 @@ virConnectGetHostname (virConnectPtr con { DEBUG("conn=%p", conn); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); - return NULL; - } - - if (conn->driver->getHostname) - return conn->driver->getHostname (conn); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + return NULL; + } + + if (conn->driver->getHostname) { + char *ret = conn->driver->getHostname (conn); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return NULL; } @@ -1248,8 +1276,9 @@ char * virConnectGetURI (virConnectPtr conn) { char *name; - - DEBUG("conn=%p", conn); + DEBUG("conn=%p", conn); + + virResetLastError(); if (!VIR_IS_CONNECT(conn)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); @@ -1259,15 +1288,23 @@ virConnectGetURI (virConnectPtr conn) /* Drivers may override getURI, but if they don't then * we provide a default implementation. */ - if (conn->driver->getURI) - return conn->driver->getURI (conn); + if (conn->driver->getURI) { + name = conn->driver->getURI (conn); + if (!name) + goto error; + } name = (char *)xmlSaveUri(conn->uri); if (!name) { virLibConnError (conn, VIR_ERR_NO_MEMORY, __FUNCTION__); - return NULL; + goto error; } return name; + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); + return NULL; } /** @@ -1287,15 +1324,24 @@ virConnectGetMaxVcpus(virConnectPtr conn { DEBUG("conn=%p, type=%s", conn, type); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); - return (-1); - } - - if (conn->driver->getMaxVcpus) - return conn->driver->getMaxVcpus (conn, type); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + return -1; + } + + if (conn->driver->getMaxVcpus) { + int ret = conn->driver->getMaxVcpus (conn, type); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return -1; } @@ -1314,20 +1360,29 @@ virConnectListDomains(virConnectPtr conn { DEBUG("conn=%p, ids=%p, maxids=%d", conn, ids, maxids); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); - return (-1); + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + return -1; } if ((ids == NULL) || (maxids < 0)) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); - } - - if (conn->driver->listDomains) - return conn->driver->listDomains (conn, ids, maxids); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + if (conn->driver->listDomains) { + int ret = conn->driver->listDomains (conn, ids, maxids); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return -1; } @@ -1344,15 +1399,24 @@ virConnectNumOfDomains(virConnectPtr con { DEBUG("conn=%p", conn); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); - return (-1); - } - - if (conn->driver->numOfDomains) - return conn->driver->numOfDomains (conn); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + goto error; + } + + if (conn->driver->numOfDomains) { + int ret = conn->driver->numOfDomains (conn); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return -1; } @@ -1375,7 +1439,9 @@ virDomainGetConnect (virDomainPtr dom) { DEBUG("dom=%p", dom); - if (!VIR_IS_DOMAIN (dom)) { + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN (dom)) { virLibDomainError (NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); return NULL; } @@ -1403,23 +1469,33 @@ virDomainCreateXML(virConnectPtr conn, c { DEBUG("conn=%p, xmlDesc=%s, flags=%d", conn, xmlDesc, flags); + virResetLastError(); + if (!VIR_IS_CONNECT(conn)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); return (NULL); } if (xmlDesc == NULL) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (NULL); - } - if (conn->flags & VIR_CONNECT_RO) { - virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (NULL); - } - - if (conn->driver->domainCreateXML) - return conn->driver->domainCreateXML (conn, xmlDesc, flags); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + if (conn->flags & VIR_CONNECT_RO) { + virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + if (conn->driver->domainCreateXML) { + virDomainPtr ret; + ret = conn->driver->domainCreateXML (conn, xmlDesc, flags); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return NULL; } @@ -1459,19 +1535,30 @@ virDomainLookupByID(virConnectPtr conn, { DEBUG("conn=%p, id=%d", conn, id); + virResetLastError(); + if (!VIR_IS_CONNECT(conn)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); return (NULL); } if (id < 0) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (NULL); - } - - if (conn->driver->domainLookupByID) - return conn->driver->domainLookupByID (conn, id); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + if (conn->driver->domainLookupByID) { + virDomainPtr ret; + ret = conn->driver->domainLookupByID (conn, id); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return NULL; } @@ -1490,19 +1577,30 @@ virDomainLookupByUUID(virConnectPtr conn { DEBUG("conn=%p, uuid=%s", conn, uuid); + virResetLastError(); + if (!VIR_IS_CONNECT(conn)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); return (NULL); } if (uuid == NULL) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (NULL); - } - - if (conn->driver->domainLookupByUUID) - return conn->driver->domainLookupByUUID (conn, uuid); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + if (conn->driver->domainLookupByUUID) { + virDomainPtr ret; + ret = conn->driver->domainLookupByUUID (conn, uuid); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return NULL; } @@ -1525,14 +1623,15 @@ virDomainLookupByUUIDString(virConnectPt DEBUG("conn=%p, uuidstr=%s", conn, uuidstr); + virResetLastError(); + if (!VIR_IS_CONNECT(conn)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); return (NULL); } if (uuidstr == NULL) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (NULL); - + goto error; } /* XXX: sexpr_uuid() also supports 'xxxx-xxxx-xxxx-xxxx' format. * We needn't it here. Right? @@ -1550,12 +1649,17 @@ virDomainLookupByUUIDString(virConnectPt if (ret!=VIR_UUID_BUFLEN) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (NULL); + goto error; } for (i = 0; i < VIR_UUID_BUFLEN; i++) uuid[i] = raw[i] & 0xFF; return virDomainLookupByUUID(conn, &uuid[0]); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); + return NULL; } /** @@ -1573,19 +1677,30 @@ virDomainLookupByName(virConnectPtr conn { DEBUG("conn=%p, name=%s", conn, name); + virResetLastError(); + if (!VIR_IS_CONNECT(conn)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); return (NULL); } if (name == NULL) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (NULL); - } - - if (conn->driver->domainLookupByName) - return conn->driver->domainLookupByName (conn, name); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + if (conn->driver->domainLookupByName) { + virDomainPtr dom; + dom = conn->driver->domainLookupByName (conn, name); + if (!dom) + goto error; + return dom; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return NULL; } @@ -1607,21 +1722,32 @@ virDomainDestroy(virDomainPtr domain) DEBUG("domain=%p", domain); - if (!VIR_IS_CONNECTED_DOMAIN(domain)) { - virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); - return (-1); - } - - conn = domain->conn; - if (conn->flags & VIR_CONNECT_RO) { - virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); - } - - if (conn->driver->domainDestroy) - return conn->driver->domainDestroy (domain); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + return (-1); + } + + conn = domain->conn; + if (conn->flags & VIR_CONNECT_RO) { + virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + if (conn->driver->domainDestroy) { + int ret; + ret = conn->driver->domainDestroy (domain); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return -1; } @@ -1639,12 +1765,14 @@ virDomainFree(virDomainPtr domain) { DEBUG("domain=%p", domain); - if (!VIR_IS_DOMAIN(domain)) { + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); return (-1); } if (virUnrefDomain(domain) < 0) - return (-1); + return -1; return(0); } @@ -1666,21 +1794,32 @@ virDomainSuspend(virDomainPtr domain) virConnectPtr conn; DEBUG("domain=%p", domain); - if (!VIR_IS_CONNECTED_DOMAIN(domain)) { - virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); - return (-1); - } - if (domain->conn->flags & VIR_CONNECT_RO) { - virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); - } - - conn = domain->conn; - - if (conn->driver->domainSuspend) - return conn->driver->domainSuspend (domain); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + return (-1); + } + if (domain->conn->flags & VIR_CONNECT_RO) { + virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + conn = domain->conn; + + if (conn->driver->domainSuspend) { + int ret; + ret = conn->driver->domainSuspend (domain); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(domain->conn); return -1; } @@ -1700,21 +1839,32 @@ virDomainResume(virDomainPtr domain) virConnectPtr conn; DEBUG("domain=%p", domain); - if (!VIR_IS_CONNECTED_DOMAIN(domain)) { - virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); - return (-1); - } - if (domain->conn->flags & VIR_CONNECT_RO) { - virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); - } - - conn = domain->conn; - - if (conn->driver->domainResume) - return conn->driver->domainResume (domain); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + return (-1); + } + if (domain->conn->flags & VIR_CONNECT_RO) { + virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + conn = domain->conn; + + if (conn->driver->domainResume) { + int ret; + ret = conn->driver->domainResume (domain); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(domain->conn); return -1; } @@ -1737,18 +1887,20 @@ virDomainSave(virDomainPtr domain, const virConnectPtr conn; DEBUG("domain=%p, to=%s", domain, to); - if (!VIR_IS_CONNECTED_DOMAIN(domain)) { - virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); - return (-1); - } - if (domain->conn->flags & VIR_CONNECT_RO) { - virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + return (-1); + } + if (domain->conn->flags & VIR_CONNECT_RO) { + virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; } conn = domain->conn; if (to == NULL) { virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); + goto error; } /* @@ -1771,10 +1923,19 @@ virDomainSave(virDomainPtr domain, const } - if (conn->driver->domainSave) - return conn->driver->domainSave (domain, to); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + if (conn->driver->domainSave) { + int ret; + ret = conn->driver->domainSave (domain, to); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(domain->conn); return -1; } @@ -1793,17 +1954,19 @@ virDomainRestore(virConnectPtr conn, con char filepath[4096]; DEBUG("conn=%p, from=%s", conn, from); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); - return (-1); - } - if (conn->flags & VIR_CONNECT_RO) { - virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + return (-1); + } + if (conn->flags & VIR_CONNECT_RO) { + virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; } if (from == NULL) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); + goto error; } /* @@ -1814,21 +1977,36 @@ virDomainRestore(virConnectPtr conn, con unsigned int len, t; t = strlen(from); - if (getcwd(filepath, sizeof(filepath) - (t + 3)) == NULL) - return (-1); + if (getcwd(filepath, sizeof(filepath) - (t + 3)) == NULL) { + virLibConnError(conn, VIR_ERR_SYSTEM_ERROR, + _("cannot get working directory")); + goto error; + } len = strlen(filepath); /* that should be covered by getcwd() semantic, but be 100% sure */ - if (len > sizeof(filepath) - (t + 3)) - return (-1); + if (len > sizeof(filepath) - (t + 3)) { + virLibConnError(conn, VIR_ERR_INTERNAL_ERROR, + _("path too long")); + goto error; + } filepath[len] = '/'; strcpy(&filepath[len + 1], from); from = &filepath[0]; } - if (conn->driver->domainRestore) - return conn->driver->domainRestore (conn, from); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + if (conn->driver->domainRestore) { + int ret; + ret = conn->driver->domainRestore (conn, from); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return -1; } @@ -1851,18 +2029,20 @@ virDomainCoreDump(virDomainPtr domain, c virConnectPtr conn; DEBUG("domain=%p, to=%s, flags=%d", domain, to, flags); - if (!VIR_IS_CONNECTED_DOMAIN(domain)) { - virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); - return (-1); - } - if (domain->conn->flags & VIR_CONNECT_RO) { - virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + return (-1); + } + if (domain->conn->flags & VIR_CONNECT_RO) { + virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; } conn = domain->conn; if (to == NULL) { virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); + goto error; } /* @@ -1873,22 +2053,37 @@ virDomainCoreDump(virDomainPtr domain, c unsigned int len, t; t = strlen(to); - if (getcwd(filepath, sizeof(filepath) - (t + 3)) == NULL) - return (-1); + if (getcwd(filepath, sizeof(filepath) - (t + 3)) == NULL) { + virLibDomainError(domain, VIR_ERR_SYSTEM_ERROR, + _("cannot get current directory")); + goto error; + } len = strlen(filepath); /* that should be covered by getcwd() semantic, but be 100% sure */ - if (len > sizeof(filepath) - (t + 3)) - return (-1); + if (len > sizeof(filepath) - (t + 3)) { + virLibDomainError(domain, VIR_ERR_INTERNAL_ERROR, + _("path too long")); + goto error; + } filepath[len] = '/'; strcpy(&filepath[len + 1], to); to = &filepath[0]; } - if (conn->driver->domainCoreDump) - return conn->driver->domainCoreDump (domain, to, flags); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + if (conn->driver->domainCoreDump) { + int ret; + ret = conn->driver->domainCoreDump (domain, to, flags); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(domain->conn); return -1; } @@ -1911,21 +2106,32 @@ virDomainShutdown(virDomainPtr domain) virConnectPtr conn; DEBUG("domain=%p", domain); - if (!VIR_IS_CONNECTED_DOMAIN(domain)) { - virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); - return (-1); - } - if (domain->conn->flags & VIR_CONNECT_RO) { - virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); - } - - conn = domain->conn; - - if (conn->driver->domainShutdown) - return conn->driver->domainShutdown (domain); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + return (-1); + } + if (domain->conn->flags & VIR_CONNECT_RO) { + virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + conn = domain->conn; + + if (conn->driver->domainShutdown) { + int ret; + ret = conn->driver->domainShutdown (domain); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(domain->conn); return -1; } @@ -1946,21 +2152,32 @@ virDomainReboot(virDomainPtr domain, uns virConnectPtr conn; DEBUG("domain=%p, flags=%u", domain, flags); - if (!VIR_IS_CONNECTED_DOMAIN(domain)) { - virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); - return (-1); - } - if (domain->conn->flags & VIR_CONNECT_RO) { - virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); - } - - conn = domain->conn; - - if (conn->driver->domainReboot) - return conn->driver->domainReboot (domain, flags); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + return (-1); + } + if (domain->conn->flags & VIR_CONNECT_RO) { + virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + conn = domain->conn; + + if (conn->driver->domainReboot) { + int ret; + ret = conn->driver->domainReboot (domain, flags); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(domain->conn); return -1; } @@ -1978,6 +2195,8 @@ virDomainGetName(virDomainPtr domain) { DEBUG("domain=%p", domain); + virResetLastError(); + if (!VIR_IS_DOMAIN(domain)) { virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); return (NULL); @@ -1999,12 +2218,16 @@ virDomainGetUUID(virDomainPtr domain, un { DEBUG("domain=%p, uuid=%p", domain, uuid); + virResetLastError(); + if (!VIR_IS_DOMAIN(domain)) { virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); return (-1); } if (uuid == NULL) { virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virSetConnError(domain->conn); return (-1); } @@ -2029,20 +2252,27 @@ virDomainGetUUIDString(virDomainPtr doma unsigned char uuid[VIR_UUID_BUFLEN]; DEBUG("domain=%p, buf=%p", domain, buf); + virResetLastError(); + if (!VIR_IS_DOMAIN(domain)) { virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); return (-1); } if (buf == NULL) { virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); + goto error; } if (virDomainGetUUID(domain, &uuid[0])) - return (-1); + goto error; virUUIDFormat(uuid, buf); return (0); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(domain->conn); + return -1; } /** @@ -2058,6 +2288,8 @@ virDomainGetID(virDomainPtr domain) { DEBUG("domain=%p", domain); + virResetLastError(); + if (!VIR_IS_DOMAIN(domain)) { virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); return ((unsigned int) -1); @@ -2080,17 +2312,28 @@ virDomainGetOSType(virDomainPtr domain) virConnectPtr conn; DEBUG("domain=%p", domain); - if (!VIR_IS_DOMAIN(domain)) { - virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); - return (NULL); - } - - conn = domain->conn; - - if (conn->driver->domainGetOSType) - return conn->driver->domainGetOSType (domain); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + return (NULL); + } + + conn = domain->conn; + + if (conn->driver->domainGetOSType) { + char *ret; + ret = conn->driver->domainGetOSType (domain); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(domain->conn); return NULL; } @@ -2110,6 +2353,8 @@ virDomainGetMaxMemory(virDomainPtr domai virConnectPtr conn; DEBUG("domain=%p", domain); + virResetLastError(); + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); return (0); @@ -2117,10 +2362,19 @@ virDomainGetMaxMemory(virDomainPtr domai conn = domain->conn; - if (conn->driver->domainGetMaxMemory) - return conn->driver->domainGetMaxMemory (domain); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + if (conn->driver->domainGetMaxMemory) { + unsigned long ret; + ret = conn->driver->domainGetMaxMemory (domain); + if (ret == 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(domain->conn); return 0; } @@ -2142,28 +2396,35 @@ virDomainSetMaxMemory(virDomainPtr domai virConnectPtr conn; DEBUG("domain=%p, memory=%lu", domain, memory); - if (domain == NULL) { - TODO - return (-1); - } - if (!VIR_IS_CONNECTED_DOMAIN(domain)) { - virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); - return (-1); - } - if (domain->conn->flags & VIR_CONNECT_RO) { - virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + return (-1); + } + if (domain->conn->flags & VIR_CONNECT_RO) { + virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; } if (memory < 4096) { virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); - } - conn = domain->conn; - - if (conn->driver->domainSetMaxMemory) - return conn->driver->domainSetMaxMemory (domain, memory); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + conn = domain->conn; + + if (conn->driver->domainSetMaxMemory) { + int ret; + ret = conn->driver->domainSetMaxMemory (domain, memory); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(domain->conn); return -1; } @@ -2185,29 +2446,36 @@ virDomainSetMemory(virDomainPtr domain, virConnectPtr conn; DEBUG("domain=%p, memory=%lu", domain, memory); - if (domain == NULL) { - TODO - return (-1); - } - if (!VIR_IS_CONNECTED_DOMAIN(domain)) { - virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); - return (-1); - } - if (domain->conn->flags & VIR_CONNECT_RO) { - virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + return (-1); + } + if (domain->conn->flags & VIR_CONNECT_RO) { + virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; } if (memory < 4096) { virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); - } - - conn = domain->conn; - - if (conn->driver->domainSetMemory) - return conn->driver->domainSetMemory (domain, memory); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + conn = domain->conn; + + if (conn->driver->domainSetMemory) { + int ret; + ret = conn->driver->domainSetMemory (domain, memory); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(domain->conn); return -1; } @@ -2228,23 +2496,34 @@ virDomainGetInfo(virDomainPtr domain, vi virConnectPtr conn; DEBUG("domain=%p, info=%p", domain, info); + virResetLastError(); + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); return (-1); } if (info == NULL) { virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); + goto error; } memset(info, 0, sizeof(virDomainInfo)); conn = domain->conn; - if (conn->driver->domainGetInfo) - return conn->driver->domainGetInfo (domain, info); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + if (conn->driver->domainGetInfo) { + int ret; + ret = conn->driver->domainGetInfo (domain, info); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(domain->conn); return -1; } @@ -2265,17 +2544,28 @@ virDomainGetXMLDesc(virDomainPtr domain, virConnectPtr conn; DEBUG("domain=%p, flags=%d", domain, flags); - if (!VIR_IS_DOMAIN(domain)) { - virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); - return (NULL); - } - - conn = domain->conn; - - if (conn->driver->domainDumpXML) - return conn->driver->domainDumpXML (domain, flags); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + return (NULL); + } + + conn = domain->conn; + + if (conn->driver->domainDumpXML) { + char *ret; + ret = conn->driver->domainDumpXML (domain, flags); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(domain->conn); return NULL; } @@ -2344,24 +2634,26 @@ virDomainMigrate (virDomainPtr domain, DEBUG("domain=%p, dconn=%p, flags=%lu, dname=%s, uri=%s, bandwidth=%lu", domain, dconn, flags, dname, uri, bandwidth); - if (!VIR_IS_DOMAIN (domain)) { + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN (domain)) { virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); return NULL; } conn = domain->conn; /* Source connection. */ if (!VIR_IS_CONNECT (dconn)) { virLibConnError (conn, VIR_ERR_INVALID_CONN, __FUNCTION__); - return NULL; - } - - if (domain->conn->flags & VIR_CONNECT_RO) { - virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return NULL; + goto error; + } + + if (domain->conn->flags & VIR_CONNECT_RO) { + virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; } if (dconn->flags & VIR_CONNECT_RO) { /* NB, delibrately report error against source object, not dest here */ virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return NULL; + goto error; } /* Check that migration is supported by both drivers. */ @@ -2377,7 +2669,7 @@ virDomainMigrate (virDomainPtr domain, version = 2; else { virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); - return NULL; + goto error; } /* Prepare the migration. @@ -2412,13 +2704,13 @@ virDomainMigrate (virDomainPtr domain, */ if (!conn->driver->domainDumpXML) { virLibConnError (conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__); - return NULL; + goto error; } dom_xml = conn->driver->domainDumpXML (domain, VIR_DOMAIN_XML_SECURE); if (!dom_xml) - return NULL; + goto error; ret = dconn->driver->domainMigratePrepare2 (dconn, &cookie, &cookielen, uri, &uri_out, flags, dname, @@ -2468,6 +2760,11 @@ virDomainMigrate (virDomainPtr domain, free (uri_out); free (cookie); return ddomain; + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(domain->conn); + return NULL; } /* @@ -2486,6 +2783,8 @@ virDomainMigratePrepare (virConnectPtr d { DEBUG("dconn=%p, cookie=%p, cookielen=%p, uri_in=%s, uri_out=%p, flags=%lu, dname=%s, bandwidth=%lu", dconn, cookie, cookielen, uri_in, uri_out, flags, dname, bandwidth); + virResetLastError(); + if (!VIR_IS_CONNECT (dconn)) { virLibConnError (NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); return -1; @@ -2493,15 +2792,24 @@ virDomainMigratePrepare (virConnectPtr d if (dconn->flags & VIR_CONNECT_RO) { virLibConnError(dconn, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return -1; - } - - if (dconn->driver->domainMigratePrepare) - return dconn->driver->domainMigratePrepare (dconn, cookie, cookielen, - uri_in, uri_out, - flags, dname, bandwidth); + goto error; + } + + if (dconn->driver->domainMigratePrepare) { + int ret; + ret = dconn->driver->domainMigratePrepare (dconn, cookie, cookielen, + uri_in, uri_out, + flags, dname, bandwidth); + if (ret < 0) + goto error; + return ret; + } virLibConnError (dconn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(dconn); return -1; } @@ -2521,7 +2829,9 @@ virDomainMigratePerform (virDomainPtr do virConnectPtr conn; DEBUG("domain=%p, cookie=%p, cookielen=%d, uri=%s, flags=%lu, dname=%s, bandwidth=%lu", domain, cookie, cookielen, uri, flags, dname, bandwidth); - if (!VIR_IS_DOMAIN (domain)) { + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN (domain)) { virLibDomainError (NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); return -1; } @@ -2529,15 +2839,24 @@ virDomainMigratePerform (virDomainPtr do if (domain->conn->flags & VIR_CONNECT_RO) { virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return -1; - } - - if (conn->driver->domainMigratePerform) - return conn->driver->domainMigratePerform (domain, cookie, cookielen, - uri, - flags, dname, bandwidth); + goto error; + } + + if (conn->driver->domainMigratePerform) { + int ret; + ret = conn->driver->domainMigratePerform (domain, cookie, cookielen, + uri, + flags, dname, bandwidth); + if (ret < 0) + goto error; + return ret; + } virLibDomainError (domain, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(domain->conn); return -1; } @@ -2555,6 +2874,8 @@ virDomainMigrateFinish (virConnectPtr dc { DEBUG("dconn=%p, dname=%s, cookie=%p, cookielen=%d, uri=%s, flags=%lu", dconn, dname, cookie, cookielen, uri, flags); + virResetLastError(); + if (!VIR_IS_CONNECT (dconn)) { virLibConnError (NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); return NULL; @@ -2562,15 +2883,24 @@ virDomainMigrateFinish (virConnectPtr dc if (dconn->flags & VIR_CONNECT_RO) { virLibConnError(dconn, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return NULL; - } - - if (dconn->driver->domainMigrateFinish) - return dconn->driver->domainMigrateFinish (dconn, dname, - cookie, cookielen, - uri, flags); + goto error; + } + + if (dconn->driver->domainMigrateFinish) { + virDomainPtr ret; + ret = dconn->driver->domainMigrateFinish (dconn, dname, + cookie, cookielen, + uri, flags); + if (!ret) + goto error; + return ret; + } virLibConnError (dconn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(dconn); return NULL; } @@ -2592,6 +2922,8 @@ virDomainMigratePrepare2 (virConnectPtr { DEBUG("dconn=%p, cookie=%p, cookielen=%p, uri_in=%s, uri_out=%p, flags=%lu, dname=%s, bandwidth=%lu, dom_xml=%s", dconn, cookie, cookielen, uri_in, uri_out, flags, dname, bandwidth, dom_xml); + virResetLastError(); + if (!VIR_IS_CONNECT (dconn)) { virLibConnError (NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); return -1; @@ -2599,16 +2931,25 @@ virDomainMigratePrepare2 (virConnectPtr if (dconn->flags & VIR_CONNECT_RO) { virLibConnError(dconn, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return -1; - } - - if (dconn->driver->domainMigratePrepare2) - return dconn->driver->domainMigratePrepare2 (dconn, cookie, cookielen, - uri_in, uri_out, - flags, dname, bandwidth, - dom_xml); + goto error; + } + + if (dconn->driver->domainMigratePrepare2) { + int ret; + ret = dconn->driver->domainMigratePrepare2 (dconn, cookie, cookielen, + uri_in, uri_out, + flags, dname, bandwidth, + dom_xml); + if (ret < 0) + goto error; + return ret; + } virLibConnError (dconn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(dconn); return -1; } @@ -2627,6 +2968,8 @@ virDomainMigrateFinish2 (virConnectPtr d { DEBUG("dconn=%p, dname=%s, cookie=%p, cookielen=%d, uri=%s, flags=%lu, retcode=%d", dconn, dname, cookie, cookielen, uri, flags, retcode); + virResetLastError(); + if (!VIR_IS_CONNECT (dconn)) { virLibConnError (NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); return NULL; @@ -2634,16 +2977,25 @@ virDomainMigrateFinish2 (virConnectPtr d if (dconn->flags & VIR_CONNECT_RO) { virLibConnError(dconn, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return NULL; - } - - if (dconn->driver->domainMigrateFinish2) - return dconn->driver->domainMigrateFinish2 (dconn, dname, - cookie, cookielen, - uri, flags, - retcode); + goto error; + } + + if (dconn->driver->domainMigrateFinish2) { + virDomainPtr ret; + ret = dconn->driver->domainMigrateFinish2 (dconn, dname, + cookie, cookielen, + uri, flags, + retcode); + if (!ret) + goto error; + return ret; + } virLibConnError (dconn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(dconn); return NULL; } @@ -2662,19 +3014,30 @@ virNodeGetInfo(virConnectPtr conn, virNo { DEBUG("conn=%p, info=%p", conn, info); + virResetLastError(); + if (!VIR_IS_CONNECT(conn)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); return (-1); } if (info == NULL) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); - } - - if (conn->driver->nodeGetInfo) - return conn->driver->nodeGetInfo (conn, info); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + if (conn->driver->nodeGetInfo) { + int ret; + ret = conn->driver->nodeGetInfo (conn, info); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return -1; } @@ -2693,15 +3056,26 @@ virConnectGetCapabilities (virConnectPtr { DEBUG("conn=%p", conn); + virResetLastError(); + if (!VIR_IS_CONNECT (conn)) { virLibConnError (NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); return NULL; } - if (conn->driver->getCapabilities) - return conn->driver->getCapabilities (conn); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + if (conn->driver->getCapabilities) { + char *ret; + ret = conn->driver->getCapabilities (conn); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return NULL; } @@ -2718,15 +3092,26 @@ virNodeGetFreeMemory(virConnectPtr conn) { DEBUG("conn=%p", conn); + virResetLastError(); + if (!VIR_IS_CONNECT (conn)) { virLibConnError (NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); return 0; } - if (conn->driver->getFreeMemory) - return conn->driver->getFreeMemory (conn); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + if (conn->driver->getFreeMemory) { + unsigned long long ret; + ret = conn->driver->getFreeMemory (conn); + if (ret == 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return 0; } @@ -2746,6 +3131,8 @@ virDomainGetSchedulerType(virDomainPtr d char *schedtype; DEBUG("domain=%p, nparams=%p", domain, nparams); + virResetLastError(); + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); return NULL; @@ -2754,10 +3141,16 @@ virDomainGetSchedulerType(virDomainPtr d if (conn->driver->domainGetSchedulerType){ schedtype = conn->driver->domainGetSchedulerType (domain, nparams); + if (!schedtype) + goto error; return schedtype; } virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(domain->conn); return NULL; } @@ -2783,16 +3176,27 @@ virDomainGetSchedulerParameters(virDomai virConnectPtr conn; DEBUG("domain=%p, params=%p, nparams=%p", domain, params, nparams); - if (!VIR_IS_CONNECTED_DOMAIN(domain)) { - virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); - return -1; - } - conn = domain->conn; - - if (conn->driver->domainGetSchedulerParameters) - return conn->driver->domainGetSchedulerParameters (domain, params, nparams); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + return -1; + } + conn = domain->conn; + + if (conn->driver->domainGetSchedulerParameters) { + int ret; + ret = conn->driver->domainGetSchedulerParameters (domain, params, nparams); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(domain->conn); return -1; } @@ -2815,20 +3219,31 @@ virDomainSetSchedulerParameters(virDomai virConnectPtr conn; DEBUG("domain=%p, params=%p, nparams=%d", domain, params, nparams); - if (!VIR_IS_CONNECTED_DOMAIN(domain)) { - virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); - return -1; - } - if (domain->conn->flags & VIR_CONNECT_RO) { - virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return -1; - } - conn = domain->conn; - - if (conn->driver->domainSetSchedulerParameters) - return conn->driver->domainSetSchedulerParameters (domain, params, nparams); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + return -1; + } + if (domain->conn->flags & VIR_CONNECT_RO) { + virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + conn = domain->conn; + + if (conn->driver->domainSetSchedulerParameters) { + int ret; + ret = conn->driver->domainSetSchedulerParameters (domain, params, nparams); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(domain->conn); return -1; } @@ -2864,25 +3279,31 @@ virDomainBlockStats (virDomainPtr dom, c struct _virDomainBlockStats stats2 = { -1, -1, -1, -1, -1 }; DEBUG("domain=%p, path=%s, stats=%p, size=%zi", dom, path, stats, size); + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN (dom)) { + virLibDomainError (NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + return -1; + } if (!stats || size > sizeof stats2) { virLibDomainError (dom, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; - } - if (!VIR_IS_CONNECTED_DOMAIN (dom)) { - virLibDomainError (NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); - return -1; + goto error; } conn = dom->conn; if (conn->driver->domainBlockStats) { if (conn->driver->domainBlockStats (dom, path, &stats2) == -1) - return -1; + goto error; memcpy (stats, &stats2, size); return 0; } virLibDomainError (dom, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(dom->conn); return -1; } @@ -2916,25 +3337,31 @@ virDomainInterfaceStats (virDomainPtr do -1, -1, -1, -1 }; DEBUG("domain=%p, path=%s, stats=%p, size=%zi", dom, path, stats, size); + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN (dom)) { + virLibDomainError (NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + return -1; + } if (!stats || size > sizeof stats2) { virLibDomainError (dom, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; - } - if (!VIR_IS_CONNECTED_DOMAIN (dom)) { - virLibDomainError (NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); - return -1; + goto error; } conn = dom->conn; if (conn->driver->domainInterfaceStats) { if (conn->driver->domainInterfaceStats (dom, path, &stats2) == -1) - return -1; + goto error; memcpy (stats, &stats2, size); return 0; } virLibDomainError (dom, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(dom->conn); return -1; } @@ -2989,6 +3416,8 @@ virDomainBlockPeek (virDomainPtr dom, DEBUG("domain=%p, path=%s, offset=%lld, size=%zi, buffer=%p", dom, path, offset, size, buffer); + virResetLastError(); + if (!VIR_IS_CONNECTED_DOMAIN (dom)) { virLibDomainError (NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); return -1; @@ -2997,33 +3426,42 @@ virDomainBlockPeek (virDomainPtr dom, if (dom->conn->flags & VIR_CONNECT_RO) { virLibDomainError(dom, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); + goto error; } if (!path) { virLibDomainError (dom, VIR_ERR_INVALID_ARG, _("path is NULL")); - return -1; + goto error; } if (flags != 0) { virLibDomainError (dom, VIR_ERR_INVALID_ARG, _("flags must be zero")); - return -1; + goto error; } /* Allow size == 0 as an access test. */ if (size > 0 && !buffer) { virLibDomainError (dom, VIR_ERR_INVALID_ARG, _("buffer is NULL")); - return -1; - } - - if (conn->driver->domainBlockPeek) - return conn->driver->domainBlockPeek (dom, path, offset, size, - buffer, flags); + goto error; + } + + if (conn->driver->domainBlockPeek) { + int ret; + ret =conn->driver->domainBlockPeek (dom, path, offset, size, + buffer, flags); + if (ret < 0) + goto error; + return ret; + } virLibDomainError (dom, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(dom->conn); return -1; } @@ -3069,6 +3507,8 @@ virDomainMemoryPeek (virDomainPtr dom, DEBUG ("domain=%p, start=%lld, size=%zi, buffer=%p, flags=%d", dom, start, size, buffer, flags); + virResetLastError(); + if (!VIR_IS_CONNECTED_DOMAIN (dom)) { virLibDomainError (NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); return -1; @@ -3077,7 +3517,7 @@ virDomainMemoryPeek (virDomainPtr dom, if (dom->conn->flags & VIR_CONNECT_RO) { virLibDomainError(dom, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); + goto error; } /* Flags must be VIR_MEMORY_VIRTUAL at the moment. @@ -3104,21 +3544,30 @@ virDomainMemoryPeek (virDomainPtr dom, if (flags != VIR_MEMORY_VIRTUAL) { virLibDomainError (dom, VIR_ERR_INVALID_ARG, _("flags parameter must be VIR_MEMORY_VIRTUAL")); - return -1; + goto error; } /* Allow size == 0 as an access test. */ if (size > 0 && !buffer) { virLibDomainError (dom, VIR_ERR_INVALID_ARG, _("buffer is NULL but size is non-zero")); - return -1; - } - - if (conn->driver->domainMemoryPeek) - return conn->driver->domainMemoryPeek (dom, start, size, - buffer, flags); + goto error; + } + + if (conn->driver->domainMemoryPeek) { + int ret; + ret = conn->driver->domainMemoryPeek (dom, start, size, + buffer, flags); + if (ret < 0) + goto error; + return ret; + } virLibDomainError (dom, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(dom->conn); return -1; } @@ -3144,23 +3593,34 @@ virDomainPtr virDomainDefineXML(virConnectPtr conn, const char *xml) { DEBUG("conn=%p, xml=%s", conn, xml); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); - return (NULL); - } - if (conn->flags & VIR_CONNECT_RO) { - virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (NULL); + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + return (NULL); + } + if (conn->flags & VIR_CONNECT_RO) { + virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; } if (xml == NULL) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (NULL); - } - - if (conn->driver->domainDefineXML) - return conn->driver->domainDefineXML (conn, xml); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + if (conn->driver->domainDefineXML) { + virDomainPtr ret; + ret = conn->driver->domainDefineXML (conn, xml); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return NULL; } @@ -3177,20 +3637,31 @@ virDomainUndefine(virDomainPtr domain) { virConnectPtr conn; DEBUG("domain=%p", domain); - if (!VIR_IS_CONNECTED_DOMAIN(domain)) { - virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); - return (-1); - } - conn = domain->conn; - if (conn->flags & VIR_CONNECT_RO) { - virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); - } - - if (conn->driver->domainUndefine) - return conn->driver->domainUndefine (domain); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + return (-1); + } + conn = domain->conn; + if (conn->flags & VIR_CONNECT_RO) { + virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + if (conn->driver->domainUndefine) { + int ret; + ret = conn->driver->domainUndefine (domain); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(domain->conn); return -1; } @@ -3207,15 +3678,26 @@ virConnectNumOfDefinedDomains(virConnect { DEBUG("conn=%p", conn); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); - return (-1); - } - - if (conn->driver->numOfDefinedDomains) - return conn->driver->numOfDefinedDomains (conn); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + return (-1); + } + + if (conn->driver->numOfDefinedDomains) { + int ret; + ret = conn->driver->numOfDefinedDomains (conn); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return -1; } @@ -3235,6 +3717,8 @@ virConnectListDefinedDomains(virConnectP int maxnames) { DEBUG("conn=%p, names=%p, maxnames=%d", conn, names, maxnames); + virResetLastError(); + if (!VIR_IS_CONNECT(conn)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); return (-1); @@ -3242,13 +3726,22 @@ virConnectListDefinedDomains(virConnectP if ((names == NULL) || (maxnames < 0)) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); - } - - if (conn->driver->listDefinedDomains) - return conn->driver->listDefinedDomains (conn, names, maxnames); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + if (conn->driver->listDefinedDomains) { + int ret; + ret = conn->driver->listDefinedDomains (conn, names, maxnames); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return -1; } @@ -3266,24 +3759,31 @@ virDomainCreate(virDomainPtr domain) { virConnectPtr conn; DEBUG("domain=%p", domain); - if (domain == NULL) { - TODO - return (-1); - } - if (!VIR_IS_CONNECTED_DOMAIN(domain)) { - virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); - return (-1); - } - conn = domain->conn; - if (conn->flags & VIR_CONNECT_RO) { - virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); - } - - if (conn->driver->domainCreate) - return conn->driver->domainCreate (domain); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + return (-1); + } + conn = domain->conn; + if (conn->flags & VIR_CONNECT_RO) { + virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + if (conn->driver->domainCreate) { + int ret; + ret = conn->driver->domainCreate (domain); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(domain->conn); return -1; } @@ -3305,21 +3805,32 @@ virDomainGetAutostart(virDomainPtr domai virConnectPtr conn; DEBUG("domain=%p, autostart=%p", domain, autostart); - if (!VIR_IS_DOMAIN(domain)) { + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); return (-1); } if (!autostart) { virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); - } - - conn = domain->conn; - - if (conn->driver->domainGetAutostart) - return conn->driver->domainGetAutostart (domain, autostart); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + conn = domain->conn; + + if (conn->driver->domainGetAutostart) { + int ret; + ret = conn->driver->domainGetAutostart (domain, autostart); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(domain->conn); return -1; } @@ -3340,22 +3851,33 @@ virDomainSetAutostart(virDomainPtr domai virConnectPtr conn; DEBUG("domain=%p, autostart=%d", domain, autostart); - if (!VIR_IS_DOMAIN(domain)) { - virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); - return (-1); - } - - conn = domain->conn; - - if (domain->conn->flags & VIR_CONNECT_RO) { - virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); - } - - if (conn->driver->domainSetAutostart) - return conn->driver->domainSetAutostart (domain, autostart); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + return (-1); + } + + conn = domain->conn; + + if (domain->conn->flags & VIR_CONNECT_RO) { + virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + if (conn->driver->domainSetAutostart) { + int ret; + ret = conn->driver->domainSetAutostart (domain, autostart); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(domain->conn); return -1; } @@ -3378,29 +3900,36 @@ virDomainSetVcpus(virDomainPtr domain, u virConnectPtr conn; DEBUG("domain=%p, nvcpus=%u", domain, nvcpus); - if (domain == NULL) { - TODO - return (-1); - } - if (!VIR_IS_CONNECTED_DOMAIN(domain)) { - virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); - return (-1); - } - if (domain->conn->flags & VIR_CONNECT_RO) { - virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + return (-1); + } + if (domain->conn->flags & VIR_CONNECT_RO) { + virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; } if (nvcpus < 1) { virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); - } - conn = domain->conn; - - if (conn->driver->domainSetVcpus) - return conn->driver->domainSetVcpus (domain, nvcpus); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + conn = domain->conn; + + if (conn->driver->domainSetVcpus) { + int ret; + ret = conn->driver->domainSetVcpus (domain, nvcpus); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(domain->conn); return -1; } @@ -3429,30 +3958,37 @@ virDomainPinVcpu(virDomainPtr domain, un virConnectPtr conn; DEBUG("domain=%p, vcpu=%u, cpumap=%p, maplen=%d", domain, vcpu, cpumap, maplen); - if (domain == NULL) { - TODO - return (-1); - } - if (!VIR_IS_CONNECTED_DOMAIN(domain)) { - virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); - return (-1); - } - if (domain->conn->flags & VIR_CONNECT_RO) { - virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + return (-1); + } + if (domain->conn->flags & VIR_CONNECT_RO) { + virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; } if ((vcpu > 32000) || (cpumap == NULL) || (maplen < 1)) { virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); - } - - conn = domain->conn; - - if (conn->driver->domainPinVcpu) - return conn->driver->domainPinVcpu (domain, vcpu, cpumap, maplen); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + conn = domain->conn; + + if (conn->driver->domainPinVcpu) { + int ret; + ret = conn->driver->domainPinVcpu (domain, vcpu, cpumap, maplen); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(domain->conn); return -1; } @@ -3484,30 +4020,37 @@ virDomainGetVcpus(virDomainPtr domain, v virConnectPtr conn; DEBUG("domain=%p, info=%p, maxinfo=%d, cpumaps=%p, maplen=%d", domain, info, maxinfo, cpumaps, maplen); - if (domain == NULL) { - TODO - return (-1); - } + virResetLastError(); + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); return (-1); } if ((info == NULL) || (maxinfo < 1)) { virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); + goto error; } if (cpumaps != NULL && maplen < 1) { virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); - } - - conn = domain->conn; - - if (conn->driver->domainGetVcpus) - return conn->driver->domainGetVcpus (domain, info, maxinfo, - cpumaps, maplen); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + conn = domain->conn; + + if (conn->driver->domainGetVcpus) { + int ret; + ret = conn->driver->domainGetVcpus (domain, info, maxinfo, + cpumaps, maplen); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(domain->conn); return -1; } @@ -3529,17 +4072,28 @@ virDomainGetMaxVcpus(virDomainPtr domain virConnectPtr conn; DEBUG("domain=%p", domain); - if (!VIR_IS_CONNECTED_DOMAIN(domain)) { - virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); - return (-1); - } - - conn = domain->conn; - - if (conn->driver->domainGetMaxVcpus) - return conn->driver->domainGetMaxVcpus (domain); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + return (-1); + } + + conn = domain->conn; + + if (conn->driver->domainGetMaxVcpus) { + int ret; + ret = conn->driver->domainGetMaxVcpus (domain); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(domain->conn); return -1; } @@ -3559,20 +4113,31 @@ virDomainAttachDevice(virDomainPtr domai virConnectPtr conn; DEBUG("domain=%p, xml=%s", domain, xml); - if (!VIR_IS_CONNECTED_DOMAIN(domain)) { - virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); - return (-1); - } - if (domain->conn->flags & VIR_CONNECT_RO) { - virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); - } - conn = domain->conn; - - if (conn->driver->domainAttachDevice) - return conn->driver->domainAttachDevice (domain, xml); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + return (-1); + } + if (domain->conn->flags & VIR_CONNECT_RO) { + virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + conn = domain->conn; + + if (conn->driver->domainAttachDevice) { + int ret; + ret = conn->driver->domainAttachDevice (domain, xml); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(domain->conn); return -1; } @@ -3591,20 +4156,31 @@ virDomainDetachDevice(virDomainPtr domai virConnectPtr conn; DEBUG("domain=%p, xml=%s", domain, xml); - if (!VIR_IS_CONNECTED_DOMAIN(domain)) { - virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); - return (-1); - } - if (domain->conn->flags & VIR_CONNECT_RO) { - virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); - } - conn = domain->conn; - - if (conn->driver->domainDetachDevice) - return conn->driver->domainDetachDevice (domain, xml); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + return (-1); + } + if (domain->conn->flags & VIR_CONNECT_RO) { + virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + conn = domain->conn; + + if (conn->driver->domainDetachDevice) { + int ret; + ret = conn->driver->domainDetachDevice (domain, xml); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(domain->conn); return -1; } @@ -3633,6 +4209,8 @@ virNodeGetCellsFreeMemory(virConnectPtr DEBUG("conn=%p, freeMems=%p, startCell=%d, maxCells=%d", conn, freeMems, startCell, maxCells); + virResetLastError(); + if (!VIR_IS_CONNECT(conn)) { virLibConnError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__); return (-1); @@ -3640,13 +4218,22 @@ virNodeGetCellsFreeMemory(virConnectPtr if ((freeMems == NULL) || (maxCells <= 0) || (startCell < 0)) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); - } - - if (conn->driver->nodeGetCellsFreeMemory) - return conn->driver->nodeGetCellsFreeMemory (conn, freeMems, startCell, maxCells); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + if (conn->driver->nodeGetCellsFreeMemory) { + int ret; + ret = conn->driver->nodeGetCellsFreeMemory (conn, freeMems, startCell, maxCells); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return -1; } @@ -3669,7 +4256,9 @@ virNetworkGetConnect (virNetworkPtr net) { DEBUG("net=%p", net); - if (!VIR_IS_NETWORK (net)) { + virResetLastError(); + + if (!VIR_IS_CONNECTED_NETWORK (net)) { virLibNetworkError (NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); return NULL; } @@ -3689,15 +4278,26 @@ virConnectNumOfNetworks(virConnectPtr co { DEBUG("conn=%p", conn); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); - return (-1); - } - - if (conn->networkDriver && conn->networkDriver->numOfNetworks) - return conn->networkDriver->numOfNetworks (conn); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + return (-1); + } + + if (conn->networkDriver && conn->networkDriver->numOfNetworks) { + int ret; + ret = conn->networkDriver->numOfNetworks (conn); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return -1; } @@ -3716,6 +4316,8 @@ virConnectListNetworks(virConnectPtr con { DEBUG("conn=%p, names=%p, maxnames=%d", conn, names, maxnames); + virResetLastError(); + if (!VIR_IS_CONNECT(conn)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); return (-1); @@ -3723,13 +4325,22 @@ virConnectListNetworks(virConnectPtr con if ((names == NULL) || (maxnames < 0)) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); - } - - if (conn->networkDriver && conn->networkDriver->listNetworks) - return conn->networkDriver->listNetworks (conn, names, maxnames); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + if (conn->networkDriver && conn->networkDriver->listNetworks) { + int ret; + ret = conn->networkDriver->listNetworks (conn, names, maxnames); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return -1; } @@ -3746,15 +4357,26 @@ virConnectNumOfDefinedNetworks(virConnec { DEBUG("conn=%p", conn); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); - return (-1); - } - - if (conn->networkDriver && conn->networkDriver->numOfDefinedNetworks) - return conn->networkDriver->numOfDefinedNetworks (conn); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + return (-1); + } + + if (conn->networkDriver && conn->networkDriver->numOfDefinedNetworks) { + int ret; + ret = conn->networkDriver->numOfDefinedNetworks (conn); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return -1; } @@ -3774,6 +4396,8 @@ virConnectListDefinedNetworks(virConnect { DEBUG("conn=%p, names=%p, maxnames=%d", conn, names, maxnames); + virResetLastError(); + if (!VIR_IS_CONNECT(conn)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); return (-1); @@ -3781,14 +4405,23 @@ virConnectListDefinedNetworks(virConnect if ((names == NULL) || (maxnames < 0)) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); - } - - if (conn->networkDriver && conn->networkDriver->listDefinedNetworks) - return conn->networkDriver->listDefinedNetworks (conn, - names, maxnames); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + if (conn->networkDriver && conn->networkDriver->listDefinedNetworks) { + int ret; + ret = conn->networkDriver->listDefinedNetworks (conn, + names, maxnames); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return -1; } @@ -3807,19 +4440,30 @@ virNetworkLookupByName(virConnectPtr con { DEBUG("conn=%p, name=%s", conn, name); + virResetLastError(); + if (!VIR_IS_CONNECT(conn)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); return (NULL); } if (name == NULL) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (NULL); - } - - if (conn->networkDriver && conn->networkDriver->networkLookupByName) - return conn->networkDriver->networkLookupByName (conn, name); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + if (conn->networkDriver && conn->networkDriver->networkLookupByName) { + virNetworkPtr ret; + ret = conn->networkDriver->networkLookupByName (conn, name); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return NULL; } @@ -3838,19 +4482,30 @@ virNetworkLookupByUUID(virConnectPtr con { DEBUG("conn=%p, uuid=%s", conn, uuid); + virResetLastError(); + if (!VIR_IS_CONNECT(conn)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); return (NULL); } if (uuid == NULL) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (NULL); - } - - if (conn->networkDriver && conn->networkDriver->networkLookupByUUID) - return conn->networkDriver->networkLookupByUUID (conn, uuid); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + if (conn->networkDriver && conn->networkDriver->networkLookupByUUID){ + virNetworkPtr ret; + ret = conn->networkDriver->networkLookupByUUID (conn, uuid); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return NULL; } @@ -3872,13 +4527,15 @@ virNetworkLookupByUUIDString(virConnectP int ret; DEBUG("conn=%p, uuidstr=%s", conn, uuidstr); + virResetLastError(); + if (!VIR_IS_CONNECT(conn)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); return (NULL); } if (uuidstr == NULL) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (NULL); + goto error; } /* XXX: sexpr_uuid() also supports 'xxxx-xxxx-xxxx-xxxx' format. @@ -3897,12 +4554,17 @@ virNetworkLookupByUUIDString(virConnectP if (ret!=VIR_UUID_BUFLEN) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (NULL); + goto error; } for (i = 0; i < VIR_UUID_BUFLEN; i++) uuid[i] = raw[i] & 0xFF; return virNetworkLookupByUUID(conn, &uuid[0]); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); + return NULL; } /** @@ -3920,23 +4582,34 @@ virNetworkCreateXML(virConnectPtr conn, { DEBUG("conn=%p, xmlDesc=%s", conn, xmlDesc); + virResetLastError(); + if (!VIR_IS_CONNECT(conn)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); return (NULL); } if (xmlDesc == NULL) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (NULL); - } - if (conn->flags & VIR_CONNECT_RO) { - virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (NULL); - } - - if (conn->networkDriver && conn->networkDriver->networkCreateXML) - return conn->networkDriver->networkCreateXML (conn, xmlDesc); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + if (conn->flags & VIR_CONNECT_RO) { + virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + if (conn->networkDriver && conn->networkDriver->networkCreateXML) { + virNetworkPtr ret; + ret = conn->networkDriver->networkCreateXML (conn, xmlDesc); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return NULL; } @@ -3954,23 +4627,34 @@ virNetworkDefineXML(virConnectPtr conn, { DEBUG("conn=%p, xml=%s", conn, xml); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); - return (NULL); - } - if (conn->flags & VIR_CONNECT_RO) { - virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (NULL); + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + return (NULL); + } + if (conn->flags & VIR_CONNECT_RO) { + virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; } if (xml == NULL) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (NULL); - } - - if (conn->networkDriver && conn->networkDriver->networkDefineXML) - return conn->networkDriver->networkDefineXML (conn, xml); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + if (conn->networkDriver && conn->networkDriver->networkDefineXML) { + virNetworkPtr ret; + ret = conn->networkDriver->networkDefineXML (conn, xml); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return NULL; } @@ -3987,6 +4671,8 @@ virNetworkUndefine(virNetworkPtr network virConnectPtr conn; DEBUG("network=%p", network); + virResetLastError(); + if (!VIR_IS_CONNECTED_NETWORK(network)) { virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); return (-1); @@ -3994,13 +4680,22 @@ virNetworkUndefine(virNetworkPtr network conn = network->conn; if (conn->flags & VIR_CONNECT_RO) { virLibNetworkError(network, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); - } - - if (conn->networkDriver && conn->networkDriver->networkUndefine) - return conn->networkDriver->networkUndefine (network); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + if (conn->networkDriver && conn->networkDriver->networkUndefine) { + int ret; + ret = conn->networkDriver->networkUndefine (network); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(network->conn); return -1; } @@ -4019,10 +4714,8 @@ virNetworkCreate(virNetworkPtr network) virConnectPtr conn; DEBUG("network=%p", network); - if (network == NULL) { - TODO - return (-1); - } + virResetLastError(); + if (!VIR_IS_CONNECTED_NETWORK(network)) { virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); return (-1); @@ -4030,13 +4723,22 @@ virNetworkCreate(virNetworkPtr network) conn = network->conn; if (conn->flags & VIR_CONNECT_RO) { virLibNetworkError(network, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); - } - - if (conn->networkDriver && conn->networkDriver->networkCreate) - return conn->networkDriver->networkCreate (network); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + if (conn->networkDriver && conn->networkDriver->networkCreate) { + int ret; + ret = conn->networkDriver->networkCreate (network); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(network->conn); return -1; } @@ -4057,6 +4759,8 @@ virNetworkDestroy(virNetworkPtr network) virConnectPtr conn; DEBUG("network=%p", network); + virResetLastError(); + if (!VIR_IS_CONNECTED_NETWORK(network)) { virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); return (-1); @@ -4065,13 +4769,22 @@ virNetworkDestroy(virNetworkPtr network) conn = network->conn; if (conn->flags & VIR_CONNECT_RO) { virLibNetworkError(network, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); - } - - if (conn->networkDriver && conn->networkDriver->networkDestroy) - return conn->networkDriver->networkDestroy (network); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + if (conn->networkDriver && conn->networkDriver->networkDestroy) { + int ret; + ret = conn->networkDriver->networkDestroy (network); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(network->conn); return -1; } @@ -4089,7 +4802,9 @@ virNetworkFree(virNetworkPtr network) { DEBUG("network=%p", network); - if (!VIR_IS_NETWORK(network)) { + virResetLastError(); + + if (!VIR_IS_CONNECTED_NETWORK(network)) { virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); return (-1); } @@ -4112,6 +4827,8 @@ virNetworkGetName(virNetworkPtr network) { DEBUG("network=%p", network); + virResetLastError(); + if (!VIR_IS_NETWORK(network)) { virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); return (NULL); @@ -4133,18 +4850,25 @@ virNetworkGetUUID(virNetworkPtr network, { DEBUG("network=%p, uuid=%p", network, uuid); + virResetLastError(); + if (!VIR_IS_NETWORK(network)) { virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); return (-1); } if (uuid == NULL) { virLibNetworkError(network, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); + goto error; } memcpy(uuid, &network->uuid[0], VIR_UUID_BUFLEN); return (0); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(network->conn); + return -1; } /** @@ -4163,13 +4887,15 @@ virNetworkGetUUIDString(virNetworkPtr ne unsigned char uuid[VIR_UUID_BUFLEN]; DEBUG("network=%p, buf=%p", network, buf); + virResetLastError(); + if (!VIR_IS_NETWORK(network)) { virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); return (-1); } if (buf == NULL) { virLibNetworkError(network, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); + goto error; } if (virNetworkGetUUID(network, &uuid[0])) @@ -4177,6 +4903,11 @@ virNetworkGetUUIDString(virNetworkPtr ne virUUIDFormat(uuid, buf); return (0); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(network->conn); + return -1; } /** @@ -4196,21 +4927,32 @@ virNetworkGetXMLDesc(virNetworkPtr netwo virConnectPtr conn; DEBUG("network=%p, flags=%d", network, flags); - if (!VIR_IS_NETWORK(network)) { + virResetLastError(); + + if (!VIR_IS_CONNECTED_NETWORK(network)) { virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); return (NULL); } if (flags != 0) { virLibNetworkError(network, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (NULL); + goto error; } conn = network->conn; - if (conn->networkDriver && conn->networkDriver->networkDumpXML) - return conn->networkDriver->networkDumpXML (network, flags); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + if (conn->networkDriver && conn->networkDriver->networkDumpXML) { + char *ret; + ret = conn->networkDriver->networkDumpXML (network, flags); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(network->conn); return NULL; } @@ -4230,17 +4972,28 @@ virNetworkGetBridgeName(virNetworkPtr ne virConnectPtr conn; DEBUG("network=%p", network); - if (!VIR_IS_NETWORK(network)) { + virResetLastError(); + + if (!VIR_IS_CONNECTED_NETWORK(network)) { virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); return (NULL); } conn = network->conn; - if (conn->networkDriver && conn->networkDriver->networkGetBridgeName) - return conn->networkDriver->networkGetBridgeName (network); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + if (conn->networkDriver && conn->networkDriver->networkGetBridgeName) { + char *ret; + ret = conn->networkDriver->networkGetBridgeName (network); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(network->conn); return NULL; } @@ -4262,21 +5015,32 @@ virNetworkGetAutostart(virNetworkPtr net virConnectPtr conn; DEBUG("network=%p, autostart=%p", network, autostart); - if (!VIR_IS_NETWORK(network)) { + virResetLastError(); + + if (!VIR_IS_CONNECTED_NETWORK(network)) { virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); return (-1); } if (!autostart) { virLibNetworkError(network, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); + goto error; } conn = network->conn; - if (conn->networkDriver && conn->networkDriver->networkGetAutostart) - return conn->networkDriver->networkGetAutostart (network, autostart); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + if (conn->networkDriver && conn->networkDriver->networkGetAutostart) { + int ret; + ret = conn->networkDriver->networkGetAutostart (network, autostart); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(network->conn); return -1; } @@ -4297,22 +5061,33 @@ virNetworkSetAutostart(virNetworkPtr net virConnectPtr conn; DEBUG("network=%p, autostart=%d", network, autostart); - if (!VIR_IS_NETWORK(network)) { + virResetLastError(); + + if (!VIR_IS_CONNECTED_NETWORK(network)) { virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); return (-1); } if (network->conn->flags & VIR_CONNECT_RO) { virLibNetworkError(network, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); + goto error; } conn = network->conn; - if (conn->networkDriver && conn->networkDriver->networkSetAutostart) - return conn->networkDriver->networkSetAutostart (network, autostart); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + if (conn->networkDriver && conn->networkDriver->networkSetAutostart) { + int ret; + ret = conn->networkDriver->networkSetAutostart (network, autostart); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(network->conn); return -1; } @@ -4336,7 +5111,9 @@ virStoragePoolGetConnect (virStoragePool { DEBUG("pool=%p", pool); - if (!VIR_IS_STORAGE_POOL (pool)) { + virResetLastError(); + + if (!VIR_IS_CONNECTED_STORAGE_POOL (pool)) { virLibStoragePoolError (NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); return NULL; } @@ -4356,15 +5133,26 @@ virConnectNumOfStoragePools (virConnectP { DEBUG("conn=%p", conn); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); - return (-1); - } - - if (conn->storageDriver && conn->storageDriver->numOfPools) - return conn->storageDriver->numOfPools (conn); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + return (-1); + } + + if (conn->storageDriver && conn->storageDriver->numOfPools) { + int ret; + ret = conn->storageDriver->numOfPools (conn); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return -1; } @@ -4387,6 +5175,8 @@ virConnectListStoragePools (virConnectPt { DEBUG("conn=%p, names=%p, maxnames=%d", conn, names, maxnames); + virResetLastError(); + if (!VIR_IS_CONNECT(conn)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); return (-1); @@ -4394,15 +5184,23 @@ virConnectListStoragePools (virConnectPt if ((names == NULL) || (maxnames < 0)) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); - } - - if (conn->storageDriver && conn->storageDriver->listPools) - return conn->storageDriver->listPools (conn, names, maxnames); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); - return -1; - + goto error; + } + + if (conn->storageDriver && conn->storageDriver->listPools) { + int ret; + ret = conn->storageDriver->listPools (conn, names, maxnames); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); + return -1; } @@ -4419,15 +5217,26 @@ virConnectNumOfDefinedStoragePools(virCo { DEBUG("conn=%p", conn); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); - return (-1); - } - - if (conn->storageDriver && conn->storageDriver->numOfDefinedPools) - return conn->storageDriver->numOfDefinedPools (conn); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + return (-1); + } + + if (conn->storageDriver && conn->storageDriver->numOfDefinedPools) { + int ret; + ret = conn->storageDriver->numOfDefinedPools (conn); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return -1; } @@ -4451,6 +5260,8 @@ virConnectListDefinedStoragePools(virCon { DEBUG("conn=%p, names=%p, maxnames=%d", conn, names, maxnames); + virResetLastError(); + if (!VIR_IS_CONNECT(conn)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); return (-1); @@ -4458,13 +5269,22 @@ virConnectListDefinedStoragePools(virCon if ((names == NULL) || (maxnames < 0)) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); - } - - if (conn->storageDriver && conn->storageDriver->listDefinedPools) - return conn->storageDriver->listDefinedPools (conn, names, maxnames); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + if (conn->storageDriver && conn->storageDriver->listDefinedPools) { + int ret; + ret = conn->storageDriver->listDefinedPools (conn, names, maxnames); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return -1; } @@ -4496,24 +5316,37 @@ virConnectFindStoragePoolSources(virConn const char *srcSpec, unsigned int flags) { - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); - return NULL; + DEBUG("conn=%p, type=%s, src=%s, flags=%u", conn, type ? type : "", srcSpec ? srcSpec : "", flags); + + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + goto error; } if (type == NULL) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return NULL; - } - - if (conn->flags & VIR_CONNECT_RO) { - virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return NULL; - } - - if (conn->storageDriver && conn->storageDriver->findPoolSources) - return conn->storageDriver->findPoolSources(conn, type, srcSpec, flags); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + if (conn->flags & VIR_CONNECT_RO) { + virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + if (conn->storageDriver && conn->storageDriver->findPoolSources) { + char *ret; + ret = conn->storageDriver->findPoolSources(conn, type, srcSpec, flags); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return NULL; } @@ -4533,19 +5366,30 @@ virStoragePoolLookupByName(virConnectPtr { DEBUG("conn=%p, name=%s", conn, name); + virResetLastError(); + if (!VIR_IS_CONNECT(conn)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); return (NULL); } if (name == NULL) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (NULL); - } - - if (conn->storageDriver && conn->storageDriver->poolLookupByName) - return conn->storageDriver->poolLookupByName (conn, name); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + if (conn->storageDriver && conn->storageDriver->poolLookupByName) { + virStoragePoolPtr ret; + ret = conn->storageDriver->poolLookupByName (conn, name); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return NULL; } @@ -4565,21 +5409,31 @@ virStoragePoolLookupByUUID(virConnectPtr { DEBUG("conn=%p, uuid=%s", conn, uuid); + virResetLastError(); + if (!VIR_IS_CONNECT(conn)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); return (NULL); } if (uuid == NULL) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (NULL); - } - - if (conn->storageDriver && conn->storageDriver->poolLookupByUUID) - return conn->storageDriver->poolLookupByUUID (conn, uuid); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); - return NULL; - + goto error; + } + + if (conn->storageDriver && conn->storageDriver->poolLookupByUUID) { + virStoragePoolPtr ret; + ret = conn->storageDriver->poolLookupByUUID (conn, uuid); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); + return NULL; } @@ -4594,26 +5448,33 @@ virStoragePoolLookupByUUID(virConnectPtr */ virStoragePoolPtr virStoragePoolLookupByUUIDString(virConnectPtr conn, - const char *uuidstr) + const char *uuidstr) { unsigned char uuid[VIR_UUID_BUFLEN]; DEBUG("conn=%p, uuidstr=%s", conn, uuidstr); + virResetLastError(); + if (!VIR_IS_CONNECT(conn)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); return (NULL); } if (uuidstr == NULL) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (NULL); + goto error; } if (virUUIDParse(uuidstr, uuid) < 0) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (NULL); + goto error; } return virStoragePoolLookupByUUID(conn, uuid); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); + return NULL; } @@ -4630,17 +5491,27 @@ virStoragePoolLookupByVolume(virStorageV { DEBUG("vol=%p", vol); - if (!VIR_IS_STORAGE_VOL(vol)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); - return (NULL); - } - - if (vol->conn->storageDriver && vol->conn->storageDriver->poolLookupByVolume) - return vol->conn->storageDriver->poolLookupByVolume (vol); + virResetLastError(); + + if (!VIR_IS_CONNECTED_STORAGE_VOL(vol)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + return (NULL); + } + + if (vol->conn->storageDriver && vol->conn->storageDriver->poolLookupByVolume) { + virStoragePoolPtr ret; + ret = vol->conn->storageDriver->poolLookupByVolume (vol); + if (!ret) + goto error; + return ret; + } virLibConnError (vol->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); - return NULL; - + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(vol->conn); + return NULL; } /** @@ -4662,23 +5533,34 @@ virStoragePoolCreateXML(virConnectPtr co { DEBUG("conn=%p, xmlDesc=%s", conn, xmlDesc); + virResetLastError(); + if (!VIR_IS_CONNECT(conn)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); return (NULL); } if (xmlDesc == NULL) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (NULL); - } - if (conn->flags & VIR_CONNECT_RO) { - virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (NULL); - } - - if (conn->storageDriver && conn->storageDriver->poolCreateXML) - return conn->storageDriver->poolCreateXML (conn, xmlDesc, flags); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + if (conn->flags & VIR_CONNECT_RO) { + virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + if (conn->storageDriver && conn->storageDriver->poolCreateXML) { + virStoragePoolPtr ret; + ret = conn->storageDriver->poolCreateXML (conn, xmlDesc, flags); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return NULL; } @@ -4700,25 +5582,35 @@ virStoragePoolDefineXML(virConnectPtr co { DEBUG("conn=%p, xml=%s", conn, xml); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); - return (NULL); - } - if (conn->flags & VIR_CONNECT_RO) { - virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (NULL); + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + return (NULL); + } + if (conn->flags & VIR_CONNECT_RO) { + virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; } if (xml == NULL) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (NULL); - } - - if (conn->storageDriver && conn->storageDriver->poolDefineXML) - return conn->storageDriver->poolDefineXML (conn, xml, flags); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); - return NULL; - + goto error; + } + + if (conn->storageDriver && conn->storageDriver->poolDefineXML) { + virStoragePoolPtr ret; + ret = conn->storageDriver->poolDefineXML (conn, xml, flags); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); + return NULL; } /** @@ -4737,6 +5629,8 @@ virStoragePoolBuild(virStoragePoolPtr po virConnectPtr conn; DEBUG("pool=%p, flags=%u", pool, flags); + virResetLastError(); + if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) { virLibStoragePoolError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); return (-1); @@ -4744,15 +5638,23 @@ virStoragePoolBuild(virStoragePoolPtr po conn = pool->conn; if (conn->flags & VIR_CONNECT_RO) { virLibStoragePoolError(pool, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); - } - - if (conn->storageDriver && conn->storageDriver->poolBuild) - return conn->storageDriver->poolBuild (pool, flags); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); - return -1; - + goto error; + } + + if (conn->storageDriver && conn->storageDriver->poolBuild) { + int ret; + ret = conn->storageDriver->poolBuild (pool, flags); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(pool->conn); + return -1; } @@ -4770,6 +5672,8 @@ virStoragePoolUndefine(virStoragePoolPtr virConnectPtr conn; DEBUG("pool=%p", pool); + virResetLastError(); + if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) { virLibStoragePoolError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); return (-1); @@ -4777,15 +5681,23 @@ virStoragePoolUndefine(virStoragePoolPtr conn = pool->conn; if (conn->flags & VIR_CONNECT_RO) { virLibStoragePoolError(pool, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); - } - - if (conn->storageDriver && conn->storageDriver->poolUndefine) - return conn->storageDriver->poolUndefine (pool); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); - return -1; - + goto error; + } + + if (conn->storageDriver && conn->storageDriver->poolUndefine) { + int ret; + ret = conn->storageDriver->poolUndefine (pool); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(pool->conn); + return -1; } @@ -4805,10 +5717,8 @@ virStoragePoolCreate(virStoragePoolPtr p virConnectPtr conn; DEBUG("pool=%p", pool); - if (pool == NULL) { - TODO; - return (-1); - } + virResetLastError(); + if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) { virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); return (-1); @@ -4816,15 +5726,23 @@ virStoragePoolCreate(virStoragePoolPtr p conn = pool->conn; if (conn->flags & VIR_CONNECT_RO) { virLibStoragePoolError(pool, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); - } - - if (conn->storageDriver && conn->storageDriver->poolCreate) - return conn->storageDriver->poolCreate (pool, flags); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); - return -1; - + goto error; + } + + if (conn->storageDriver && conn->storageDriver->poolCreate) { + int ret; + ret = conn->storageDriver->poolCreate (pool, flags); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(pool->conn); + return -1; } @@ -4846,6 +5764,8 @@ virStoragePoolDestroy(virStoragePoolPtr virConnectPtr conn; DEBUG("pool=%p", pool); + virResetLastError(); + if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) { virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); return (-1); @@ -4854,13 +5774,22 @@ virStoragePoolDestroy(virStoragePoolPtr conn = pool->conn; if (conn->flags & VIR_CONNECT_RO) { virLibStoragePoolError(pool, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); - } - - if (conn->storageDriver && conn->storageDriver->poolDestroy) - return conn->storageDriver->poolDestroy (pool); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + if (conn->storageDriver && conn->storageDriver->poolDestroy) { + int ret; + ret = conn->storageDriver->poolDestroy (pool); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(pool->conn); return -1; } @@ -4882,6 +5811,8 @@ virStoragePoolDelete(virStoragePoolPtr p virConnectPtr conn; DEBUG("pool=%p, flags=%u", pool, flags); + virResetLastError(); + if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) { virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); return (-1); @@ -4890,13 +5821,22 @@ virStoragePoolDelete(virStoragePoolPtr p conn = pool->conn; if (conn->flags & VIR_CONNECT_RO) { virLibStoragePoolError(pool, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); - } - - if (conn->storageDriver && conn->storageDriver->poolDelete) - return conn->storageDriver->poolDelete (pool, flags); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + if (conn->storageDriver && conn->storageDriver->poolDelete) { + int ret; + ret = conn->storageDriver->poolDelete (pool, flags); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(pool->conn); return -1; } @@ -4915,7 +5855,9 @@ virStoragePoolFree(virStoragePoolPtr poo { DEBUG("pool=%p", pool); - if (!VIR_IS_STORAGE_POOL(pool)) { + virResetLastError(); + + if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) { virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); return (-1); } @@ -4944,6 +5886,8 @@ virStoragePoolRefresh(virStoragePoolPtr virConnectPtr conn; DEBUG("pool=%p flags=%u", pool, flags); + virResetLastError(); + if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) { virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); return (-1); @@ -4952,13 +5896,22 @@ virStoragePoolRefresh(virStoragePoolPtr conn = pool->conn; if (conn->flags & VIR_CONNECT_RO) { virLibStoragePoolError(pool, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); - } - - if (conn->storageDriver && conn->storageDriver->poolRefresh) - return conn->storageDriver->poolRefresh (pool, flags); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + if (conn->storageDriver && conn->storageDriver->poolRefresh) { + int ret; + ret = conn->storageDriver->poolRefresh (pool, flags); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(pool->conn); return -1; } @@ -4976,12 +5929,13 @@ virStoragePoolGetName(virStoragePoolPtr { DEBUG("pool=%p", pool); + virResetLastError(); + if (!VIR_IS_STORAGE_POOL(pool)) { virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); return (NULL); } return (pool->name); - } @@ -5000,19 +5954,25 @@ virStoragePoolGetUUID(virStoragePoolPtr { DEBUG("pool=%p, uuid=%p", pool, uuid); + virResetLastError(); + if (!VIR_IS_STORAGE_POOL(pool)) { virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); return (-1); } if (uuid == NULL) { virLibStoragePoolError(pool, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); + goto error; } memcpy(uuid, &pool->uuid[0], VIR_UUID_BUFLEN); return (0); +error: + /* Copy to connection error object for back compatability */ + virSetConnError(pool->conn); + return -1; } /** @@ -5031,21 +5991,27 @@ virStoragePoolGetUUIDString(virStoragePo unsigned char uuid[VIR_UUID_BUFLEN]; DEBUG("pool=%p, buf=%p", pool, buf); + virResetLastError(); + if (!VIR_IS_STORAGE_POOL(pool)) { virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); return (-1); } if (buf == NULL) { virLibStoragePoolError(pool, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); + goto error; } if (virStoragePoolGetUUID(pool, &uuid[0])) - return (-1); + goto error; virUUIDFormat(uuid, buf); return (0); +error: + /* Copy to connection error object for back compatability */ + virSetConnError(pool->conn); + return -1; } @@ -5066,25 +6032,35 @@ virStoragePoolGetInfo(virStoragePoolPtr virConnectPtr conn; DEBUG("pool=%p, info=%p", pool, info); + virResetLastError(); + if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) { virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); return (-1); } if (info == NULL) { virLibStoragePoolError(pool, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); + goto error; } memset(info, 0, sizeof(virStoragePoolInfo)); conn = pool->conn; - if (conn->storageDriver->poolGetInfo) - return conn->storageDriver->poolGetInfo (pool, info); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); - return -1; - + if (conn->storageDriver->poolGetInfo) { + int ret; + ret = conn->storageDriver->poolGetInfo (pool, info); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(pool->conn); + return -1; } @@ -5106,23 +6082,33 @@ virStoragePoolGetXMLDesc(virStoragePoolP virConnectPtr conn; DEBUG("pool=%p, flags=%u", pool, flags); - if (!VIR_IS_STORAGE_POOL(pool)) { + virResetLastError(); + + if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) { virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); return (NULL); } if (flags != 0) { virLibStoragePoolError(pool, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (NULL); - } - - conn = pool->conn; - - if (conn->storageDriver && conn->storageDriver->poolGetXMLDesc) - return conn->storageDriver->poolGetXMLDesc (pool, flags); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); - return NULL; - + goto error; + } + + conn = pool->conn; + + if (conn->storageDriver && conn->storageDriver->poolGetXMLDesc) { + char *ret; + ret = conn->storageDriver->poolGetXMLDesc (pool, flags); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(pool->conn); + return NULL; } @@ -5143,21 +6129,32 @@ virStoragePoolGetAutostart(virStoragePoo virConnectPtr conn; DEBUG("pool=%p, autostart=%p", pool, autostart); - if (!VIR_IS_STORAGE_POOL(pool)) { + virResetLastError(); + + if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) { virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); return (-1); } if (!autostart) { virLibStoragePoolError(pool, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); - } - - conn = pool->conn; - - if (conn->storageDriver && conn->storageDriver->poolGetAutostart) - return conn->storageDriver->poolGetAutostart (pool, autostart); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + conn = pool->conn; + + if (conn->storageDriver && conn->storageDriver->poolGetAutostart) { + int ret; + ret = conn->storageDriver->poolGetAutostart (pool, autostart); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(pool->conn); return -1; } @@ -5178,22 +6175,33 @@ virStoragePoolSetAutostart(virStoragePoo virConnectPtr conn; DEBUG("pool=%p, autostart=%d", pool, autostart); - if (!VIR_IS_STORAGE_POOL(pool)) { - virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); - return (-1); + virResetLastError(); + + if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) { + virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); + goto error; } if (pool->conn->flags & VIR_CONNECT_RO) { virLibStoragePoolError(pool, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); - } - - conn = pool->conn; - - if (conn->storageDriver && conn->storageDriver->poolSetAutostart) - return conn->storageDriver->poolSetAutostart (pool, autostart); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + conn = pool->conn; + + if (conn->storageDriver && conn->storageDriver->poolSetAutostart) { + int ret; + ret = conn->storageDriver->poolSetAutostart (pool, autostart); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(pool->conn); return -1; } @@ -5211,15 +6219,26 @@ virStoragePoolNumOfVolumes(virStoragePoo { DEBUG("pool=%p", pool); + virResetLastError(); + if (!VIR_IS_STORAGE_POOL(pool)) { virLibConnError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); return (-1); } - if (pool->conn->storageDriver && pool->conn->storageDriver->poolNumOfVolumes) - return pool->conn->storageDriver->poolNumOfVolumes (pool); + if (pool->conn->storageDriver && pool->conn->storageDriver->poolNumOfVolumes) { + int ret; + ret = pool->conn->storageDriver->poolNumOfVolumes (pool); + if (ret < 0) + goto error; + return ret; + } virLibConnError (pool->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(pool->conn); return -1; } @@ -5242,6 +6261,8 @@ virStoragePoolListVolumes(virStoragePool { DEBUG("pool=%p, names=%p, maxnames=%d", pool, names, maxnames); + virResetLastError(); + if (!VIR_IS_STORAGE_POOL(pool)) { virLibConnError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); return (-1); @@ -5249,13 +6270,22 @@ virStoragePoolListVolumes(virStoragePool if ((names == NULL) || (maxnames < 0)) { virLibConnError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); - } - - if (pool->conn->storageDriver && pool->conn->storageDriver->poolListVolumes) - return pool->conn->storageDriver->poolListVolumes (pool, names, maxnames); + goto error; + } + + if (pool->conn->storageDriver && pool->conn->storageDriver->poolListVolumes) { + int ret; + ret = pool->conn->storageDriver->poolListVolumes (pool, names, maxnames); + if (ret < 0) + goto error; + return ret; + } virLibConnError (pool->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(pool->conn); return -1; } @@ -5279,6 +6309,8 @@ virStorageVolGetConnect (virStorageVolPt { DEBUG("vol=%p", vol); + virResetLastError(); + if (!VIR_IS_STORAGE_VOL (vol)) { virLibStoragePoolError (NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__); return NULL; @@ -5303,19 +6335,30 @@ virStorageVolLookupByName(virStoragePool { DEBUG("pool=%p, name=%s", pool, name); + virResetLastError(); + if (!VIR_IS_STORAGE_POOL(pool)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); return (NULL); } if (name == NULL) { virLibConnError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (NULL); - } - - if (pool->conn->storageDriver && pool->conn->storageDriver->volLookupByName) - return pool->conn->storageDriver->volLookupByName (pool, name); + goto error; + } + + if (pool->conn->storageDriver && pool->conn->storageDriver->volLookupByName) { + virStorageVolPtr ret; + ret = pool->conn->storageDriver->volLookupByName (pool, name); + if (!ret) + goto error; + return ret; + } virLibConnError (pool->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(pool->conn); return NULL; } @@ -5337,19 +6380,30 @@ virStorageVolLookupByKey(virConnectPtr c { DEBUG("conn=%p, key=%s", conn, key); + virResetLastError(); + if (!VIR_IS_CONNECT(conn)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); return (NULL); } if (key == NULL) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (NULL); - } - - if (conn->storageDriver && conn->storageDriver->volLookupByKey) - return conn->storageDriver->volLookupByKey (conn, key); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + if (conn->storageDriver && conn->storageDriver->volLookupByKey) { + virStorageVolPtr ret; + ret = conn->storageDriver->volLookupByKey (conn, key); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return NULL; } @@ -5369,19 +6423,30 @@ virStorageVolLookupByPath(virConnectPtr { DEBUG("conn=%p, path=%s", conn, path); + virResetLastError(); + if (!VIR_IS_CONNECT(conn)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); return (NULL); } if (path == NULL) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (NULL); - } - - if (conn->storageDriver && conn->storageDriver->volLookupByPath) - return conn->storageDriver->volLookupByPath (conn, path); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + if (conn->storageDriver && conn->storageDriver->volLookupByPath) { + virStorageVolPtr ret; + ret = conn->storageDriver->volLookupByPath (conn, path); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return NULL; } @@ -5400,6 +6465,8 @@ virStorageVolGetName(virStorageVolPtr vo { DEBUG("vol=%p", vol); + virResetLastError(); + if (!VIR_IS_STORAGE_VOL(vol)) { virLibStorageVolError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__); return (NULL); @@ -5423,6 +6490,8 @@ virStorageVolGetKey(virStorageVolPtr vol { DEBUG("vol=%p", vol); + virResetLastError(); + if (!VIR_IS_STORAGE_VOL(vol)) { virLibStorageVolError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__); return (NULL); @@ -5450,6 +6519,8 @@ virStorageVolCreateXML(virStoragePoolPtr { DEBUG("pool=%p, flags=%u", pool, flags); + virResetLastError(); + if (!VIR_IS_STORAGE_POOL(pool)) { virLibConnError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__); return (NULL); @@ -5457,13 +6528,22 @@ virStorageVolCreateXML(virStoragePoolPtr if (pool->conn->flags & VIR_CONNECT_RO) { virLibConnError(pool->conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (NULL); - } - - if (pool->conn->storageDriver && pool->conn->storageDriver->volCreateXML) - return pool->conn->storageDriver->volCreateXML (pool, xmldesc, flags); + goto error; + } + + if (pool->conn->storageDriver && pool->conn->storageDriver->volCreateXML) { + virStorageVolPtr ret; + ret = pool->conn->storageDriver->volCreateXML (pool, xmldesc, flags); + if (!ret) + goto error; + return ret; + } virLibConnError (pool->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(pool->conn); return NULL; } @@ -5484,6 +6564,8 @@ virStorageVolDelete(virStorageVolPtr vol virConnectPtr conn; DEBUG("vol=%p, flags=%u", vol, flags); + virResetLastError(); + if (!VIR_IS_CONNECTED_STORAGE_VOL(vol)) { virLibStorageVolError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__); return (-1); @@ -5492,13 +6574,22 @@ virStorageVolDelete(virStorageVolPtr vol conn = vol->conn; if (conn->flags & VIR_CONNECT_RO) { virLibStorageVolError(vol, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); - } - - if (conn->storageDriver && conn->storageDriver->volDelete) - return conn->storageDriver->volDelete (vol, flags); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + if (conn->storageDriver && conn->storageDriver->volDelete) { + int ret; + ret = conn->storageDriver->volDelete (vol, flags); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(vol->conn); return -1; } @@ -5517,6 +6608,8 @@ virStorageVolFree(virStorageVolPtr vol) { DEBUG("vol=%p", vol); + virResetLastError(); + if (!VIR_IS_STORAGE_VOL(vol)) { virLibStorageVolError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__); return (-1); @@ -5544,23 +6637,34 @@ virStorageVolGetInfo(virStorageVolPtr vo virConnectPtr conn; DEBUG("vol=%p, info=%p", vol, info); + virResetLastError(); + if (!VIR_IS_CONNECTED_STORAGE_VOL(vol)) { virLibStorageVolError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__); return (-1); } if (info == NULL) { virLibStorageVolError(vol, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); + goto error; } memset(info, 0, sizeof(virStorageVolInfo)); conn = vol->conn; - if (conn->storageDriver->volGetInfo) - return conn->storageDriver->volGetInfo (vol, info); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + if (conn->storageDriver->volGetInfo){ + int ret; + ret = conn->storageDriver->volGetInfo (vol, info); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(vol->conn); return -1; } @@ -5582,23 +6686,33 @@ virStorageVolGetXMLDesc(virStorageVolPtr virConnectPtr conn; DEBUG("vol=%p, flags=%u", vol, flags); + virResetLastError(); + if (!VIR_IS_STORAGE_VOL(vol)) { virLibStorageVolError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__); return (NULL); } if (flags != 0) { virLibStorageVolError(vol, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (NULL); + goto error; } conn = vol->conn; - if (conn->storageDriver && conn->storageDriver->volGetXMLDesc) - return conn->storageDriver->volGetXMLDesc (vol, flags); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); - return NULL; - + if (conn->storageDriver && conn->storageDriver->volGetXMLDesc) { + char *ret; + ret = conn->storageDriver->volGetXMLDesc (vol, flags); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(vol->conn); + return NULL; } @@ -5620,6 +6734,8 @@ virStorageVolGetPath(virStorageVolPtr vo virConnectPtr conn; DEBUG("vol=%p", vol); + virResetLastError(); + if (!VIR_IS_STORAGE_VOL(vol)) { virLibStorageVolError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__); return (NULL); @@ -5627,10 +6743,19 @@ virStorageVolGetPath(virStorageVolPtr vo conn = vol->conn; - if (conn->storageDriver && conn->storageDriver->volGetPath) - return conn->storageDriver->volGetPath (vol); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + if (conn->storageDriver && conn->storageDriver->volGetPath) { + char *ret; + ret = conn->storageDriver->volGetPath (vol); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(vol->conn); return NULL; } @@ -5655,19 +6780,30 @@ virNodeNumOfDevices(virConnectPtr conn, { DEBUG("conn=%p, cap=%s, flags=%d", conn, cap, flags); + virResetLastError(); + if (!VIR_IS_CONNECT(conn)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); return (-1); } if (flags != 0) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); - } - - if (conn->deviceMonitor && conn->deviceMonitor->numOfDevices) - return conn->deviceMonitor->numOfDevices (conn, cap, flags); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + if (conn->deviceMonitor && conn->deviceMonitor->numOfDevices) { + int ret; + ret = conn->deviceMonitor->numOfDevices (conn, cap, flags); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return -1; } @@ -5696,19 +6832,30 @@ virNodeListDevices(virConnectPtr conn, DEBUG("conn=%p, cap=%s, names=%p, maxnames=%d, flags=%d", conn, cap, names, maxnames, flags); + virResetLastError(); + if (!VIR_IS_CONNECT(conn)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); return (-1); } if ((flags != 0) || (names == NULL) || (maxnames < 0)) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); - } - - if (conn->deviceMonitor && conn->deviceMonitor->listDevices) - return conn->deviceMonitor->listDevices (conn, cap, names, maxnames, flags); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + if (conn->deviceMonitor && conn->deviceMonitor->listDevices) { + int ret; + ret = conn->deviceMonitor->listDevices (conn, cap, names, maxnames, flags); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return -1; } @@ -5726,6 +6873,8 @@ virNodeDevicePtr virNodeDeviceLookupByNa { DEBUG("conn=%p, name=%p", conn, name); + virResetLastError(); + if (!VIR_IS_CONNECT(conn)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); return NULL; @@ -5733,13 +6882,22 @@ virNodeDevicePtr virNodeDeviceLookupByNa if (name == NULL) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return NULL; - } - - if (conn->deviceMonitor && conn->deviceMonitor->deviceLookupByName) - return conn->deviceMonitor->deviceLookupByName (conn, name); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + if (conn->deviceMonitor && conn->deviceMonitor->deviceLookupByName) { + virNodeDevicePtr ret; + ret = conn->deviceMonitor->deviceLookupByName (conn, name); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return NULL; } @@ -5758,15 +6916,26 @@ char *virNodeDeviceGetXMLDesc(virNodeDev { DEBUG("dev=%p, conn=%p", dev, dev ? dev->conn : NULL); + virResetLastError(); + if (!VIR_IS_CONNECTED_NODE_DEVICE(dev)) { virLibNodeDeviceError(NULL, VIR_ERR_INVALID_NODE_DEVICE, __FUNCTION__); return NULL; } - if (dev->conn->deviceMonitor && dev->conn->deviceMonitor->deviceDumpXML) - return dev->conn->deviceMonitor->deviceDumpXML (dev, flags); + if (dev->conn->deviceMonitor && dev->conn->deviceMonitor->deviceDumpXML) { + char *ret; + ret = dev->conn->deviceMonitor->deviceDumpXML (dev, flags); + if (!ret) + goto error; + return ret; + } virLibConnError (dev->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(dev->conn); return NULL; } @@ -5804,6 +6973,8 @@ const char *virNodeDeviceGetParent(virNo { DEBUG("dev=%p, conn=%p", dev, dev ? dev->conn : NULL); + virResetLastError(); + if (!VIR_IS_CONNECTED_NODE_DEVICE(dev)) { virLibNodeDeviceError(NULL, VIR_ERR_INVALID_NODE_DEVICE, __FUNCTION__); return NULL; @@ -5814,6 +6985,7 @@ const char *virNodeDeviceGetParent(virNo dev->parent = dev->conn->deviceMonitor->deviceGetParent (dev); } else { virLibConnError (dev->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + virSetConnError(dev->conn); return NULL; } } @@ -5832,15 +7004,26 @@ int virNodeDeviceNumOfCaps(virNodeDevice { DEBUG("dev=%p, conn=%p", dev, dev ? dev->conn : NULL); + virResetLastError(); + if (!VIR_IS_CONNECTED_NODE_DEVICE(dev)) { virLibNodeDeviceError(NULL, VIR_ERR_INVALID_NODE_DEVICE, __FUNCTION__); return -1; } - if (dev->conn->deviceMonitor && dev->conn->deviceMonitor->deviceNumOfCaps) - return dev->conn->deviceMonitor->deviceNumOfCaps (dev); + if (dev->conn->deviceMonitor && dev->conn->deviceMonitor->deviceNumOfCaps) { + int ret; + ret = dev->conn->deviceMonitor->deviceNumOfCaps (dev); + if (ret < 0) + goto error; + return ret; + } virLibConnError (dev->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(dev->conn); return -1; } @@ -5861,15 +7044,26 @@ int virNodeDeviceListCaps(virNodeDeviceP DEBUG("dev=%p, conn=%p, names=%p, maxnames=%d", dev, dev ? dev->conn : NULL, names, maxnames); + virResetLastError(); + if (!VIR_IS_CONNECTED_NODE_DEVICE(dev)) { virLibNodeDeviceError(NULL, VIR_ERR_INVALID_NODE_DEVICE, __FUNCTION__); return -1; } - if (dev->conn->deviceMonitor && dev->conn->deviceMonitor->deviceListCaps) - return dev->conn->deviceMonitor->deviceListCaps (dev, names, maxnames); + if (dev->conn->deviceMonitor && dev->conn->deviceMonitor->deviceListCaps) { + int ret; + ret = dev->conn->deviceMonitor->deviceListCaps (dev, names, maxnames); + if (ret < 0) + goto error; + return ret; + } virLibConnError (dev->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(dev->conn); return -1; } @@ -5887,6 +7081,8 @@ int virNodeDeviceFree(virNodeDevicePtr d { DEBUG("dev=%p, conn=%p", dev, dev ? dev->conn : NULL); + virResetLastError(); + if (!VIR_IS_CONNECTED_NODE_DEVICE(dev)) { virLibNodeDeviceError(NULL, VIR_ERR_INVALID_NODE_DEVICE, __FUNCTION__); return (-1); @@ -5919,6 +7115,8 @@ virConnectDomainEventRegister(virConnect void *opaque, virFreeCallback freecb) { + DEBUG("conn=%p, cb=%p, opaque=%p, freecb=%p", conn, cb, opaque, freecb); + virResetLastError(); if (!VIR_IS_CONNECT(conn)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); @@ -5926,11 +7124,21 @@ virConnectDomainEventRegister(virConnect } if (cb == NULL) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); - } - - if ((conn->driver) && (conn->driver->domainEventRegister)) - return conn->driver->domainEventRegister (conn, cb, opaque, freecb); + goto error; + } + + if ((conn->driver) && (conn->driver->domainEventRegister)) { + int ret; + ret = conn->driver->domainEventRegister (conn, cb, opaque, freecb); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError(conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); return -1; } @@ -5949,6 +7157,9 @@ int virConnectDomainEventDeregister(virConnectPtr conn, virConnectDomainEventCallback cb) { + DEBUG("conn=%p, cb=%p", conn, cb); + + virResetLastError(); if (!VIR_IS_CONNECT(conn)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); @@ -5956,12 +7167,21 @@ virConnectDomainEventDeregister(virConne } if (cb == NULL) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); - } - if ((conn->driver) && (conn->driver->domainEventDeregister)) - return conn->driver->domainEventDeregister (conn, cb); - - return -1; -} - - + goto error; + } + if ((conn->driver) && (conn->driver->domainEventDeregister)) { + int ret; + ret = conn->driver->domainEventDeregister (conn, cb); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError(conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); + return -1; +} + + diff --git a/src/virterror.c b/src/virterror.c --- a/src/virterror.c +++ b/src/virterror.c @@ -18,11 +18,11 @@ #include "virterror_internal.h" #include "datatypes.h" #include "logging.h" +#include "memory.h" +#include "threads.h" -virError virLastErr = /* the last error */ - { .code = 0, .domain = 0, .message = NULL, .level = VIR_ERR_NONE, - .conn = NULL, .dom = NULL, .str1 = NULL, .str2 = NULL, .str3 = NULL, - .int1 = 0, .int2 = 0, .net = NULL }; +virThreadLocal virLastErr; + virErrorFunc virErrorHandler = NULL; /* global error handler */ void *virUserData = NULL; /* associated data */ @@ -154,28 +154,118 @@ static const char *virErrorDomainName(vi return(dom); } + /* + * Internal helper that is called when a thread exits, to + * release the error object stored in the thread local + */ +static void +virLastErrFreeData(void *data) +{ + virErrorPtr err = data; + if (!err) + return; + virResetError(err); + VIR_FREE(err); +} + + +int +virErrorInitialize(void) +{ + return virThreadLocalInit(&virLastErr, virLastErrFreeData); +} + + +/* + * Internal helper to ensure a generic error code is stored + * in case where API returns failure, but forgot to set an + * error + */ +static void +virErrorGenericFailure(virErrorPtr err) +{ + err->code = VIR_ERR_INTERNAL_ERROR; + err->domain = VIR_FROM_NONE; + err->level = VIR_ERR_ERROR; + err->message = strdup(_("Unknown failure")); +} + + +/* + * Internal helper to perform a deep copy of the an error + */ +static int +virCopyError(virErrorPtr from, + virErrorPtr to) +{ + int ret = 0; + if (!to) + return 0; + virResetError(to); + if (!from) + return 0; + to->code = from->code; + to->domain = from->domain; + to->level = from->level; + if (from->message && !(to->message = strdup(from->message))) + ret = -1; + if (from->str1 && !(to->str1 = strdup(from->str1))) + ret = -1; + if (from->str2 && !(to->str2 = strdup(from->str2))) + ret = -1; + if (from->str3 && !(to->str3 = strdup(from->str3))) + ret = -1; + to->int1 = from->int1; + to->int2 = from->int2; + /* + * Delibrately not setting 'conn', 'dom', 'net' references + */ + return ret; +} + +static virErrorPtr +virLastErrorObject(void) +{ + virErrorPtr err; + err = virThreadLocalGet(&virLastErr); + if (!err) { + if (VIR_ALLOC(err) < 0) + return NULL; + virThreadLocalSet(&virLastErr, err); + } + return err; +} + + +/** * virGetLastError: * * Provide a pointer to the last error caught at the library level - * Simpler but may not be suitable for multithreaded accesses, in which - * case use virCopyLastError() + * + * The error object is kept in thread local storage, so separate + * threads can safely access this concurrently. * * Returns a pointer to the last error or NULL if none occurred. */ virErrorPtr virGetLastError(void) { - if (virLastErr.code == VIR_ERR_OK) - return (NULL); - return (&virLastErr); + virErrorPtr err = virLastErrorObject(); + if (!err || err->code == VIR_ERR_OK) + return NULL; + return err; } -/* +/** * virCopyLastError: * @to: target to receive the copy * * Copy the content of the last error caught at the library level + * + * The error object is kept in thread local storage, so separate + * threads can safely access this concurrently. + * * One will need to free the result with virResetError() * * Returns 0 if no error was found and the error code otherwise and -1 in case @@ -184,12 +274,14 @@ virGetLastError(void) int virCopyLastError(virErrorPtr to) { - if (to == NULL) - return (-1); - if (virLastErr.code == VIR_ERR_OK) - return (0); - memcpy(to, &virLastErr, sizeof(virError)); - return (virLastErr.code); + virErrorPtr err = virLastErrorObject(); + /* We can't guarentee caller has initialized it to zero */ + memset(to, 0, sizeof(*to)); + if (err) + virCopyError(err, to); + else + virResetError(to); + return to->code; } /** @@ -210,15 +302,22 @@ virResetError(virErrorPtr err) memset(err, 0, sizeof(virError)); } + /** * virResetLastError: * * Reset the last error caught at the library level. + * + * The error object is kept in thread local storage, so separate + * threads can safely access this concurrently, only resetting + * their own error object. */ void virResetLastError(void) { - virResetError(&virLastErr); + virErrorPtr err = virLastErrorObject(); + if (err) + virResetError(err); } /** @@ -226,8 +325,20 @@ virResetLastError(void) * @conn: pointer to the hypervisor connection * * Provide a pointer to the last error caught on that connection - * Simpler but may not be suitable for multithreaded accesses, in which - * case use virConnCopyLastError() + * + * This method is not protected against access from multiple + * threads. In a multi-threaded application, always use the + * global virGetLastError() API which is backed by thread + * local storage. + * + * If the connection object was discovered to be invalid by + * an API call, then the error will be reported against the + * global error object. + * + * Since 0.6.0, all errors reported in the per-connection object + * are also duplicated in the global error object. As such an + * application can always use virGetLastError(). This method + * remains for backwards compatability. * * Returns a pointer to the last error or NULL if none occurred. */ @@ -235,8 +346,8 @@ virErrorPtr virConnGetLastError(virConnectPtr conn) { if (conn == NULL) - return (NULL); - return (&conn->err); + return NULL; + return &conn->err; } /** @@ -245,6 +356,21 @@ virConnGetLastError(virConnectPtr conn) * @to: target to receive the copy * * Copy the content of the last error caught on that connection + * + * This method is not protected against access from multiple + * threads. In a multi-threaded application, always use the + * global virGetLastError() API which is backed by thread + * local storage. + * + * If the connection object was discovered to be invalid by + * an API call, then the error will be reported against the + * global error object. + * + * Since 0.6.0, all errors reported in the per-connection object + * are also duplicated in the global error object. As such an + * application can always use virGetLastError(). This method + * remains for backwards compatability. + * * One will need to free the result with virResetError() * * Returns 0 if no error was found and the error code otherwise and -1 in case @@ -253,20 +379,27 @@ virConnGetLastError(virConnectPtr conn) int virConnCopyLastError(virConnectPtr conn, virErrorPtr to) { + /* We can't guarentee caller has initialized it to zero */ + memset(to, 0, sizeof(*to)); + if (conn == NULL) - return (-1); - if (to == NULL) - return (-1); + return -1; + virMutexLock(&conn->lock); if (conn->err.code == VIR_ERR_OK) - return (0); - memcpy(to, &conn->err, sizeof(virError)); - return (conn->err.code); + virResetError(to); + else + virCopyError(&conn->err, to); + virMutexUnlock(&conn->lock); + return to->code; } /** * virConnResetLastError: * @conn: pointer to the hypervisor connection * + * The error object is kept in thread local storage, so separate + * threads can safely access this concurrently. + * * Reset the last error caught on that connection */ void @@ -274,7 +407,9 @@ virConnResetLastError(virConnectPtr conn { if (conn == NULL) return; + virMutexLock(&conn->lock); virResetError(&conn->err); + virMutexUnlock(&conn->lock); } /** @@ -309,8 +444,10 @@ virConnSetErrorFunc(virConnectPtr conn, { if (conn == NULL) return; + virMutexLock(&conn->lock); conn->handler = handler; conn->userData = userData; + virMutexUnlock(&conn->lock); } /** @@ -357,6 +494,44 @@ virDefaultErrorFunc(virErrorPtr err) dom, lvl, domain, network, err->message); } +/* + * Internal helper to ensure the global error object + * is initialized with a generic message if not already + * set. + */ +void +virSetGlobalError(void) +{ + virErrorPtr err = virLastErrorObject(); + + if (err && err->code == VIR_ERR_OK) + virErrorGenericFailure(err); +} + +/* + * Internal helper to ensure the connection error object + * is initialized from the global object. + */ +void +virSetConnError(virConnectPtr conn) +{ + virErrorPtr err = virLastErrorObject(); + + if (err && err->code == VIR_ERR_OK) + virErrorGenericFailure(err); + + if (conn) { + virMutexLock(&conn->lock); + if (err) + virCopyError(err, &conn->err); + else + virErrorGenericFailure(&conn->err); + virMutexUnlock(&conn->lock); + } +} + + + /** * virRaiseError: * @conn: the connection to the hypervisor if available @@ -377,16 +552,29 @@ virDefaultErrorFunc(virErrorPtr err) * immediately if a callback is found and store it for later handling. */ void -virRaiseError(virConnectPtr conn, virDomainPtr dom, virNetworkPtr net, +virRaiseError(virConnectPtr conn, + virDomainPtr dom ATTRIBUTE_UNUSED, + virNetworkPtr net ATTRIBUTE_UNUSED, int domain, int code, virErrorLevel level, const char *str1, const char *str2, const char *str3, int int1, int int2, const char *msg, ...) { - virErrorPtr to = &virLastErr; + virErrorPtr to; void *userData = virUserData; virErrorFunc handler = virErrorHandler; char *str; + /* + * All errors are recorded in thread local storage + * For compatability, public API calls will copy them + * to the per-connection error object when neccessary + */ + to = virLastErrorObject(); + if (!to) + return; /* Hit OOM allocating thread error object, sod all we can do now */ + + virResetError(to); + if (code == VIR_ERR_OK) return; @@ -394,11 +582,12 @@ virRaiseError(virConnectPtr conn, virDom * try to find the best place to save and report the error */ if (conn != NULL) { - to = &conn->err; + virMutexLock(&conn->lock); if (conn->handler != NULL) { handler = conn->handler; userData = conn->userData; } + virMutexUnlock(&conn->lock); } /* @@ -421,9 +610,10 @@ virRaiseError(virConnectPtr conn, virDom * Save the information about the error */ virResetError(to); - to->conn = conn; - to->dom = dom; - to->net = net; + /* + * Delibrately not setting conn, dom & net fields since + * they're utterly unsafe + */ to->domain = domain; to->code = code; to->message = str; @@ -813,3 +1003,5 @@ void virReportErrorHelper(virConnectPtr virerr, errorMessage, NULL, -1, -1, virerr, errorMessage); } + + diff --git a/src/virterror_internal.h b/src/virterror_internal.h --- a/src/virterror_internal.h +++ b/src/virterror_internal.h @@ -24,7 +24,6 @@ #include "internal.h" -extern virError virLastErr; extern virErrorFunc virErrorHandler; extern void *virUserData; @@ -33,6 +32,7 @@ extern void *virUserData; * API for error handling * * * ************************************************************************/ +int virErrorInitialize(void); void virRaiseError(virConnectPtr conn, virDomainPtr dom, virNetworkPtr net, @@ -53,4 +53,7 @@ void virReportErrorHelper(virConnectPtr ATTRIBUTE_FORMAT(printf, 7, 8); +void virSetGlobalError(void); +void virSetConnError(virConnectPtr conn); + #endif diff --git a/tests/cpuset b/tests/cpuset --- a/tests/cpuset +++ b/tests/cpuset @@ -40,6 +40,6 @@ libvir: Domain Config error : failed Xen error: Failed to define domain from xml-invalid EOF -compare out exp || fail=1 +compare exp out || fail=1 (exit $fail); exit $fail diff --git a/tests/read-bufsiz b/tests/read-bufsiz --- a/tests/read-bufsiz +++ b/tests/read-bufsiz @@ -37,7 +37,7 @@ for i in before after; do virsh --connect test:///default define $in > out || fail=1 printf "Domain test defined from $in\n\n" > exp || fail=1 - compare out exp || fail=1 + compare exp out || fail=1 done (exit $fail); exit $fail diff --git a/tests/start b/tests/start --- a/tests/start +++ b/tests/start @@ -34,9 +34,9 @@ virsh -c $test_url start test > out 2> e # stdout gets a newline echo > exp || fail=1 -compare out exp || fail=1 +compare exp out || fail=1 echo 'error: Domain is already active' > exp || fail=1 -compare err exp || fail=1 +compare exp err || fail=1 (exit $fail); exit $fail diff --git a/tests/undefine b/tests/undefine --- a/tests/undefine +++ b/tests/undefine @@ -9,7 +9,7 @@ # (at your option) any later version. # This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of +# but WITHEXP ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. @@ -32,7 +32,7 @@ cat <<\EOF > exp || fail=1 libvir: Test error : internal error Domain 'test' is still running error: Failed to undefine domain test EOF -compare out exp || fail=1 +compare exp out || fail=1 # A different diagnostic when specifying a domain ID virsh -q -c test:///default undefine 1 > out 2>&1 @@ -41,7 +41,7 @@ cat <<\EOF > exp || fail=1 error: a running domain like 1 cannot be undefined; to undefine, first shutdown then undefine using its name or UUID EOF -compare out exp || fail=1 +compare exp out || fail=1 # Succeed, now: first shut down, then undefine, both via name. virsh -q -c test:///default 'shutdown test; undefine test' > out 2>&1 @@ -50,6 +50,6 @@ cat <<\EOF > exp || fail=1 Domain test is being shutdown Domain test has been undefined EOF -compare out exp || fail=1 +compare exp out || fail=1 (exit $fail); exit $fail diff --git a/tests/vcpupin b/tests/vcpupin --- a/tests/vcpupin +++ b/tests/vcpupin @@ -32,7 +32,7 @@ cat <<\EOF > exp || fail=1 error: vcpupin: Invalid or missing vCPU number. EOF -compare out exp || fail=1 +compare exp out || fail=1 # An out-of-range vCPU number deserves a diagnostic, too. virsh --connect test:///default vcpupin test 100 0,1 > out 2>&1 @@ -41,6 +41,6 @@ cat <<\EOF > exp || fail=1 error: vcpupin: Invalid vCPU number. EOF -compare out exp || fail=1 +compare exp out || fail=1 (exit $fail); exit $fail -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list