+Mon Apr 28 17:24:22 EST 2008 Daniel P. Berrange <berrange@redhat.com>
+
+ * src/memory.h, src/memory.c: Added safer APIs for dealing
+ with low level memory allocation.
+ * src/hash.c, src/capabilities.c: Convert to new memory
+ allocation APIs
+ * src/internal.h: Define ATTRIBUTE_RETURN_CHECK and fix
+ type in virDebug no-op impl
+ * proxy/Makefile.am: Build and link against memory.c
+
Mon Apr 28 10:24:22 EST 2008 Daniel P. Berrange <berrange@redhat.com>
* src/buf.c, src/buf.h: Change API to move errors checks to
@top_srcdir@/src/sexpr.c @top_srcdir@/src/xml.c \
@top_srcdir@/src/xs_internal.c @top_srcdir@/src/buf.c \
@top_srcdir@/src/capabilities.c \
+ @top_srcdir@/src/memory.c \
@top_srcdir@/src/util.c \
@top_srcdir@/src/uuid.c
libvirt_proxy_LDFLAGS = $(WARN_CFLAGS)
libvirt.c internal.h \
gnutls_1_0_compat.h \
socketcompat.h \
+ memory.c memory.h \
hash.c hash.h \
test.c test.h \
buf.c buf.h \
#include "capabilities.h"
#include "buf.h"
+#include "memory.h"
/**
{
virCapsPtr caps;
- if ((caps = calloc(1, sizeof(*caps))) == NULL)
+ if (VIR_ALLOC(caps) < 0)
goto no_memory;
if ((caps->host.arch = strdup(arch)) == NULL)
static void
virCapabilitiesFreeHostNUMACell(virCapsHostNUMACellPtr cell)
{
- free(cell->cpus);
- free(cell);
+ VIR_FREE(cell->cpus);
+ VIR_FREE(cell);
}
static void
virCapabilitiesFreeGuestDomain(virCapsGuestDomainPtr dom)
{
int i;
- free(dom->info.emulator);
- free(dom->info.loader);
+ VIR_FREE(dom->info.emulator);
+ VIR_FREE(dom->info.loader);
for (i = 0 ; i < dom->info.nmachines ; i++)
- free(dom->info.machines[i]);
- free(dom->info.machines);
- free(dom->type);
+ VIR_FREE(dom->info.machines[i]);
+ VIR_FREE(dom->info.machines);
+ VIR_FREE(dom->type);
- free(dom);
+ VIR_FREE(dom);
}
static void
virCapabilitiesFreeGuestFeature(virCapsGuestFeaturePtr feature)
{
- free(feature->name);
- free(feature);
+ VIR_FREE(feature->name);
+ VIR_FREE(feature);
}
static void
virCapabilitiesFreeGuest(virCapsGuestPtr guest)
{
int i;
- free(guest->ostype);
+ VIR_FREE(guest->ostype);
- free(guest->arch.name);
- free(guest->arch.defaultInfo.emulator);
- free(guest->arch.defaultInfo.loader);
+ VIR_FREE(guest->arch.name);
+ VIR_FREE(guest->arch.defaultInfo.emulator);
+ VIR_FREE(guest->arch.defaultInfo.loader);
for (i = 0 ; i < guest->arch.defaultInfo.nmachines ; i++)
- free(guest->arch.defaultInfo.machines[i]);
- free(guest->arch.defaultInfo.machines);
+ VIR_FREE(guest->arch.defaultInfo.machines[i]);
+ VIR_FREE(guest->arch.defaultInfo.machines);
for (i = 0 ; i < guest->arch.ndomains ; i++)
virCapabilitiesFreeGuestDomain(guest->arch.domains[i]);
- free(guest->arch.domains);
+ VIR_FREE(guest->arch.domains);
for (i = 0 ; i < guest->nfeatures ; i++)
virCapabilitiesFreeGuestFeature(guest->features[i]);
- free(guest->features);
+ VIR_FREE(guest->features);
- free(guest);
+ VIR_FREE(guest);
}
for (i = 0 ; i < caps->nguests ; i++)
virCapabilitiesFreeGuest(caps->guests[i]);
- free(caps->guests);
+ VIR_FREE(caps->guests);
for (i = 0 ; i < caps->host.nfeatures ; i++)
- free(caps->host.features[i]);
- free(caps->host.features);
+ VIR_FREE(caps->host.features[i]);
+ VIR_FREE(caps->host.features);
for (i = 0 ; i < caps->host.nnumaCell ; i++)
virCapabilitiesFreeHostNUMACell(caps->host.numaCell[i]);
- free(caps->host.numaCell);
+ VIR_FREE(caps->host.numaCell);
for (i = 0 ; i < caps->host.nmigrateTrans ; i++)
- free(caps->host.migrateTrans[i]);
- free(caps->host.migrateTrans);
+ VIR_FREE(caps->host.migrateTrans[i]);
+ VIR_FREE(caps->host.migrateTrans);
- free(caps->host.arch);
- free(caps);
+ VIR_FREE(caps->host.arch);
+ VIR_FREE(caps);
}
virCapabilitiesAddHostFeature(virCapsPtr caps,
const char *name)
{
- char **features;
-
- if ((features = realloc(caps->host.features,
- sizeof(*features) * (caps->host.nfeatures+1))) == NULL)
+ if (VIR_REALLOC_N(caps->host.features,
+ caps->host.nfeatures + 1) < 0)
return -1;
- caps->host.features = features;
if ((caps->host.features[caps->host.nfeatures] = strdup(name)) == NULL)
return -1;
virCapabilitiesAddHostMigrateTransport(virCapsPtr caps,
const char *name)
{
- char **migrateTrans;
-
- if ((migrateTrans = realloc(caps->host.migrateTrans,
- sizeof(*migrateTrans) * (caps->host.nmigrateTrans+1))) == NULL)
+ if (VIR_REALLOC_N(caps->host.migrateTrans,
+ caps->host.nmigrateTrans + 1) < 0)
return -1;
- caps->host.migrateTrans = migrateTrans;
if ((caps->host.migrateTrans[caps->host.nmigrateTrans] = strdup(name)) == NULL)
return -1;
int ncpus,
const int *cpus)
{
- virCapsHostNUMACellPtr cell, *cells;
+ virCapsHostNUMACellPtr cell;
- if ((cells = realloc(caps->host.numaCell,
- sizeof(*cells) * (caps->host.nnumaCell+1))) == NULL)
+ if (VIR_REALLOC_N(caps->host.numaCell,
+ caps->host.nnumaCell + 1) < 0)
return -1;
- caps->host.numaCell = cells;
- if ((cell = calloc(1, sizeof(cell))) == NULL)
+ if (VIR_ALLOC(cell) < 0)
return -1;
caps->host.numaCell[caps->host.nnumaCell] = cell;
- if ((caps->host.numaCell[caps->host.nnumaCell]->cpus =
- malloc(ncpus * sizeof(*cpus))) == NULL)
+ if (VIR_ALLOC_N(caps->host.numaCell[caps->host.nnumaCell]->cpus,
+ ncpus) < 0)
return -1;
memcpy(caps->host.numaCell[caps->host.nnumaCell]->cpus,
cpus,
int nmachines,
const char *const *machines)
{
- virCapsGuestPtr guest, *guests;
+ virCapsGuestPtr guest;
int i;
- if ((guest = calloc(1, sizeof(*guest))) == NULL)
+ if (VIR_ALLOC(guest) < 0)
goto no_memory;
if ((guest->ostype = strdup(ostype)) == NULL)
(guest->arch.defaultInfo.loader = strdup(loader)) == NULL)
goto no_memory;
if (nmachines) {
- if ((guest->arch.defaultInfo.machines =
- calloc(nmachines, sizeof(*guest->arch.defaultInfo.machines))) == NULL)
+ if (VIR_ALLOC_N(guest->arch.defaultInfo.machines,
+ nmachines) < 0)
goto no_memory;
for (i = 0 ; i < nmachines ; i++) {
if ((guest->arch.defaultInfo.machines[i] = strdup(machines[i])) == NULL)
}
}
- if ((guests = realloc(caps->guests,
- sizeof(*guests) *
- (caps->nguests + 1))) == NULL)
+ if (VIR_REALLOC_N(caps->guests,
+ caps->nguests + 1) < 0)
goto no_memory;
- caps->guests = guests;
caps->guests[caps->nguests] = guest;
caps->nguests++;
int nmachines,
const char *const *machines)
{
- virCapsGuestDomainPtr dom, *doms;
+ virCapsGuestDomainPtr dom;
int i;
- if ((dom = calloc(1, sizeof(*dom))) == NULL)
+ if (VIR_ALLOC(dom) < 0)
goto no_memory;
if ((dom->type = strdup(hvtype)) == NULL)
(dom->info.loader = strdup(loader)) == NULL)
goto no_memory;
if (nmachines) {
- if ((dom->info.machines =
- calloc(nmachines, sizeof(*dom->info.machines))) == NULL)
+ if (VIR_ALLOC_N(dom->info.machines, nmachines) < 0)
goto no_memory;
for (i = 0 ; i < nmachines ; i++) {
if ((dom->info.machines[i] = strdup(machines[i])) == NULL)
}
}
- if ((doms = realloc(guest->arch.domains,
- sizeof(*doms) *
- (guest->arch.ndomains + 1))) == NULL)
+ if (VIR_REALLOC_N(guest->arch.domains,
+ guest->arch.ndomains + 1) < 0)
goto no_memory;
- guest->arch.domains = doms;
guest->arch.domains[guest->arch.ndomains] = dom;
guest->arch.ndomains++;
int defaultOn,
int toggle)
{
- virCapsGuestFeaturePtr feature, *features;
+ virCapsGuestFeaturePtr feature;
- if ((feature = calloc(1, sizeof(*feature))) == NULL)
+ if (VIR_ALLOC(feature) < 0)
goto no_memory;
if ((feature->name = strdup(name)) == NULL)
feature->defaultOn = defaultOn;
feature->toggle = toggle;
- if ((features = realloc(guest->features,
- sizeof(*features) *
- (guest->nfeatures + 1))) == NULL)
+ if (VIR_REALLOC_N(guest->features,
+ guest->nfeatures + 1) < 0)
goto no_memory;
- guest->features = features;
guest->features[guest->nfeatures] = feature;
guest->nfeatures++;
#include <libxml/threads.h>
#include "internal.h"
#include "hash.h"
+#include "memory.h"
#define MAX_HASH_LEN 8
virHashTablePtr
virHashCreate(int size)
{
- virHashTablePtr table;
+ virHashTablePtr table = NULL;
if (size <= 0)
size = 256;
- table = malloc(sizeof(*table));
- if (table) {
- table->size = size;
- table->nbElems = 0;
- table->table = calloc(1, size * sizeof(*(table->table)));
- if (table->table) {
- return (table);
- }
- free(table);
+ if (VIR_ALLOC(table) < 0)
+ return NULL;
+
+ table->size = size;
+ table->nbElems = 0;
+ if (VIR_ALLOC_N(table->table, size) < 0) {
+ VIR_FREE(table);
+ return NULL;
}
- return (NULL);
+
+ return table;
}
/**
if (oldtable == NULL)
return (-1);
- table->table = calloc(1, size * sizeof(*(table->table)));
- if (table->table == NULL) {
+ if (VIR_ALLOC_N(table->table, size) < 0) {
table->table = oldtable;
return (-1);
}
if (table->table[key].valid == 0) {
memcpy(&(table->table[key]), iter, sizeof(virHashEntry));
table->table[key].next = NULL;
- free(iter);
+ VIR_FREE(iter);
} else {
iter->next = table->table[key].next;
table->table[key].next = iter;
}
}
- free(oldtable);
+ VIR_FREE(oldtable);
#ifdef DEBUG_GROW
xmlGenericError(xmlGenericErrorContext,
next = iter->next;
if ((f != NULL) && (iter->payload != NULL))
f(iter->payload, iter->name);
- free(iter->name);
+ VIR_FREE(iter->name);
iter->payload = NULL;
if (!inside_table)
- free(iter);
+ VIR_FREE(iter);
nbElems--;
inside_table = 0;
iter = next;
}
inside_table = 0;
}
- free(table->table);
+ VIR_FREE(table->table);
}
- free(table);
+ VIR_FREE(table);
}
/**
if (insert == NULL) {
entry = &(table->table[key]);
} else {
- entry = malloc(sizeof(*entry));
- if (entry == NULL)
+ if (VIR_ALLOC(entry) < 0)
return (-1);
}
if (insert == NULL) {
entry = &(table->table[key]);
} else {
- entry = malloc(sizeof(*entry));
- if (entry == NULL)
+ if (VIR_ALLOC(entry) < 0)
return (-1);
}
if ((f != NULL) && (entry->payload != NULL))
f(entry->payload, entry->name);
entry->payload = NULL;
- free(entry->name);
+ VIR_FREE(entry->name);
if (prev) {
prev->next = entry->next;
- free(entry);
+ VIR_FREE(entry);
} else {
if (entry->next == NULL) {
entry->valid = 0;
entry = entry->next;
memcpy(&(table->table[key]), entry,
sizeof(virHashEntry));
- free(entry);
+ VIR_FREE(entry);
}
}
table->nbElems--;
if (iter(entry->payload, entry->name, data)) {
count++;
f(entry->payload, entry->name);
- free(entry->name);
+ VIR_FREE(entry->name);
table->nbElems--;
if (prev) {
prev->next = entry->next;
- free(entry);
+ VIR_FREE(entry);
entry = prev;
} else {
if (entry->next == NULL) {
entry = entry->next;
memcpy(&(table->table[i]), entry,
sizeof(virHashEntry));
- free(entry);
+ VIR_FREE(entry);
entry = &(table->table[i]);
continue;
}
virGetConnect(void) {
virConnectPtr ret;
- ret = calloc(1, sizeof(*ret));
- if (ret == NULL) {
+ if (VIR_ALLOC(ret) < 0) {
virHashError(NULL, VIR_ERR_NO_MEMORY, _("allocating connection"));
goto failed;
}
virHashFree(ret->storageVols, (virHashDeallocator) virStorageVolFreeName);
pthread_mutex_destroy(&ret->lock);
- free(ret);
+ VIR_FREE(ret);
}
return(NULL);
}
if (__lastErr.conn == conn)
__lastErr.conn = NULL;
- free(conn->name);
+ VIR_FREE(conn->name);
pthread_mutex_unlock(&conn->lock);
pthread_mutex_destroy(&conn->lock);
- free(conn);
+ VIR_FREE(conn);
}
/**
ret = (virDomainPtr) virHashLookup(conn->domains, name);
/* TODO check the UUID */
if (ret == NULL) {
- ret = (virDomainPtr) calloc(1, sizeof(*ret));
- if (ret == NULL) {
+ VIR_ALLOC(ret);
+ if (0) {
virHashError(conn, VIR_ERR_NO_MEMORY, _("allocating domain"));
goto error;
}
error:
pthread_mutex_unlock(&conn->lock);
if (ret != NULL) {
- free(ret->name );
- free(ret);
+ VIR_FREE(ret->name);
+ VIR_FREE(ret);
}
return(NULL);
}
__lastErr.dom = NULL;
domain->magic = -1;
domain->id = -1;
- free(domain->name);
- free(domain);
+ VIR_FREE(domain->name);
+ VIR_FREE(domain);
DEBUG("unref connection %p %s %d", conn, conn->name, conn->refs);
conn->refs--;
ret = (virNetworkPtr) virHashLookup(conn->networks, name);
/* TODO check the UUID */
if (ret == NULL) {
- ret = (virNetworkPtr) calloc(1, sizeof(*ret));
- if (ret == NULL) {
+ if (VIR_ALLOC(ret) < 0) {
virHashError(conn, VIR_ERR_NO_MEMORY, _("allocating network"));
goto error;
}
error:
pthread_mutex_unlock(&conn->lock);
if (ret != NULL) {
- free(ret->name );
- free(ret);
+ VIR_FREE(ret->name);
+ VIR_FREE(ret);
}
return(NULL);
}
__lastErr.net = NULL;
network->magic = -1;
- free(network->name);
- free(network);
+ VIR_FREE(network->name);
+ VIR_FREE(network);
DEBUG("unref connection %p %s %d", conn, conn->name, conn->refs);
conn->refs--;
ret = (virStoragePoolPtr) virHashLookup(conn->storagePools, name);
/* TODO check the UUID */
if (ret == NULL) {
- ret = (virStoragePoolPtr) calloc(1, sizeof(*ret));
- if (ret == NULL) {
+ if (VIR_ALLOC(ret) < 0) {
virHashError(conn, VIR_ERR_NO_MEMORY, _("allocating storage pool"));
goto error;
}
error:
pthread_mutex_unlock(&conn->lock);
if (ret != NULL) {
- free(ret->name);
- free(ret);
+ VIR_FREE(ret->name);
+ VIR_FREE(ret);
}
return(NULL);
}
_("pool missing from connection hash table"));
pool->magic = -1;
- free(pool->name);
- free(pool);
+ VIR_FREE(pool->name);
+ VIR_FREE(pool);
DEBUG("unref connection %p %s %d", conn, conn->name, conn->refs);
conn->refs--;
ret = (virStorageVolPtr) virHashLookup(conn->storageVols, key);
if (ret == NULL) {
- ret = (virStorageVolPtr) calloc(1, sizeof(*ret));
- if (ret == NULL) {
+ if (VIR_ALLOC(ret) < 0) {
virHashError(conn, VIR_ERR_NO_MEMORY, _("allocating storage vol"));
goto error;
}
error:
pthread_mutex_unlock(&conn->lock);
if (ret != NULL) {
- free(ret->name);
- free(ret->pool);
- free(ret);
+ VIR_FREE(ret->name);
+ VIR_FREE(ret->pool);
+ VIR_FREE(ret);
}
return(NULL);
}
_("vol missing from connection hash table"));
vol->magic = -1;
- free(vol->name);
- free(vol->pool);
- free(vol);
+ VIR_FREE(vol->name);
+ VIR_FREE(vol->pool);
+ VIR_FREE(vol);
DEBUG("unref connection %p %s %d", conn, conn->name, conn->refs);
conn->refs--;
#define VIR_DEBUG(category, fmt,...) \
do { if (debugFlag) fprintf (stderr, "DEBUG: %s: %s (" fmt ")\n", category, __func__, __VA_ARGS__); } while (0)
#else
-#define VIR_DEBUG(category, fmt,...)
+#define VIR_DEBUG(category, fmt,...) \
do { } while (0)
#endif /* !ENABLE_DEBUG */
#endif
#ifdef __GNUC__
+
+#ifndef __GNUC_PREREQ
+#define __GNUC_PREREQ(maj,min) 0
+#endif
+
/**
* ATTRIBUTE_UNUSED:
*
#define ATTRIBUTE_FORMAT(args...) __attribute__((__format__ (args)))
#endif
+#ifndef ATTRIBUTE_RETURN_CHECK
+#if __GNUC_PREREQ (3, 4)
+#define ATTRIBUTE_RETURN_CHECK __attribute__((__warn_unused_result__))
+#else
+#define ATTRIBUTE_RETURN_CHECK
+#endif
+#endif
+
#else
#define ATTRIBUTE_UNUSED
#define ATTRIBUTE_FORMAT(...)
+#define ATTRIBUTE_RETURN_CHECK
#endif /* __GNUC__ */
/**
--- /dev/null
+/*
+ * memory.c: safer memory allocation
+ *
+ * Copyright (C) 2008 Daniel P. Berrange
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <stdlib.h>
+
+#include "memory.h"
+
+
+/* Return 1 if an array of N objects, each of size S, cannot exist due
+ to size arithmetic overflow. S must be positive and N must be
+ nonnegative. This is a macro, not an inline function, so that it
+ works correctly even when SIZE_MAX < N.
+
+ By gnulib convention, SIZE_MAX represents overflow in size
+ calculations, so the conservative dividend to use here is
+ SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value.
+ However, malloc (SIZE_MAX) fails on all known hosts where
+ sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for
+ exactly-SIZE_MAX allocations on such hosts; this avoids a test and
+ branch when S is known to be 1. */
+# define xalloc_oversized(n, s) \
+ ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n))
+
+
+/**
+ * virAlloc:
+ * @ptrptr: pointer to pointer for address of allocated memory
+ * @size: number of bytes to allocate
+ *
+ * Allocate 'size' bytes of memory. Return the address of the
+ * allocated memory in 'ptrptr'. The newly allocated memory is
+ * filled with zeros.
+ *
+ * Returns -1 on failure to allocate, zero on success
+ */
+int virAlloc(void *ptrptr, size_t size)
+{
+ if (size == 0) {
+ *(void **)ptrptr = NULL;
+ return 0;
+ }
+
+
+
+ *(void **)ptrptr = calloc(1, size);
+ if (*(void **)ptrptr == NULL)
+ return -1;
+ return 0;
+}
+
+/**
+ * virAllocN:
+ * @ptrptr: pointer to pointer for address of allocated memory
+ * @size: number of bytes to allocate
+ * @count: number of elements to allocate
+ *
+ * Allocate an array of memory 'count' elements long,
+ * each with 'size' bytes. Return the address of the
+ * allocated memory in 'ptrptr'. The newly allocated
+ * memory is filled with zeros.
+ *
+ * Returns -1 on failure to allocate, zero on success
+ */
+int virAllocN(void *ptrptr, size_t size, size_t count)
+{
+ if (size == 0 || count == 0) {
+ *(void **)ptrptr = NULL;
+ return 0;
+ }
+
+ *(void**)ptrptr = calloc(count, size);
+ if (*(void**)ptrptr == NULL)
+ return -1;
+ return 0;
+}
+
+/**
+ * virReallocN:
+ * @ptrptr: pointer to pointer for address of allocated memory
+ * @size: number of bytes to allocate
+ * @count: number of elements in array
+ *
+ * Resize the block of memory in 'ptrptr' to be an array of
+ * 'count' elements, each 'size' bytes in length. Update 'ptrptr'
+ * with the address of the newly allocated memory. On failure,
+ * 'ptrptr' is not changed and still points to the original memory
+ * block. The newly allocated memory is filled with zeros.
+ *
+ * Returns -1 on failure to allocate, zero on success
+ */
+int virReallocN(void *ptrptr, size_t size, size_t count)
+{
+ void *tmp;
+ if (size == 0 || count == 0) {
+ free(*(void **)ptrptr);
+ *(void **)ptrptr = NULL;
+ return 0;
+ }
+ if (xalloc_oversized(count, size)) {
+ errno = ENOMEM;
+ return -1;
+ }
+ tmp = realloc(*(void**)ptrptr, size * count);
+ if (!tmp)
+ return -1;
+ *(void**)ptrptr = tmp;
+ return 0;
+}
+
+/**
+ * virFree:
+ * @ptrptr: pointer to pointer for address of memory to be freed
+ *
+ * Release the chunk of memory in the pointer pointed to by
+ * the 'ptrptr' variable. After release, 'ptrptr' will be
+ * updated to point to NULL.
+ */
+void virFree(void *ptrptr)
+{
+ free(*(void**)ptrptr);
+ *(void**)ptrptr = NULL;
+}
--- /dev/null
+/*
+ * memory.c: safer memory allocation
+ *
+ * Copyright (C) 2008 Daniel P. Berrange
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+
+#ifndef __VIR_MEMORY_H_
+#define __VIR_MEMORY_H_
+
+#include "internal.h"
+
+/* Don't call these directly - use the macros below */
+int virAlloc(void *ptrptr, size_t size) ATTRIBUTE_RETURN_CHECK;
+int virAllocN(void *ptrptr, size_t size, size_t count) ATTRIBUTE_RETURN_CHECK;
+int virReallocN(void *ptrptr, size_t size, size_t count) ATTRIBUTE_RETURN_CHECK;
+void virFree(void *ptrptr);
+
+
+/**
+ * VIR_ALLOC:
+ * @ptr: pointer to hold address of allocated memory
+ *
+ * Allocate sizeof(*ptr) bytes of memory and store
+ * the address of allocated memory in 'ptr'. Fill the
+ * newly allocated memory with zeros.
+ *
+ * Returns -1 on failure, 0 on success
+ */
+#define VIR_ALLOC(ptr) virAlloc(&(ptr), sizeof(*(ptr)))
+
+/**
+ * VIR_ALLOC_N:
+ * @ptr: pointer to hold address of allocated memory
+ * @count: number of elements to allocate
+ *
+ * Allocate an array of 'count' elements, each sizeof(*ptr)
+ * bytes long and store the address of allocated memory in
+ * 'ptr'. Fill the newly allocated memory with zeros.
+ *
+ * Returns -1 on failure, 0 on success
+ */
+#define VIR_ALLOC_N(ptr, count) virAllocN(&(ptr), sizeof(*(ptr)), (count))
+
+/**
+ * VIR_REALLOC_N:
+ * @ptr: pointer to hold address of allocated memory
+ * @count: number of elements to allocate
+ *
+ * Re-allocate an array of 'count' elements, each sizeof(*ptr)
+ * bytes long and store the address of allocated memory in
+ * 'ptr'. Fill the newly allocated memory with zeros
+ *
+ * Returns -1 on failure, 0 on success
+ */
+#define VIR_REALLOC_N(ptr, count) virReallocN(&(ptr), sizeof(*(ptr)), (count))
+
+/**
+ * VIR_FREE:
+ * @ptr: pointer holding address to be freed
+ *
+ * Free the memory stored in 'ptr' and update to point
+ * to NULL.
+ */
+#define VIR_FREE(ptr) virFree(&(ptr));
+
+#endif /* __VIR_MEMORY_H_ */