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. In libvirt.c, in any exit paths which result in an error code, we copy the per-thread virErrorPtr object into either the global error object or per-connection object as applicable for the scenario. This gives us 100% backwards compatability. NB, we hold a lock when doing this so that these are race-free when setting them. At the start of every API call, we call virThreadResetLastError() and at any exit path with an error, if the error object is not set, then we set a generic error message. This means that if the internal driver code is broken and forgets to raise an error, the caller will still at least see a generic error report. Finally, virCopyLastError and virConnCopyLastError were not correctly strdup'ing the char * fields. This meant that if the original error was cleared, you'd get a use-after-free error, shortly followed by a double-free error if the first didn't kill you. This patch also fixes those two methods to correctly strdup the char *. As for language bindings, they should *all* be updated to use the virThreadGetLastError() method, and *never* call virGetLastError() or the virConnGetLastError() calls. With this patch applied, assuming all the per-hypervisor drivers are thread-safe (they are except for Xen which is still TODO), then the public API for virConectPtr is also (almost[1]) guarenteed to be thread- safe. include/libvirt/virterror.h | 7 src/datatypes.c | 11 src/datatypes.h | 15 src/libvirt.c | 3729 ++++++++++++++++++++++++++++++-------------- src/libvirt_sym.version.in | 8 src/virterror.c | 281 +++ src/virterror_internal.h | 4 7 files changed, 2902 insertions(+), 1153 deletions(-) Daniel [1] We need to fix lots of stupid internal mistakes like strerror() vs strerror_r() - these were already a problem even with libvirt being single-threaded on virConnectPtr, because the app using libvirt could be threaded. More on this later... diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -187,6 +187,13 @@ void virConnSetErrorFunc (virConnectPt virErrorFunc handler); int virConnCopyLastError (virConnectPtr conn, virErrorPtr to); + + +virErrorPtr virThreadGetLastError (void); +int virThreadCopyLastError (virErrorPtr to); +void virThreadResetLastError (void); + + #ifdef __cplusplus } #endif 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); @@ -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); @@ -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); 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 @@ -778,6 +778,8 @@ virGetVersion(unsigned long *libVer, con #endif if (*typeVer == 0) { virLibConnError(NULL, VIR_ERR_NO_SUPPORT, type); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); return (-1); } } @@ -791,6 +793,8 @@ do_open (const char *name, { int i, res; virConnectPtr ret; + + virThreadResetLastError(); ret = virGetConnect(); if (ret == NULL) @@ -945,17 +949,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")); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); virUnrefConnect(ret); @@ -1050,8 +1045,16 @@ virConnectClose(virConnectPtr conn) { DEBUG("conn=%p", conn); - if (!VIR_IS_CONNECT(conn)) - return (-1); + virThreadResetLastError(); + + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + return (-1); + } if (conn->networkDriver) conn->networkDriver->close (conn); @@ -1061,8 +1064,11 @@ virConnectClose(virConnectPtr conn) conn->deviceMonitor->close (conn); conn->driver->close (conn); - if (virUnrefConnect(conn) < 0) - return (-1); + if (virUnrefConnect(conn) < 0) { + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); + return (-1); + } return (0); } @@ -1073,12 +1079,22 @@ 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); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + return (-1); + } + + ret = VIR_DRV_SUPPORTS_FEATURE (conn->driver, conn, feature); + /* Copy to connection error object for back compatability */ + virThreadSetConnError(conn); + return ret; } /** @@ -1098,8 +1114,12 @@ virConnectGetType(virConnectPtr conn) const char *ret; DEBUG("conn=%p", conn); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); return (NULL); } @@ -1128,20 +1148,32 @@ virConnectGetVersion(virConnectPtr conn, { DEBUG("conn=%p, hvVer=%p", conn, hvVer); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); - return (-1); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(conn); return -1; } @@ -1162,15 +1194,27 @@ 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__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(conn); return NULL; } @@ -1193,26 +1237,37 @@ virConnectGetURI (virConnectPtr conn) virConnectGetURI (virConnectPtr conn) { char *name; - - DEBUG("conn=%p", conn); - - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + DEBUG("conn=%p", conn); + + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); return NULL; } /* 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 */ + virThreadSetConnError(conn); + return NULL; } /** @@ -1232,15 +1287,26 @@ 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__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(conn); return -1; } @@ -1259,20 +1325,31 @@ 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); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(conn); return -1; } @@ -1289,15 +1366,26 @@ 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__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(conn); return -1; } @@ -1320,8 +1408,12 @@ virDomainGetConnect (virDomainPtr dom) { DEBUG("dom=%p", dom); + virThreadResetLastError(); + if (!VIR_IS_DOMAIN (dom)) { virLibDomainError (NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); return NULL; } return dom->conn; @@ -1348,23 +1440,35 @@ virDomainCreateXML(virConnectPtr conn, c { DEBUG("conn=%p, xmlDesc=%s, flags=%d", conn, xmlDesc, flags); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(conn); return NULL; } @@ -1404,19 +1508,32 @@ virDomainLookupByID(virConnectPtr conn, { DEBUG("conn=%p, id=%d", conn, id); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(conn); return NULL; } @@ -1435,19 +1552,32 @@ virDomainLookupByUUID(virConnectPtr conn { DEBUG("conn=%p, uuid=%s", conn, uuid); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(conn); return NULL; } @@ -1470,14 +1600,17 @@ virDomainLookupByUUIDString(virConnectPt DEBUG("conn=%p, uuidstr=%s", conn, uuidstr); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); 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 +1628,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 */ + virThreadSetConnError(conn); + return NULL; } /** @@ -1518,19 +1656,32 @@ virDomainLookupByName(virConnectPtr conn { DEBUG("conn=%p, name=%s", conn, name); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(conn); return NULL; } @@ -1552,21 +1703,34 @@ 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__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(conn); return -1; } @@ -1584,12 +1748,18 @@ virDomainFree(virDomainPtr domain) { DEBUG("domain=%p", domain); - if (!VIR_IS_DOMAIN(domain)) { - virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); - return (-1); - } - if (virUnrefDomain(domain) < 0) - return (-1); + virThreadResetLastError(); + + if (!VIR_IS_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); + return (-1); + } + if (virUnrefDomain(domain) < 0) { + virThreadSetGlobalError(); + return -1; + } return(0); } @@ -1611,21 +1781,34 @@ 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__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(domain->conn); return -1; } @@ -1645,21 +1828,34 @@ 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__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(domain->conn); return -1; } @@ -1682,18 +1878,22 @@ 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); + virThreadResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + 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 +1916,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 */ + virThreadSetConnError(domain->conn); return -1; } @@ -1738,17 +1947,21 @@ virDomainRestore(virConnectPtr conn, con char filepath[4096]; DEBUG("conn=%p, from=%s", conn, from); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); 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 +1972,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 */ + virThreadSetConnError(conn); return -1; } @@ -1796,18 +2024,22 @@ 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); + virThreadResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + 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 +2050,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 */ + virThreadSetConnError(domain->conn); return -1; } @@ -1856,21 +2103,34 @@ 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__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(domain->conn); return -1; } @@ -1891,21 +2151,34 @@ 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__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(domain->conn); return -1; } @@ -1923,8 +2196,12 @@ virDomainGetName(virDomainPtr domain) { DEBUG("domain=%p", domain); - if (!VIR_IS_DOMAIN(domain)) { - virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); return (NULL); } return (domain->name); @@ -1944,12 +2221,18 @@ virDomainGetUUID(virDomainPtr domain, un { DEBUG("domain=%p, uuid=%p", domain, uuid); - if (!VIR_IS_DOMAIN(domain)) { - virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); return (-1); } if (uuid == NULL) { virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetConnError(domain->conn); return (-1); } @@ -1974,20 +2257,29 @@ virDomainGetUUIDString(virDomainPtr doma unsigned char uuid[VIR_UUID_BUFLEN]; DEBUG("domain=%p, buf=%p", domain, buf); - if (!VIR_IS_DOMAIN(domain)) { - virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(domain->conn); + return -1; } /** @@ -2003,8 +2295,12 @@ virDomainGetID(virDomainPtr domain) { DEBUG("domain=%p", domain); - if (!VIR_IS_DOMAIN(domain)) { - virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); return ((unsigned int) -1); } return (domain->id); @@ -2025,17 +2321,30 @@ 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__); + virThreadResetLastError(); + + if (!VIR_IS_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(domain->conn); return NULL; } @@ -2055,17 +2364,30 @@ virDomainGetMaxMemory(virDomainPtr domai virConnectPtr conn; DEBUG("domain=%p", domain); - if (!VIR_IS_CONNECTED_DOMAIN(domain)) { - virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); return (0); } 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 */ + virThreadSetConnError(domain->conn); return 0; } @@ -2087,28 +2409,37 @@ 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); + virThreadResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(domain->conn); return -1; } @@ -2130,29 +2461,38 @@ 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); + virThreadResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(domain->conn); return -1; } @@ -2173,23 +2513,36 @@ virDomainGetInfo(virDomainPtr domain, vi virConnectPtr conn; DEBUG("domain=%p, info=%p", domain, info); - if (!VIR_IS_CONNECTED_DOMAIN(domain)) { - virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(domain->conn); return -1; } @@ -2210,17 +2563,30 @@ 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__); + virThreadResetLastError(); + + if (!VIR_IS_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(domain->conn); return NULL; } @@ -2289,14 +2655,18 @@ virDomainMigrate (virDomainPtr domain, DEBUG("domain=%p, dconn=%p, flags=%lu, dname=%s, uri=%s, bandwidth=%lu", domain, dconn, flags, dname, uri, bandwidth); + virThreadResetLastError(); + if (!VIR_IS_DOMAIN (domain)) { virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); 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 +2682,7 @@ virDomainMigrate (virDomainPtr domain, version = 2; else { virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); - return NULL; + goto error; } /* Prepare the migration. @@ -2347,13 +2717,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 +2773,11 @@ virDomainMigrate (virDomainPtr domain, free (uri_out); free (cookie); return ddomain; + +error: + /* Copy to connection error object for back compatability */ + virThreadSetConnError(domain->conn); + return NULL; } /* @@ -2421,17 +2796,30 @@ 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); + virThreadResetLastError(); + 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); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + return -1; + } + + 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 */ + virThreadSetConnError(dconn); return -1; } @@ -2451,18 +2839,31 @@ 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); + virThreadResetLastError(); + if (!VIR_IS_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); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); + return -1; + } + conn = domain->conn; + + 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 */ + virThreadSetConnError(domain->conn); return -1; } @@ -2480,17 +2881,30 @@ virDomainMigrateFinish (virConnectPtr dc { DEBUG("dconn=%p, dname=%s, cookie=%p, cookielen=%d, uri=%s, flags=%lu", dconn, dname, cookie, cookielen, uri, flags); + virThreadResetLastError(); + 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); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + return NULL; + } + + 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 */ + virThreadSetConnError(dconn); return NULL; } @@ -2512,18 +2926,31 @@ 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); + virThreadResetLastError(); + 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); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + return -1; + } + + 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 */ + virThreadSetConnError(dconn); return -1; } @@ -2542,18 +2969,31 @@ 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); + virThreadResetLastError(); + 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); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + return NULL; + } + + 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 */ + virThreadSetConnError(dconn); return NULL; } @@ -2572,19 +3012,32 @@ virNodeGetInfo(virConnectPtr conn, virNo { DEBUG("conn=%p, info=%p", conn, info); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(conn); return -1; } @@ -2603,15 +3056,28 @@ virConnectGetCapabilities (virConnectPtr { DEBUG("conn=%p", conn); + virThreadResetLastError(); + 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__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + return NULL; + } + + 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 */ + virThreadSetConnError(conn); return NULL; } @@ -2628,15 +3094,28 @@ virNodeGetFreeMemory(virConnectPtr conn) { DEBUG("conn=%p", conn); + virThreadResetLastError(); + if (!VIR_IS_CONNECT (conn)) { virLibConnError (NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(conn); return 0; } @@ -2656,18 +3135,28 @@ virDomainGetSchedulerType(virDomainPtr d char *schedtype; DEBUG("domain=%p, nparams=%p", domain, nparams); - if (!VIR_IS_CONNECTED_DOMAIN(domain)) { - virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); return NULL; } conn = domain->conn; 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 */ + virThreadSetConnError(domain->conn); return NULL; } @@ -2693,16 +3182,29 @@ 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__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(domain->conn); return -1; } @@ -2725,20 +3227,33 @@ 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__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(domain->conn); return -1; } @@ -2774,25 +3289,33 @@ 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); + virThreadResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN (dom)) { + virLibDomainError (NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(dom->conn); return -1; } @@ -2826,25 +3349,33 @@ virDomainInterfaceStats (virDomainPtr do -1, -1, -1, -1 }; DEBUG("domain=%p, path=%s, stats=%p, size=%zi", dom, path, stats, size); + virThreadResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN (dom)) { + virLibDomainError (NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(dom->conn); return -1; } @@ -2899,8 +3430,12 @@ virDomainBlockPeek (virDomainPtr dom, DEBUG("domain=%p, path=%s, offset=%lld, size=%zi, buffer=%p", dom, path, offset, size, buffer); + virThreadResetLastError(); + if (!VIR_IS_CONNECTED_DOMAIN (dom)) { virLibDomainError (NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); return -1; } conn = dom->conn; @@ -2908,27 +3443,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 */ + virThreadSetConnError(dom->conn); return -1; } @@ -2974,8 +3518,12 @@ virDomainMemoryPeek (virDomainPtr dom, DEBUG ("domain=%p, start=%lld, size=%zi, buffer=%p, flags=%d", dom, start, size, buffer, flags); + virThreadResetLastError(); + if (!VIR_IS_CONNECTED_DOMAIN (dom)) { virLibDomainError (NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); return -1; } conn = dom->conn; @@ -3004,21 +3552,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 */ + virThreadSetConnError(dom->conn); return -1; } @@ -3044,23 +3601,36 @@ virDomainDefineXML(virConnectPtr conn, c virDomainDefineXML(virConnectPtr conn, const char *xml) { DEBUG("conn=%p, xml=%s", conn, xml); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(conn); return NULL; } @@ -3077,20 +3647,33 @@ 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__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(domain->conn); return -1; } @@ -3107,15 +3690,28 @@ 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__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(conn); return -1; } @@ -3135,20 +3731,33 @@ virConnectListDefinedDomains(virConnectP int maxnames) { DEBUG("conn=%p, names=%p, maxnames=%d", conn, names, maxnames); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); return (-1); } 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 */ + virThreadSetConnError(conn); return -1; } @@ -3166,24 +3775,33 @@ 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__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(domain->conn); return -1; } @@ -3205,21 +3823,34 @@ virDomainGetAutostart(virDomainPtr domai virConnectPtr conn; DEBUG("domain=%p, autostart=%p", domain, autostart); - if (!VIR_IS_DOMAIN(domain)) { - virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(domain->conn); return -1; } @@ -3240,17 +3871,30 @@ 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__); + virThreadResetLastError(); + + if (!VIR_IS_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(domain->conn); return -1; } @@ -3273,29 +3917,38 @@ 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); + virThreadResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(domain->conn); return -1; } @@ -3324,30 +3977,39 @@ 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); + virThreadResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(domain->conn); return -1; } @@ -3379,30 +4041,39 @@ 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); - } - if (!VIR_IS_CONNECTED_DOMAIN(domain)) { - virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(domain->conn); return -1; } @@ -3424,17 +4095,30 @@ 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__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(domain->conn); return -1; } @@ -3454,20 +4138,33 @@ 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__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(domain->conn); return -1; } @@ -3486,20 +4183,33 @@ 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__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(domain->conn); return -1; } @@ -3528,20 +4238,33 @@ virNodeGetCellsFreeMemory(virConnectPtr DEBUG("conn=%p, freeMems=%p, startCell=%d, maxCells=%d", conn, freeMems, startCell, maxCells); + virThreadResetLastError(); + if (!VIR_IS_CONNECT(conn)) { virLibConnError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); return (-1); } 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 */ + virThreadSetConnError(conn); return -1; } @@ -3564,8 +4287,12 @@ virNetworkGetConnect (virNetworkPtr net) { DEBUG("net=%p", net); + virThreadResetLastError(); + if (!VIR_IS_NETWORK (net)) { virLibNetworkError (NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); return NULL; } return net->conn; @@ -3584,15 +4311,28 @@ 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__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(conn); return -1; } @@ -3611,20 +4351,33 @@ virConnectListNetworks(virConnectPtr con { DEBUG("conn=%p, names=%p, maxnames=%d", conn, names, maxnames); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); return (-1); } 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 */ + virThreadSetConnError(conn); return -1; } @@ -3641,15 +4394,28 @@ 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__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(conn); return -1; } @@ -3669,21 +4435,34 @@ virConnectListDefinedNetworks(virConnect { DEBUG("conn=%p, names=%p, maxnames=%d", conn, names, maxnames); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); return (-1); } 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 */ + virThreadSetConnError(conn); return -1; } @@ -3702,19 +4481,32 @@ virNetworkLookupByName(virConnectPtr con { DEBUG("conn=%p, name=%s", conn, name); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(conn); return NULL; } @@ -3733,19 +4525,32 @@ virNetworkLookupByUUID(virConnectPtr con { DEBUG("conn=%p, uuid=%s", conn, uuid); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(conn); return NULL; } @@ -3767,13 +4572,17 @@ virNetworkLookupByUUIDString(virConnectP int ret; DEBUG("conn=%p, uuidstr=%s", conn, uuidstr); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); 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 +4601,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 */ + virThreadSetConnError(conn); + return NULL; } /** @@ -3815,23 +4629,36 @@ virNetworkCreateXML(virConnectPtr conn, { DEBUG("conn=%p, xmlDesc=%s", conn, xmlDesc); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(conn); return NULL; } @@ -3849,23 +4676,36 @@ virNetworkDefineXML(virConnectPtr conn, { DEBUG("conn=%p, xml=%s", conn, xml); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(conn); return NULL; } @@ -3882,20 +4722,33 @@ virNetworkUndefine(virNetworkPtr network virConnectPtr conn; DEBUG("network=%p", network); + virThreadResetLastError(); + if (!VIR_IS_CONNECTED_NETWORK(network)) { virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); return (-1); } 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 */ + virThreadSetConnError(network->conn); return -1; } @@ -3914,24 +4767,33 @@ virNetworkCreate(virNetworkPtr network) virConnectPtr conn; DEBUG("network=%p", network); - if (network == NULL) { - TODO - return (-1); - } + virThreadResetLastError(); + if (!VIR_IS_CONNECTED_NETWORK(network)) { virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); return (-1); } 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 */ + virThreadSetConnError(network->conn); return -1; } @@ -3952,21 +4814,34 @@ virNetworkDestroy(virNetworkPtr network) virConnectPtr conn; DEBUG("network=%p", network); + virThreadResetLastError(); + if (!VIR_IS_CONNECTED_NETWORK(network)) { virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); return (-1); } 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 */ + virThreadSetConnError(network->conn); return -1; } @@ -3984,12 +4859,19 @@ virNetworkFree(virNetworkPtr network) { DEBUG("network=%p", network); - if (!VIR_IS_NETWORK(network)) { - virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); - return (-1); - } - if (virUnrefNetwork(network) < 0) - return (-1); + virThreadResetLastError(); + + if (!VIR_IS_NETWORK(network)) { + virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); + return (-1); + } + if (virUnrefNetwork(network) < 0) { + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); + return (-1); + } return(0); } @@ -4007,8 +4889,12 @@ virNetworkGetName(virNetworkPtr network) { DEBUG("network=%p", network); - if (!VIR_IS_NETWORK(network)) { - virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_NETWORK(network)) { + virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); return (NULL); } return (network->name); @@ -4028,18 +4914,27 @@ virNetworkGetUUID(virNetworkPtr network, { DEBUG("network=%p, uuid=%p", network, uuid); - if (!VIR_IS_NETWORK(network)) { - virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_NETWORK(network)) { + virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); return (-1); } if (uuid == NULL) { virLibNetworkError(network, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); + goto error; } memcpy(uuid, &network->uuid[0], VIR_UUID_BUFLEN); return (0); + +error: + /* Copy to connection error object for back compatability */ + virThreadSetConnError(network->conn); + return -1; } /** @@ -4058,13 +4953,17 @@ virNetworkGetUUIDString(virNetworkPtr ne unsigned char uuid[VIR_UUID_BUFLEN]; DEBUG("network=%p, buf=%p", network, buf); - if (!VIR_IS_NETWORK(network)) { - virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_NETWORK(network)) { + virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); return (-1); } if (buf == NULL) { virLibNetworkError(network, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); + goto error; } if (virNetworkGetUUID(network, &uuid[0])) @@ -4072,6 +4971,11 @@ virNetworkGetUUIDString(virNetworkPtr ne virUUIDFormat(uuid, buf); return (0); + +error: + /* Copy to connection error object for back compatability */ + virThreadSetConnError(network->conn); + return -1; } /** @@ -4091,21 +4995,34 @@ virNetworkGetXMLDesc(virNetworkPtr netwo virConnectPtr conn; DEBUG("network=%p, flags=%d", network, flags); - if (!VIR_IS_NETWORK(network)) { - virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_NETWORK(network)) { + virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(network->conn); return NULL; } @@ -4125,17 +5042,30 @@ virNetworkGetBridgeName(virNetworkPtr ne virConnectPtr conn; DEBUG("network=%p", network); - if (!VIR_IS_NETWORK(network)) { - virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_NETWORK(network)) { + virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(network->conn); return NULL; } @@ -4157,21 +5087,34 @@ virNetworkGetAutostart(virNetworkPtr net virConnectPtr conn; DEBUG("network=%p, autostart=%p", network, autostart); - if (!VIR_IS_NETWORK(network)) { - virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_NETWORK(network)) { + virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(network->conn); return -1; } @@ -4192,17 +5135,30 @@ virNetworkSetAutostart(virNetworkPtr net virConnectPtr conn; DEBUG("network=%p, autostart=%d", network, autostart); - if (!VIR_IS_NETWORK(network)) { - virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_NETWORK(network)) { + virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(network->conn); return -1; } @@ -4226,8 +5182,12 @@ virStoragePoolGetConnect (virStoragePool { DEBUG("pool=%p", pool); + virThreadResetLastError(); + if (!VIR_IS_STORAGE_POOL (pool)) { virLibStoragePoolError (NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); return NULL; } return pool->conn; @@ -4246,15 +5206,28 @@ 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__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(conn); return -1; } @@ -4277,22 +5250,34 @@ virConnectListStoragePools (virConnectPt { DEBUG("conn=%p, names=%p, maxnames=%d", conn, names, maxnames); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); return (-1); } 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 */ + virThreadSetConnError(conn); + return -1; } @@ -4309,15 +5294,28 @@ 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__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(conn); return -1; } @@ -4341,20 +5339,33 @@ virConnectListDefinedStoragePools(virCon { DEBUG("conn=%p, names=%p, maxnames=%d", conn, names, maxnames); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); return (-1); } 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 */ + virThreadSetConnError(conn); return -1; } @@ -4386,19 +5397,34 @@ virConnectFindStoragePoolSources(virConn const char *srcSpec, unsigned int flags) { - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + DEBUG("conn=%p, type=%s, src=%s, flags=%u", conn, type ? type : "", srcSpec ? srcSpec : "", flags); + + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(conn); return NULL; } @@ -4418,19 +5444,32 @@ virStoragePoolLookupByName(virConnectPtr { DEBUG("conn=%p, name=%s", conn, name); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(conn); return NULL; } @@ -4450,21 +5489,33 @@ virStoragePoolLookupByUUID(virConnectPtr { DEBUG("conn=%p, uuid=%s", conn, uuid); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(conn); + return NULL; } @@ -4479,26 +5530,35 @@ 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); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(conn); + return NULL; } @@ -4515,17 +5575,29 @@ virStoragePoolLookupByVolume(virStorageV { DEBUG("vol=%p", vol); + virThreadResetLastError(); + 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); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(vol->conn); + return NULL; } /** @@ -4547,23 +5619,36 @@ virStoragePoolCreateXML(virConnectPtr co { DEBUG("conn=%p, xmlDesc=%s", conn, xmlDesc); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(conn); return NULL; } @@ -4585,25 +5670,37 @@ virStoragePoolDefineXML(virConnectPtr co { DEBUG("conn=%p, xml=%s", conn, xml); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(conn); + return NULL; } /** @@ -4622,22 +5719,34 @@ virStoragePoolBuild(virStoragePoolPtr po virConnectPtr conn; DEBUG("pool=%p, flags=%u", pool, flags); + virThreadResetLastError(); + if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) { virLibStoragePoolError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); return (-1); } 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 */ + virThreadSetConnError(pool->conn); + return -1; } @@ -4654,23 +5763,35 @@ virStoragePoolUndefine(virStoragePoolPtr { virConnectPtr conn; DEBUG("pool=%p", pool); + + virThreadResetLastError(); if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) { virLibStoragePoolError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); return (-1); } 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 */ + virThreadSetConnError(pool->conn); + return -1; } @@ -4690,26 +5811,34 @@ virStoragePoolCreate(virStoragePoolPtr p virConnectPtr conn; DEBUG("pool=%p", pool); - if (pool == NULL) { - TODO; - return (-1); - } + virThreadResetLastError(); + if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) { virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); return (-1); } 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 */ + virThreadSetConnError(pool->conn); + return -1; } @@ -4731,21 +5860,34 @@ virStoragePoolDestroy(virStoragePoolPtr virConnectPtr conn; DEBUG("pool=%p", pool); + virThreadResetLastError(); + if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) { virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); return (-1); } 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 */ + virThreadSetConnError(pool->conn); return -1; } @@ -4767,21 +5909,34 @@ virStoragePoolDelete(virStoragePoolPtr p virConnectPtr conn; DEBUG("pool=%p, flags=%u", pool, flags); + virThreadResetLastError(); + if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) { virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); return (-1); } 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 */ + virThreadSetConnError(pool->conn); return -1; } @@ -4800,12 +5955,19 @@ virStoragePoolFree(virStoragePoolPtr poo { DEBUG("pool=%p", pool); - if (!VIR_IS_STORAGE_POOL(pool)) { - virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); - return (-1); - } - if (virUnrefStoragePool(pool) < 0) - return (-1); + virThreadResetLastError(); + + if (!VIR_IS_STORAGE_POOL(pool)) { + virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); + return (-1); + } + if (virUnrefStoragePool(pool) < 0) { + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); + return (-1); + } return(0); } @@ -4829,21 +5991,34 @@ virStoragePoolRefresh(virStoragePoolPtr virConnectPtr conn; DEBUG("pool=%p flags=%u", pool, flags); + virThreadResetLastError(); + if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) { virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); return (-1); } 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 */ + virThreadSetConnError(pool->conn); return -1; } @@ -4861,12 +6036,15 @@ virStoragePoolGetName(virStoragePoolPtr { DEBUG("pool=%p", pool); - if (!VIR_IS_STORAGE_POOL(pool)) { - virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_STORAGE_POOL(pool)) { + virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); return (NULL); } return (pool->name); - } @@ -4885,19 +6063,27 @@ virStoragePoolGetUUID(virStoragePoolPtr { DEBUG("pool=%p, uuid=%p", pool, uuid); - if (!VIR_IS_STORAGE_POOL(pool)) { - virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_STORAGE_POOL(pool)) { + virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(pool->conn); + return -1; } /** @@ -4916,21 +6102,29 @@ virStoragePoolGetUUIDString(virStoragePo unsigned char uuid[VIR_UUID_BUFLEN]; DEBUG("pool=%p, buf=%p", pool, buf); - if (!VIR_IS_STORAGE_POOL(pool)) { - virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_STORAGE_POOL(pool)) { + virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(pool->conn); + return -1; } @@ -4951,25 +6145,37 @@ virStoragePoolGetInfo(virStoragePoolPtr virConnectPtr conn; DEBUG("pool=%p, info=%p", pool, info); + virThreadResetLastError(); + if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) { virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(pool->conn); + return -1; } @@ -4991,23 +6197,35 @@ virStoragePoolGetXMLDesc(virStoragePoolP virConnectPtr conn; DEBUG("pool=%p, flags=%u", pool, flags); - if (!VIR_IS_STORAGE_POOL(pool)) { - virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_STORAGE_POOL(pool)) { + virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(pool->conn); + return NULL; } @@ -5028,21 +6246,34 @@ virStoragePoolGetAutostart(virStoragePoo virConnectPtr conn; DEBUG("pool=%p, autostart=%p", pool, autostart); - if (!VIR_IS_STORAGE_POOL(pool)) { - virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_STORAGE_POOL(pool)) { + virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(pool->conn); return -1; } @@ -5063,17 +6294,30 @@ 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__); + virThreadResetLastError(); + + if (!VIR_IS_STORAGE_POOL(pool)) { + virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); + 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 */ + virThreadSetConnError(pool->conn); return -1; } @@ -5091,15 +6335,28 @@ virStoragePoolNumOfVolumes(virStoragePoo { DEBUG("pool=%p", pool); + virThreadResetLastError(); + 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); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); + return (-1); + } + + 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 */ + virThreadSetConnError(pool->conn); return -1; } @@ -5122,20 +6379,33 @@ virStoragePoolListVolumes(virStoragePool { DEBUG("pool=%p, names=%p, maxnames=%d", pool, names, maxnames); + virThreadResetLastError(); + if (!VIR_IS_STORAGE_POOL(pool)) { virLibConnError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); return (-1); } 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 */ + virThreadSetConnError(pool->conn); return -1; } @@ -5159,8 +6429,12 @@ virStorageVolGetConnect (virStorageVolPt { DEBUG("vol=%p", vol); + virThreadResetLastError(); + if (!VIR_IS_STORAGE_VOL (vol)) { virLibStoragePoolError (NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); return NULL; } return vol->conn; @@ -5183,19 +6457,32 @@ virStorageVolLookupByName(virStoragePool { DEBUG("pool=%p, name=%s", pool, name); - if (!VIR_IS_STORAGE_POOL(pool)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_STORAGE_POOL(pool)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(pool->conn); return NULL; } @@ -5217,19 +6504,32 @@ virStorageVolLookupByKey(virConnectPtr c { DEBUG("conn=%p, key=%s", conn, key); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(conn); return NULL; } @@ -5249,19 +6549,32 @@ virStorageVolLookupByPath(virConnectPtr { DEBUG("conn=%p, path=%s", conn, path); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(conn); return NULL; } @@ -5280,8 +6593,12 @@ virStorageVolGetName(virStorageVolPtr vo { DEBUG("vol=%p", vol); + virThreadResetLastError(); + if (!VIR_IS_STORAGE_VOL(vol)) { virLibStorageVolError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); return (NULL); } return (vol->name); @@ -5303,8 +6620,12 @@ virStorageVolGetKey(virStorageVolPtr vol { DEBUG("vol=%p", vol); + virThreadResetLastError(); + if (!VIR_IS_STORAGE_VOL(vol)) { virLibStorageVolError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); return (NULL); } return (vol->key); @@ -5330,20 +6651,33 @@ virStorageVolCreateXML(virStoragePoolPtr { DEBUG("pool=%p, flags=%u", pool, flags); + virThreadResetLastError(); + if (!VIR_IS_STORAGE_POOL(pool)) { virLibConnError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); return (NULL); } 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 */ + virThreadSetConnError(pool->conn); return NULL; } @@ -5364,21 +6698,34 @@ virStorageVolDelete(virStorageVolPtr vol virConnectPtr conn; DEBUG("vol=%p, flags=%u", vol, flags); + virThreadResetLastError(); + if (!VIR_IS_CONNECTED_STORAGE_VOL(vol)) { virLibStorageVolError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); return (-1); } 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 */ + virThreadSetConnError(vol->conn); return -1; } @@ -5397,12 +6744,19 @@ virStorageVolFree(virStorageVolPtr vol) { DEBUG("vol=%p", vol); + virThreadResetLastError(); + if (!VIR_IS_STORAGE_VOL(vol)) { virLibStorageVolError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__); - return (-1); - } - if (virUnrefStorageVol(vol) < 0) - return (-1); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); + return (-1); + } + if (virUnrefStorageVol(vol) < 0) { + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); + return (-1); + } return(0); } @@ -5424,23 +6778,36 @@ virStorageVolGetInfo(virStorageVolPtr vo virConnectPtr conn; DEBUG("vol=%p, info=%p", vol, info); + virThreadResetLastError(); + if (!VIR_IS_CONNECTED_STORAGE_VOL(vol)) { virLibStorageVolError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(vol->conn); return -1; } @@ -5462,23 +6829,35 @@ virStorageVolGetXMLDesc(virStorageVolPtr virConnectPtr conn; DEBUG("vol=%p, flags=%u", vol, flags); + virThreadResetLastError(); + if (!VIR_IS_STORAGE_VOL(vol)) { virLibStorageVolError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(vol->conn); + return NULL; } @@ -5500,17 +6879,30 @@ virStorageVolGetPath(virStorageVolPtr vo virConnectPtr conn; DEBUG("vol=%p", vol); + virThreadResetLastError(); + if (!VIR_IS_STORAGE_VOL(vol)) { virLibStorageVolError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__); + /* Copy to global error object for back compatability */ + virThreadSetGlobalError(); return (NULL); } 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 */ + virThreadSetConnError(vol->conn); return NULL; } @@ -5535,19 +6927,32 @@ virNodeNumOfDevices(virConnectPtr conn, { DEBUG("conn=%p, cap=%s, flags=%d", conn, cap, flags); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(conn); return -1; } @@ -5576,19 +6981,32 @@ virNodeListDevices(virConnectPtr conn, DEBUG("conn=%p, cap=%s, names=%p, maxnames=%d, flags=%d", conn, cap, names, maxnames, flags); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); 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 */ + virThreadSetConnError(conn); return -1; } @@ -5606,20 +7024,33 @@ virNodeDevicePtr virNodeDeviceLookupByNa { DEBUG("conn=%p, name=%p", conn, name); - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); return NULL; } 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 */ + virThreadSetConnError(conn); return NULL; } @@ -5638,15 +7069,28 @@ char *virNodeDeviceGetXMLDesc(virNodeDev { DEBUG("dev=%p, conn=%p", dev, dev ? dev->conn : NULL); + virThreadResetLastError(); + 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); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + return NULL; + } + + 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 */ + virThreadSetConnError(dev->conn); return NULL; } @@ -5684,8 +7128,12 @@ const char *virNodeDeviceGetParent(virNo { DEBUG("dev=%p, conn=%p", dev, dev ? dev->conn : NULL); + virThreadResetLastError(); + if (!VIR_IS_CONNECTED_NODE_DEVICE(dev)) { virLibNodeDeviceError(NULL, VIR_ERR_INVALID_NODE_DEVICE, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); return NULL; } @@ -5712,15 +7160,28 @@ int virNodeDeviceNumOfCaps(virNodeDevice { DEBUG("dev=%p, conn=%p", dev, dev ? dev->conn : NULL); + virThreadResetLastError(); + 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); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + return -1; + } + + 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 */ + virThreadSetConnError(dev->conn); return -1; } @@ -5741,15 +7202,28 @@ int virNodeDeviceListCaps(virNodeDeviceP DEBUG("dev=%p, conn=%p, names=%p, maxnames=%d", dev, dev ? dev->conn : NULL, names, maxnames); + virThreadResetLastError(); + 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); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + return -1; + } + + 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 */ + virThreadSetConnError(dev->conn); return -1; } @@ -5767,12 +7241,19 @@ int virNodeDeviceFree(virNodeDevicePtr d { DEBUG("dev=%p, conn=%p", dev, dev ? dev->conn : NULL); + virThreadResetLastError(); + if (!VIR_IS_CONNECTED_NODE_DEVICE(dev)) { virLibNodeDeviceError(NULL, VIR_ERR_INVALID_NODE_DEVICE, __FUNCTION__); - return (-1); - } - if (virUnrefNodeDevice(dev) < 0) - return (-1); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + return (-1); + } + if (virUnrefNodeDevice(dev) < 0) { + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); + return (-1); + } return(0); } @@ -5799,18 +7280,32 @@ virConnectDomainEventRegister(virConnect void *opaque, virFreeCallback freecb) { - - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + DEBUG("conn=%p, cb=%p, opaque=%p, freecb=%p", conn, cb, opaque, freecb); + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); return (-1); } 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 */ + virThreadSetConnError(conn); return -1; } @@ -5829,19 +7324,33 @@ virConnectDomainEventDeregister(virConne virConnectDomainEventDeregister(virConnectPtr conn, virConnectDomainEventCallback cb) { - - if (!VIR_IS_CONNECT(conn)) { - virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + DEBUG("conn=%p, cb=%p", conn, cb); + + virThreadResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + /* Copy to connection error object for back compatability */ + virThreadSetGlobalError(); return (-1); } 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 */ + virThreadSetConnError(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,13 @@ LIBVIRT_0.5.0 { } LIBVIRT_0.4.5; -/* no new entry point in 0.5.1 */ +LIBVIRT_0.5.2 { + global: + virThreadGetLastError; + virThreadCopyLastError; + virThreadResetLastError; +} LIBVIRT_0.5.0; + /* .... 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,14 @@ #include "virterror_internal.h" #include "datatypes.h" +#include "memory.h" -virError virLastErr = /* the last error */ +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 }; +static PTHREAD_MUTEX_T(virLastErrLock); + virErrorFunc virErrorHandler = NULL; /* global error handler */ void *virUserData = NULL; /* associated data */ @@ -62,12 +65,49 @@ void *virUserData = NULL; /* asso }} \ } -/* +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; +} + + + +/** * 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() + * + * This function is not safe for use in a multi-threaded + * application. Use virThreadGetLastError() instead. + * + * This function is also not very suitable for single-threaded + * applications because for any API call, it is impossible + * to determine whether an error was set globally or on the + * connection. Always use virThreadGetLastError() * * Returns a pointer to the last error or NULL if none occurred. */ @@ -79,11 +119,20 @@ virGetLastError(void) return (&virLastErr); } -/* +/** * virCopyLastError: * @to: target to receive the copy * * Copy the content of the last error caught at the library level + * + * This function is not safe for use in a multi-threaded + * application. Use virThreadCopyLastError() instead. + * + * This function is also not very suitable for single-threaded + * applications because for any API call, it is impossible + * to determine whether an error was set globally or on the + * connection. Always use virThreadCopyLastError() + * * 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 +141,8 @@ 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); + virCopyError(&virLastErr, to); + return to->code; } /** @@ -118,10 +163,19 @@ virResetError(virErrorPtr err) memset(err, 0, sizeof(virError)); } + /** * virResetLastError: * * Reset the last error caught at the library level. + * + * This function is not safe for use in a multi-threaded + * application. Use virThreadResetLastError() instead. + * + * This function is also not very suitable for single-threaded + * applications because for any API call, it is impossible + * to determine whether an error was set globally or on the + * connection. Always use virThreadResetLastError() */ void virResetLastError(void) @@ -134,8 +188,14 @@ 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 function is not safe for use in a multi-threaded + * application. Use virThreadGetLastError() instead. + * + * This function is also not very suitable for single-threaded + * applications because for any API call, it is impossible + * to determine whether an error was set globally or on the + * connection. Always use virThreadGetLastError() * * Returns a pointer to the last error or NULL if none occurred. */ @@ -153,6 +213,15 @@ virConnGetLastError(virConnectPtr conn) * @to: target to receive the copy * * Copy the content of the last error caught on that connection + * + * This function is not safe for use in a multi-threaded + * application. Use virThreadCopyLastError() instead. + * + * This function is also not very suitable for single-threaded + * applications because for any API call, it is impossible + * to determine whether an error was set globally or on the + * connection. Always use virThreadCopyLastError() + * * 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 @@ -163,17 +232,21 @@ virConnCopyLastError(virConnectPtr conn, { if (conn == NULL) return (-1); - if (to == NULL) - return (-1); - if (conn->err.code == VIR_ERR_OK) - return (0); - memcpy(to, &conn->err, sizeof(virError)); - return (conn->err.code); + virCopyError(&conn->err, to); + return to->code; } /** * virConnResetLastError: * @conn: pointer to the hypervisor connection + * + * This function is not safe for use in a multi-threaded + * application. Use virThreadResetLastError() instead. + * + * This function is also not very suitable for single-threaded + * applications because for any API call, it is impossible + * to determine whether an error was set globally or on the + * connection. Always use virThreadResetLastError() * * Reset the last error caught on that connection */ @@ -217,8 +290,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 +413,146 @@ virDefaultErrorFunc(virErrorPtr err) dom, lvl, domain, network, err->message); } + +pthread_once_t virErrorKeyInit = PTHREAD_ONCE_INIT; +pthread_key_t virErrorKey; + +static void +virErrorKeyFreeData(void *data) +{ + virErrorPtr err = data; + virResetError(err); + VIR_FREE(err); +} + +static void +virErrorKeyCreate(void) +{ + pthread_key_create(&virErrorKey, virErrorKeyFreeData); +} + + +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")); +} + +/** + * virThreadGetLastError: + * + * Provide a pointer to the last error caught during an API + * call in this thread. + * + * The contents of the returned error object are only valid + * until the next API call is made, or until the thread exits + * + * Returns a pointer to the last error or NULL if none occurred. + */ +virErrorPtr +virThreadGetLastError(void) +{ + virErrorPtr err; + pthread_once(&virErrorKeyInit, virErrorKeyCreate); + err = pthread_getspecific(virErrorKey); + if (!err) { + if (VIR_ALLOC(err) < 0) + return NULL; + pthread_setspecific(virErrorKey, err); + } + return err; +} + + +/** + * virThreadCopyLastError: + * @to: target to receive the copy + * + * Copy the content of the last error caught during an API + * call in this thread. + * + * 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 + * of parameter error. + */ +int +virThreadCopyLastError (virErrorPtr to) +{ + virErrorPtr err; + + err = virThreadGetLastError(); + if (virCopyError(err, to) < 0) + return -1; + + return to->code; +} + + +/** + * virThreadResetLastError: + * + * Reset the last error caught during an API call + * in this thread + */ +void +virThreadResetLastError (void) +{ + virErrorPtr err; + + err = virThreadGetLastError(); + if (err) + virResetError(err); +} + + +/** + * virThreadSetConnError: + * + * Initialize the global error with the contents of the + * the thread local error + */ +void +virThreadSetGlobalError(void) +{ + virErrorPtr err; + + err = virThreadGetLastError(); + + if (err && err->code == VIR_ERR_OK) + virErrorGenericFailure(err); + + pthread_mutex_lock(&virLastErrLock); + virCopyError(err, &virLastErr); + pthread_mutex_unlock(&virLastErrLock); +} + +/** + * virThreadSetConnError: + * + * Initialize the connection error with the contents of the + * the thread local error + */ +void +virThreadSetConnError(virConnectPtr conn) +{ + virErrorPtr err; + + err = virThreadGetLastError(); + + if (err && err->code == VIR_ERR_OK) + virErrorGenericFailure(err); + + pthread_mutex_lock(&conn->lock); + virCopyError(err, &conn->err); + pthread_mutex_unlock(&conn->lock); +} + + + /** * virRaiseError: * @conn: the connection to the hypervisor if available @@ -358,15 +573,29 @@ virDefaultErrorFunc(virErrorPtr err) * immediately if a callback is found and store it for later handling. */ void -virRaiseError(virConnectPtr conn, virDomainPtr dom, virNetworkPtr net, +virRaiseError(virConnectPtr conn, + virDomainPtr dom ATTRIBUTE_UNUSED, + virNetworkPtr net ATTRIBUTE_UNUSED, int domain, int code, virErrorLevel level, const char *str1, const char *str2, const char *str3, int int1, int int2, const char *msg, ...) { - virErrorPtr to = &virLastErr; + virErrorPtr to; void *userData = virUserData; virErrorFunc handler = virErrorHandler; char *str; + + /* + * All errors are recorded in thread local storage + * For compatability, public API calls will copy them + * to the global or per-connection error object when + * neccessary + */ + to = virThreadGetLastError(); + 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 +604,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 +625,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; 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 virThreadSetGlobalError(void); +void virThreadSetConnError(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 :| -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list