Update the code to be more in line with how code looks elsewhere in libvirt. Allow listing of domains, networks, storage pools, and network interfaces. Update the function prototypes in libvirt.c to include a message about the client needing to free() returned name fields. Fix the all domains example flags values. --- examples/hellolibvirt/hellolibvirt.c | 131 ++++++++++++++++++++++------------- src/libvirt.c | 21 +++--- 2 files changed, 91 insertions(+), 61 deletions(-) diff --git a/examples/hellolibvirt/hellolibvirt.c b/examples/hellolibvirt/hellolibvirt.c index 234637e..85e5ae6 100644 --- a/examples/hellolibvirt/hellolibvirt.c +++ b/examples/hellolibvirt/hellolibvirt.c @@ -15,7 +15,7 @@ showError(virConnectPtr conn) virErrorPtr err; err = malloc(sizeof(*err)); - if (NULL == err) { + if (!err) { printf("Could not allocate memory for error data\n"); goto out; } @@ -56,14 +56,14 @@ showHypervisorInfo(virConnectPtr conn) * to fail if, for example, there is no connection to a * hypervisor, so check what it returns. */ hvType = virConnectGetType(conn); - if (NULL == hvType) { + if (!hvType) { ret = 1; printf("Failed to get hypervisor type\n"); showError(conn); goto out; } - if (0 != virConnectGetVersion(conn, &hvVer)) { + if (virConnectGetVersion(conn, &hvVer) < 0) { ret = 1; printf("Failed to get hypervisor version\n"); showError(conn); @@ -85,73 +85,101 @@ out: return ret; } +/* Turn off the message in order to compile here + * + * The virConnectListAll*(), vir*IsActive(), vir*GetName(), and vir*Free() + * functions require specific types which aren't possible to provide in + * this tabular manner. + */ +#pragma GCC diagnostic ignored "-Wstrict-prototypes" +typedef struct _objectTable objectTable; +struct _objectTable { + const char *objName; + int (*activeFcn)(virConnectPtr); + int (*inactiveFcn)(virConnectPtr); + int (*allFcn)(); + int (*isActiveFcn)(); + const char *(*nameFcn)(); + int (*freeFcn)(); + unsigned int flags; +}; + +objectTable fcnTable[] = { + {"domains", + virConnectNumOfDomains, virConnectNumOfDefinedDomains, + virConnectListAllDomains, virDomainIsActive, + virDomainGetName, virDomainFree, + VIR_CONNECT_LIST_DOMAINS_ACTIVE | + VIR_CONNECT_LIST_DOMAINS_INACTIVE}, + {"networks", + virConnectNumOfNetworks, virConnectNumOfDefinedNetworks, + virConnectListAllNetworks, virNetworkIsActive, + virNetworkGetName, virNetworkFree, + VIR_CONNECT_LIST_NETWORKS_ACTIVE | + VIR_CONNECT_LIST_NETWORKS_INACTIVE}, + {"storage pools", + virConnectNumOfStoragePools, virConnectNumOfDefinedStoragePools, + virConnectListAllStoragePools, virStoragePoolIsActive, + virStoragePoolGetName, virStoragePoolFree, + VIR_CONNECT_LIST_STORAGE_POOLS_ACTIVE | + VIR_CONNECT_LIST_STORAGE_POOLS_INACTIVE}, + {"interfaces", + virConnectNumOfInterfaces, virConnectNumOfDefinedInterfaces, + virConnectListAllInterfaces, virInterfaceIsActive, + virInterfaceGetName, virInterfaceFree, + VIR_CONNECT_LIST_INTERFACES_ACTIVE | + VIR_CONNECT_LIST_INTERFACES_INACTIVE}, + {NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0} +}; static int -showDomains(virConnectPtr conn) +showObject(virConnectPtr conn, objectTable entry) { - int ret = 0, i, numNames, numInactiveDomains, numActiveDomains; - char **nameList = NULL; + int ret = 0, numActive, numInactive, numObjects, i; + void **objects = NULL; - numActiveDomains = virConnectNumOfDomains(conn); - if (-1 == numActiveDomains) { + if ((numActive = (*entry.activeFcn)(conn)) < 0) { ret = 1; - printf("Failed to get number of active domains\n"); + printf("Failed to get number of active %s\n", entry.objName); showError(conn); goto out; } - numInactiveDomains = virConnectNumOfDefinedDomains(conn); - if (-1 == numInactiveDomains) { + if ((numInactive = (*entry.inactiveFcn)(conn)) < 0) { ret = 1; - printf("Failed to get number of inactive domains\n"); + printf("Failed to get number of inactive %s\n", entry.objName); showError(conn); goto out; } - printf("There are %d active and %d inactive domains\n", - numActiveDomains, numInactiveDomains); + printf("There are %d active and %d inactive %s:\n", + numActive, numInactive, entry.objName); - nameList = malloc(sizeof(*nameList) * numInactiveDomains); - - if (NULL == nameList) { + if ((numObjects = (*entry.allFcn)(conn, &objects, entry.flags)) < 0) { ret = 1; - printf("Could not allocate memory for list of inactive domains\n"); - goto out; - } - - numNames = virConnectListDefinedDomains(conn, - nameList, - numInactiveDomains); - - if (-1 == numNames) { - ret = 1; - printf("Could not get list of defined domains from hypervisor\n"); + printf("Failed to get all %s\n", entry.objName); showError(conn); goto out; } - - if (numNames > 0) { - printf("Inactive domains:\n"); - } - - for (i = 0 ; i < numNames ; i++) { - printf(" %s\n", *(nameList + i)); - /* The API documentation doesn't say so, but the names - * returned by virConnectListDefinedDomains are strdup'd and - * must be freed here. */ - free(*(nameList + i)); + for (i = 0; i < numObjects; i++) { + int active = (*entry.isActiveFcn)(objects[i]); + /* Sure the name could be longer, but for a quick example this works */ + printf("\t%8s (%s)\n", + (*entry.nameFcn)(objects[i]), + (active == 1 ? "active" : "non-active")); + + /* We have to free the entry */ + (*entry.freeFcn)(objects[i]); } - + free(objects); out: - free(nameList); return ret; } - int main(int argc, char *argv[]) { - int ret = 0; + int ret = 0, i; virConnectPtr conn; char *uri; @@ -163,7 +191,7 @@ main(int argc, char *argv[]) * except, possibly, the URI of the hypervisor. */ conn = virConnectOpenAuth(uri, virConnectAuthPtrDefault, 0); - if (NULL == conn) { + if (!conn) { ret = 1; printf("No connection to hypervisor\n"); showError(conn); @@ -171,7 +199,7 @@ main(int argc, char *argv[]) } uri = virConnectGetURI(conn); - if (NULL == uri) { + if (!uri) { ret = 1; printf("Failed to get URI for hypervisor connection\n"); showError(conn); @@ -181,18 +209,21 @@ main(int argc, char *argv[]) printf("Connected to hypervisor at \"%s\"\n", uri); free(uri); - if (0 != showHypervisorInfo(conn)) { + if (showHypervisorInfo(conn) < 0) { ret = 1; goto disconnect; } - if (0 != showDomains(conn)) { - ret = 1; - goto disconnect; + i = 0; + while (fcnTable[i].objName) { + ret = showObject(conn, fcnTable[i]); + if (ret != 0) + goto disconnect; + i++; } disconnect: - if (0 != virConnectClose(conn)) { + if (virConnectClose(conn) < 0) { printf("Failed to disconnect from hypervisor\n"); showError(conn); ret = 1; diff --git a/src/libvirt.c b/src/libvirt.c index 1e78500..e717f16 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -8304,19 +8304,18 @@ error: * VIR_CONNECT_LIST_DOMAINS_NO_SNAPSHOT, for filtering based on whether * a domain has snapshots. * - * Returns the number of domains found or -1 and sets domains to NULL in case - * of error. On success, the array stored into @doms is guaranteed to have an + * Returns the number of domains found or -1 and sets domains to NULL in case of + * error. On success, the array stored into @domains is guaranteed to have an * extra allocated element set to NULL but not included in the return count, to * make iteration easier. The caller is responsible for calling virDomainFree() - * on each array element, then calling free() on @doms. + * on each array element, then calling free() on @domains. * * Example of usage: * virDomainPtr *domains; - * virDomainPtr dom; * int i; * int ret; - * unsigned int flags = VIR_CONNECT_LIST_RUNNING | - * VIR_CONNECT_LIST_PERSISTENT; + * unsigned int flags = VIR_CONNECT_LIST_DOMAINS_RUNNING | + * VIR_CONNECT_LIST_DOMAINS_PERSISTENT; * * ret = virConnectListAllDomains(conn, &domains, flags); * if (ret < 0) @@ -10226,7 +10225,7 @@ error: * this command is inherently racy; a network can be started between a call * to virConnectNumOfNetworks() and this call; you are only guaranteed that * all currently active networks were listed if the return is less than - * @maxnames. + * @maxnames. The client must call free() on each returned name. */ int virConnectListNetworks(virConnectPtr conn, char **const names, int maxnames) @@ -11208,7 +11207,7 @@ error: * this command is inherently racy; a interface can be started between a call * to virConnectNumOfInterfaces() and this call; you are only guaranteed that * all currently active interfaces were listed if the return is less than - * @maxnames. + * @maxnames. The client must call free() on each returned name. */ int virConnectListInterfaces(virConnectPtr conn, char **const names, int maxnames) @@ -12076,7 +12075,7 @@ error: * this command is inherently racy; a pool can be started between a call to * virConnectNumOfStoragePools() and this call; you are only guaranteed * that all currently active pools were listed if the return is less than - * @maxnames. + * @maxnames. The client must call free() on each returned name. */ int virConnectListStoragePools(virConnectPtr conn, @@ -18285,7 +18284,7 @@ error: * the results, see virDomainListAllSnapshots(). * * Returns the number of domain snapshots found or -1 in case of error. - * The caller is responsible for freeing each member of the array. + * The caller is responsible to call free() for each member of the array. */ int virDomainSnapshotListNames(virDomainPtr domain, char **names, int nameslen, @@ -18534,7 +18533,7 @@ error: * the results, see virDomainSnapshotListAllChildren(). * * Returns the number of domain snapshots found or -1 in case of error. - * The caller is responsible for freeing each member of the array. + * The caller is responsible to call free() for each member of the array. */ int virDomainSnapshotListChildrenNames(virDomainSnapshotPtr snapshot, -- 1.7.11.7 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list