
On Fri, Dec 12, 2008 at 01:31:24PM +0100, Daniel Veillard wrote:
On Fri, Dec 12, 2008 at 10:51:33AM +0000, Daniel P. Berrange wrote:
On Fri, Dec 12, 2008 at 09:46:14AM +0100, Daniel Veillard wrote:
On Thu, Dec 11, 2008 at 08:16:36PM +0000, Daniel P. Berrange wrote:
The current public API for error reporting consists of
- A global error object - A per-connection error object
Some functions always set errors on the global object. Other functions always set errors on the per-connection object, except when they set errors on the global object. Both have built-in race conditions if they are accessed from multiple threads because of the time between the API call raising the error, and the caller querying it.
The solution to this is to do away with all of the existing error objects and replace them with a per-thread error object. Well, except we can't do away with existing objects because of ABI compatability. This turns out to not be such a bad problem after all....
So with this patch...
virterror.c gets ability to track a per-thread virErrorPtr instance. This object is stored in a thread local variable via pthread_{get,set}specific. It is allocated when first required, and deleted when the thread exits
Every single API will *always* set the virErrorPtr object associated with its current thread.
In the public virterror.h we add
virErrorPtr virThreadGetLastError (void); int virThreadCopyLastError (virErrorPtr to); void virThreadResetLastError (void);
This provides a guarenteed thread-safe public API for fetching error information. All the other existing APIs have docs updated to recommend against their use.
I understand the problem but I don't understand the way you expect to fix it. Historically this copies the libxml2 error APIs, but in libxml2 the error data are stored in thread safe local storage. Until now basically libvirt could not be used in a threaded way or at least not without lot of constraints. Now we are getting thread safe, I suggest to just retrofit thread safety into the exiting API, since they have the exact same signature I see no reason to annoy the application writer with extra API and deprecated ones. If the application is single threaded nothing changes for them in practice. If the application is multi-threaded the old behaviour wasn't making sense, could not be trusted and the new code does basically "the right thing" now.
Yes, I guess that does atually make sense.
So I'll make the global virGetLastError() thread-safe, and then there's no need for the new APIs, and also no need for anyone to call the virConnGetLastError(), though I'll make sure that still syncs to whatever error is stored in the global location anyway.
okay, cool !
Try out this patch. The virConn*Error methods are left as is, and the global vir*Error methods are made to use a thread local Daniel diff --git a/src/datatypes.c b/src/datatypes.c --- a/src/datatypes.c +++ b/src/datatypes.c @@ -192,8 +192,6 @@ virReleaseConnect(virConnectPtr conn) { virHashFree(conn->nodeDevices, (virHashDeallocator) virNodeDeviceFree); virResetError(&conn->err); - if (virLastErr.conn == conn) - virLastErr.conn = NULL; xmlFreeURI(conn->uri); @@ -216,7 +214,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); } pthread_mutex_lock(&conn->lock); @@ -250,7 +248,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); } pthread_mutex_lock(&conn->lock); @@ -320,10 +318,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); @@ -355,7 +349,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); } pthread_mutex_lock(&domain->conn->lock); @@ -390,7 +384,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); } pthread_mutex_lock(&conn->lock); @@ -456,11 +450,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); @@ -491,7 +480,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); } pthread_mutex_lock(&network->conn->lock); @@ -527,7 +516,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); } pthread_mutex_lock(&conn->lock); @@ -624,7 +613,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); } pthread_mutex_lock(&pool->conn->lock); @@ -661,7 +650,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); } pthread_mutex_lock(&conn->lock); @@ -762,7 +751,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); } pthread_mutex_lock(&vol->conn->lock); @@ -798,7 +787,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); } pthread_mutex_lock(&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 */ PTHREAD_MUTEX_T (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 @@ -791,6 +791,8 @@ do_open (const char *name, { int i, res; virConnectPtr ret; + + virResetLastError(); ret = virGetConnect(); if (ret == NULL) @@ -945,17 +947,8 @@ failed: 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); @@ -1050,8 +1043,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); @@ -1073,12 +1070,20 @@ int 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; } /** @@ -1097,6 +1102,8 @@ virConnectGetType(virConnectPtr conn) { const char *ret; DEBUG("conn=%p", conn); + + virResetLastError(); if (!VIR_IS_CONNECT(conn)) { virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); @@ -1128,20 +1135,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; } @@ -1162,15 +1179,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; } @@ -1193,8 +1220,9 @@ virConnectGetURI (virConnectPtr conn) 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__); @@ -1204,15 +1232,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; } /** @@ -1232,15 +1268,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; } @@ -1259,20 +1304,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; } @@ -1289,15 +1343,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; } @@ -1320,7 +1383,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; } @@ -1348,23 +1413,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); + goto error; } 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->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; } @@ -1404,19 +1479,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; } @@ -1435,19 +1521,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; } @@ -1470,14 +1567,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? @@ -1495,12 +1593,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; } /** @@ -1518,19 +1621,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; } @@ -1552,21 +1666,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; } @@ -1584,12 +1709,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); } @@ -1611,21 +1738,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; } @@ -1645,21 +1783,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; } @@ -1682,18 +1831,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; } /* @@ -1716,10 +1867,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; } @@ -1738,17 +1898,19 @@ virDomainRestore(virConnectPtr conn, con char filepath[4096]; DEBUG("conn=%p, from=%s", conn, from); + 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__); - return (-1); + goto error; } if (from == NULL) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); + goto error; } /* @@ -1759,21 +1921,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; } @@ -1796,18 +1973,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; } /* @@ -1818,22 +1997,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; } @@ -1856,21 +2050,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; } @@ -1891,21 +2096,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; } @@ -1923,6 +2139,8 @@ virDomainGetName(virDomainPtr domain) { DEBUG("domain=%p", domain); + virResetLastError(); + if (!VIR_IS_DOMAIN(domain)) { virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); return (NULL); @@ -1944,12 +2162,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); } @@ -1974,20 +2196,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; } /** @@ -2003,6 +2232,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); @@ -2025,17 +2256,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; } @@ -2055,6 +2297,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); @@ -2062,10 +2306,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; } @@ -2087,28 +2340,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; } @@ -2130,29 +2390,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; } @@ -2173,23 +2440,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; } @@ -2210,17 +2488,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; } @@ -2289,14 +2578,16 @@ 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; + goto error; } /* Check that migration is supported by both drivers. */ @@ -2312,7 +2603,7 @@ virDomainMigrate (virDomainPtr domain, version = 2; else { virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); - return NULL; + goto error; } /* Prepare the migration. @@ -2347,13 +2638,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, @@ -2403,6 +2694,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; } /* @@ -2421,17 +2717,28 @@ 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; } - if (dconn->driver->domainMigratePrepare) - return dconn->driver->domainMigratePrepare (dconn, cookie, cookielen, - uri_in, uri_out, - flags, dname, bandwidth); + 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; } @@ -2451,18 +2758,29 @@ 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; } conn = domain->conn; - if (conn->driver->domainMigratePerform) - return conn->driver->domainMigratePerform (domain, cookie, cookielen, - uri, - flags, dname, bandwidth); + 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; } @@ -2480,17 +2798,28 @@ 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; } - if (dconn->driver->domainMigrateFinish) - return dconn->driver->domainMigrateFinish (dconn, dname, - cookie, cookielen, - uri, flags); + 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; } @@ -2512,18 +2841,29 @@ 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; } - if (dconn->driver->domainMigratePrepare2) - return dconn->driver->domainMigratePrepare2 (dconn, cookie, cookielen, - uri_in, uri_out, - flags, dname, bandwidth, - dom_xml); + 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; } @@ -2542,18 +2882,29 @@ 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; } - if (dconn->driver->domainMigrateFinish2) - return dconn->driver->domainMigrateFinish2 (dconn, dname, - cookie, cookielen, - uri, flags, - retcode); + 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; } @@ -2572,19 +2923,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; } @@ -2603,15 +2965,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; } @@ -2627,16 +3000,27 @@ virNodeGetFreeMemory(virConnectPtr conn) 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; } @@ -2656,6 +3040,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; @@ -2664,10 +3050,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; } @@ -2693,16 +3085,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; } @@ -2725,20 +3128,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; } @@ -2774,25 +3188,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; } @@ -2826,25 +3246,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; } @@ -2899,6 +3325,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; @@ -2908,27 +3336,36 @@ virDomainBlockPeek (virDomainPtr dom, 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; } @@ -2973,6 +3410,8 @@ virDomainMemoryPeek (virDomainPtr dom, virConnectPtr conn; 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__); @@ -3004,21 +3443,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; } @@ -3044,23 +3492,34 @@ virDomainDefineXML(virConnectPtr conn, c virDomainDefineXML(virConnectPtr conn, const char *xml) { DEBUG("conn=%p, xml=%s", conn, xml); + 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__); - return (NULL); + 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; } @@ -3077,20 +3536,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; } @@ -3107,15 +3577,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; } @@ -3135,6 +3616,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); @@ -3142,13 +3625,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; } @@ -3166,24 +3658,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; } @@ -3205,21 +3704,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; } @@ -3240,17 +3750,28 @@ 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 (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 (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; } @@ -3273,29 +3794,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; } @@ -3324,30 +3852,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; } @@ -3379,30 +3914,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; } @@ -3424,17 +3966,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; } @@ -3454,20 +4007,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; } @@ -3486,20 +4050,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; } @@ -3528,6 +4103,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); @@ -3535,13 +4112,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; } @@ -3564,7 +4150,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; } @@ -3584,15 +4172,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; } @@ -3611,6 +4210,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); @@ -3618,13 +4219,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; } @@ -3641,15 +4251,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; } @@ -3669,6 +4290,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); @@ -3676,14 +4299,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; } @@ -3702,19 +4334,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; } @@ -3733,19 +4376,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; } @@ -3767,13 +4421,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. @@ -3792,12 +4448,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; } /** @@ -3815,23 +4476,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); + goto error; } 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->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; } @@ -3849,23 +4521,34 @@ virNetworkDefineXML(virConnectPtr conn, { DEBUG("conn=%p, xml=%s", conn, xml); + 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__); - return (NULL); + 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; } @@ -3882,6 +4565,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); @@ -3889,13 +4574,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; } @@ -3914,10 +4608,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); @@ -3925,13 +4617,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; } @@ -3952,6 +4653,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); @@ -3960,13 +4663,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; } @@ -3984,7 +4696,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); } @@ -4007,6 +4721,8 @@ virNetworkGetName(virNetworkPtr network) { DEBUG("network=%p", network); + virResetLastError(); + if (!VIR_IS_NETWORK(network)) { virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); return (NULL); @@ -4027,6 +4743,8 @@ virNetworkGetUUID(virNetworkPtr network, virNetworkGetUUID(virNetworkPtr network, unsigned char *uuid) { DEBUG("network=%p, uuid=%p", network, uuid); + + virResetLastError(); if (!VIR_IS_NETWORK(network)) { virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); @@ -4034,12 +4752,17 @@ virNetworkGetUUID(virNetworkPtr network, } 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; } /** @@ -4058,13 +4781,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])) @@ -4072,6 +4797,11 @@ virNetworkGetUUIDString(virNetworkPtr ne virUUIDFormat(uuid, buf); return (0); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(network->conn); + return -1; } /** @@ -4091,21 +4821,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; } @@ -4125,17 +4866,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; } @@ -4157,21 +4909,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; } @@ -4192,17 +4955,28 @@ 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); } 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; } @@ -4226,7 +5000,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; } @@ -4246,15 +5022,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; } @@ -4277,6 +5064,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); @@ -4284,15 +5073,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; } @@ -4309,15 +5106,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; } @@ -4341,6 +5149,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); @@ -4348,13 +5158,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; } @@ -4386,19 +5205,32 @@ virConnectFindStoragePoolSources(virConn const char *srcSpec, unsigned int flags) { + 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__); return NULL; } if (type == NULL) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __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->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; } @@ -4418,19 +5250,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; } @@ -4450,21 +5293,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; } @@ -4479,26 +5332,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; } @@ -4515,17 +5375,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; } /** @@ -4547,23 +5417,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); + goto error; } 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->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; } @@ -4585,25 +5466,35 @@ virStoragePoolDefineXML(virConnectPtr co { DEBUG("conn=%p, xml=%s", conn, xml); + 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__); - return (NULL); + 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; } /** @@ -4622,6 +5513,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); @@ -4629,15 +5522,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; } @@ -4655,6 +5556,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); @@ -4662,15 +5565,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; } @@ -4690,10 +5601,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); @@ -4701,15 +5610,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; } @@ -4731,6 +5648,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); @@ -4739,13 +5658,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; } @@ -4767,6 +5695,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); @@ -4775,13 +5705,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; } @@ -4800,7 +5739,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); } @@ -4829,6 +5770,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); @@ -4837,13 +5780,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; } @@ -4861,12 +5813,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); - } @@ -4885,19 +5838,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; } /** @@ -4916,21 +5875,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; } @@ -4951,25 +5916,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; } @@ -4991,23 +5966,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; } @@ -5028,21 +6013,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; } @@ -5063,17 +6059,28 @@ 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); - } - - conn = pool->conn; - - if (conn->storageDriver && conn->storageDriver->poolSetAutostart) - return conn->storageDriver->poolSetAutostart (pool, autostart); - - virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + virResetLastError(); + + if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) { + virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); + return (-1); + } + + 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; } @@ -5090,16 +6097,27 @@ virStoragePoolNumOfVolumes(virStoragePoo virStoragePoolNumOfVolumes(virStoragePoolPtr pool) { 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; } @@ -5122,6 +6140,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); @@ -5129,13 +6149,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; } @@ -5159,6 +6188,8 @@ virStorageVolGetConnect (virStorageVolPt { DEBUG("vol=%p", vol); + virResetLastError(); + if (!VIR_IS_STORAGE_VOL (vol)) { virLibStoragePoolError (NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__); return NULL; @@ -5183,19 +6214,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; } @@ -5217,19 +6259,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; } @@ -5249,19 +6302,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; } @@ -5279,6 +6343,8 @@ virStorageVolGetName(virStorageVolPtr vo virStorageVolGetName(virStorageVolPtr vol) { DEBUG("vol=%p", vol); + + virResetLastError(); if (!VIR_IS_STORAGE_VOL(vol)) { virLibStorageVolError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__); @@ -5302,6 +6368,8 @@ virStorageVolGetKey(virStorageVolPtr vol virStorageVolGetKey(virStorageVolPtr vol) { DEBUG("vol=%p", vol); + + virResetLastError(); if (!VIR_IS_STORAGE_VOL(vol)) { virLibStorageVolError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__); @@ -5330,6 +6398,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); @@ -5337,13 +6407,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; } @@ -5364,6 +6443,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); @@ -5372,13 +6453,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; } @@ -5397,6 +6487,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); @@ -5424,23 +6516,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; } @@ -5462,23 +6565,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; } @@ -5500,6 +6613,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); @@ -5507,10 +6622,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; } @@ -5535,19 +6659,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; } @@ -5576,19 +6711,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; } @@ -5606,6 +6752,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; @@ -5613,13 +6761,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; } @@ -5638,15 +6795,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; } @@ -5683,6 +6851,8 @@ const char *virNodeDeviceGetParent(virNo const char *virNodeDeviceGetParent(virNodeDevicePtr dev) { 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__); @@ -5694,6 +6864,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; } } @@ -5712,15 +6883,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; } @@ -5741,15 +6923,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; } @@ -5766,6 +6959,8 @@ int virNodeDeviceFree(virNodeDevicePtr d int virNodeDeviceFree(virNodeDevicePtr dev) { 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__); @@ -5799,6 +6994,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__); @@ -5806,11 +7003,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; } @@ -5829,6 +7036,9 @@ virConnectDomainEventDeregister(virConne 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__); @@ -5836,12 +7046,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/libvirt_sym.version.in b/src/libvirt_sym.version.in --- a/src/libvirt_sym.version.in +++ b/src/libvirt_sym.version.in @@ -249,7 +249,7 @@ LIBVIRT_0.5.0 { } LIBVIRT_0.4.5; -/* no new entry point in 0.5.1 */ + /* .... define new API here using predicted next version number .... */ diff --git a/src/virterror.c b/src/virterror.c --- a/src/virterror.c +++ b/src/virterror.c @@ -17,11 +17,18 @@ #include "virterror_internal.h" #include "datatypes.h" +#include "memory.h" -virError virLastErr = /* the last error */ +#ifdef HAVE_PTHREAD_H +pthread_once_t virLastErrInit = PTHREAD_ONCE_INIT; +pthread_key_t virLastErr; +#else +static 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 }; +#endif + virErrorFunc virErrorHandler = NULL; /* global error handler */ void *virUserData = NULL; /* associated data */ @@ -62,28 +69,129 @@ void *virUserData = NULL; /* asso }} \ } + +#ifdef HAVE_PTHREAD_H /* + * 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); +} + + +/* + * Internal helper called *once* by pthread_once() to create the + * thread local field we store errors in + */ +static void +virLastErrCreate(void) +{ + pthread_key_create(&virLastErr, virLastErrFreeData); +} +#endif + + +/* + * 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; +#ifdef HAVE_PTHREAD_H + pthread_once(&virLastErrInit, virLastErrCreate); + err = pthread_getspecific(virLastErr); + if (!err) { + if (VIR_ALLOC(err) < 0) + return NULL; + pthread_setspecific(virLastErr, err); + } +#else + err = &virLastErr; +#endif + 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 @@ -92,12 +200,12 @@ int 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(); + if (err) + virCopyError(err, to); + else + virResetError(to); + return to->code; } /** @@ -118,15 +226,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); } /** @@ -134,8 +249,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. */ @@ -143,8 +270,8 @@ virConnGetLastError(virConnectPtr conn) virConnGetLastError(virConnectPtr conn) { if (conn == NULL) - return (NULL); - return (&conn->err); + return NULL; + return &conn->err; } /** @@ -153,6 +280,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 @@ -162,18 +304,22 @@ virConnCopyLastError(virConnectPtr conn, virConnCopyLastError(virConnectPtr conn, virErrorPtr to) { if (conn == NULL) - return (-1); - if (to == NULL) - return (-1); + return -1; + pthread_mutex_lock(&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); + pthread_mutex_unlock(&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 */ @@ -182,7 +328,9 @@ virConnResetLastError(virConnectPtr conn { if (conn == NULL) return; + pthread_mutex_lock(&conn->lock); virResetError(&conn->err); + pthread_mutex_unlock(&conn->lock); } /** @@ -217,8 +365,10 @@ virConnSetErrorFunc(virConnectPtr conn, { if (conn == NULL) return; + pthread_mutex_lock(&conn->lock); conn->handler = handler; conn->userData = userData; + pthread_mutex_unlock(&conn->lock); } /** @@ -338,6 +488,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) { + pthread_mutex_lock(&conn->lock); + if (err) + virCopyError(err, &conn->err); + else + virErrorGenericFailure(&conn->err); + pthread_mutex_unlock(&conn->lock); + } +} + + + /** * virRaiseError: * @conn: the connection to the hypervisor if available @@ -358,15 +546,28 @@ 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 = virGetLastError(); + if (!to) + return; /* Hit OOM allocating thread error object, sod all we can do now */ + + virResetError(to); if (code == VIR_ERR_OK) return; @@ -375,11 +576,12 @@ virRaiseError(virConnectPtr conn, virDom * try to find the best place to save and report the error */ if (conn != NULL) { - to = &conn->err; + pthread_mutex_lock(&conn->lock); if (conn->handler != NULL) { handler = conn->handler; userData = conn->userData; } + pthread_mutex_unlock(&conn->lock); } /* @@ -395,9 +597,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; @@ -787,3 +990,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; @@ -53,4 +52,7 @@ void virReportErrorHelper(virConnectPtr ATTRIBUTE_FORMAT(printf, 7, 8); +void virSetGlobalError(void); +void virSetConnError(virConnectPtr conn); + #endif -- |: 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 :|