...
 
Commits (19)
......@@ -23,38 +23,11 @@ dnl
dnl do we have libvirt installed?
LIBVIRT_REQUIRED=0.8.0
LIBVIRT_REQUIRED=1.0.6
PKG_CHECK_MODULES(LIBVIRT, libvirt >= $LIBVIRT_REQUIRED)
LIBVIRT_LIBS="$LIBVIRT_LIBS -lvirt"
AC_SUBST(LIBVIRT_LIBS)
dnl do we have old libvirt?
save_CFLAGS="$CFLAGS"
save_LDFLAGS="$LDFLAGS"
save_LIBS="$LIBS"
CFLAGS="$CFLAGS $LIBVIRT_CFLAGS"
LDFLAGS="$CFLAGS $LIBVIRT_LIBS"
AC_CHECK_LIB([virt], [virEventRunDefaultImpl], [old=0], [old=1])
CFLAGS="$save_CFLAGS"
LDFLAGS="$save_LDFLAGS"
LIBS="$save_LIBS"
if test $old = 1 ; then
AC_DEFINE_UNQUOTED([LIBVIRT_OLD], ["$old"], [we are using old libvirt
which does not have new event api])
AC_CHECK_FUNCS([gettimeofday])
AC_CHECK_FUNCS([memmove])
AC_CHECK_HEADERS([fcntl.h])
AC_CHECK_HEADERS([stddef.h])
AC_CHECK_HEADERS([sys/time.h])
AC_CHECK_TYPES([ptrdiff_t])
AC_C_INLINE
AC_FUNC_REALLOC
AC_HEADER_STDBOOL
AC_TYPE_PID_T
AC_HEADER_TIME
fi
AM_CONDITIONAL([LIBVIRT_OLD], [test $old = 1])
AC_SUBST(LIBVIRT_CFLAGS)
SNMP_CONFIG="net-snmp-config"
SNMP_CFLAGS=""
......
bin_PROGRAMS=libvirtMib_subagent
LIBVIRT_OLD_SRCS = \
threads.c \
event_poll.c \
memory.c \
util.c
LIBVIRT_OLD_HDRS = \
internal.h \
ignore-value.h \
threads.h \
event_poll.h \
memory.h \
util.h
USER_SRCS = \
libvirtGuestTable_data_get.c \
libvirtGuestTable_data_set.c \
......@@ -61,10 +47,6 @@ libvirtMib_subagent_LDADD= \
$(LIBVIRT_LIBS) \
$(SNMP_LIBS)
if LIBVIRT_OLD
libvirtMib_subagent_SOURCES+=${LIBVIRT_OLD_SRCS} ${LIBVIRT_OLD_HDRS}
endif
EXTRA_DIST = LIBVIRT-MIB.txt
install-data-local:
......
This diff is collapsed.
/*
* event.h: event loop for monitoring file handles
*
* Copyright (C) 2007 Daniel P. Berrange
* Copyright (C) 2007 Red Hat, Inc.
*
* 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
*
* Author: Daniel P. Berrange <berrange@redhat.com>
*/
#ifndef __VIR_EVENT_POLL_H__
# define __VIR_EVENT_POLL_H__
# include "internal.h"
/**
* virEventPollAddHandle: register a callback for monitoring file handle events
*
* @fd: file handle to monitor for events
* @events: bitset of events to watch from POLLnnn constants
* @cb: callback to invoke when an event occurs
* @opaque: user data to pass to callback
*
* returns -1 if the file handle cannot be registered, 0 upon success
*/
int virEventPollAddHandle(int fd, int events,
virEventHandleCallback cb,
void *opaque,
virFreeCallback ff);
/**
* virEventPollUpdateHandle: change event set for a monitored file handle
*
* @watch: watch whose handle to update
* @events: bitset of events to watch from POLLnnn constants
*
* Will not fail if fd exists
*/
void virEventPollUpdateHandle(int watch, int events);
/**
* virEventPollRemoveHandle: unregister a callback from a file handle
*
* @watch: watch whose handle to remove
*
* returns -1 if the file handle was not registered, 0 upon success
*/
int virEventPollRemoveHandle(int watch);
/**
* virEventPollAddTimeout: register a callback for a timer event
*
* @frequency: time between events in milliseconds
* @cb: callback to invoke when an event occurs
* @opaque: user data to pass to callback
*
* Setting frequency to -1 will disable the timer. Setting the frequency
* to zero will cause it to fire on every event loop iteration.
*
* returns -1 if the file handle cannot be registered, a positive
* integer timer id upon success
*/
int virEventPollAddTimeout(int frequency,
virEventTimeoutCallback cb,
void *opaque,
virFreeCallback ff);
/**
* virEventPollUpdateTimeout: change frequency for a timer
*
* @timer: timer id to change
* @frequency: time between events in milliseconds
*
* Setting frequency to -1 will disable the timer. Setting the frequency
* to zero will cause it to fire on every event loop iteration.
*
* Will not fail if timer exists
*/
void virEventPollUpdateTimeout(int timer, int frequency);
/**
* virEventPollRemoveTimeout: unregister a callback for a timer
*
* @timer: the timer id to remove
*
* returns -1 if the timer was not registered, 0 upon success
*/
int virEventPollRemoveTimeout(int timer);
/**
* virEventPollInit: Initialize the event loop
*
* returns -1 if initialization failed
*/
int virEventPollInit(void);
/**
* virEventPollRunOnce: run a single iteration of the event loop.
*
* Blocks the caller until at least one file handle has an
* event or the first timer expires.
*
* returns -1 if the event monitoring failed
*/
int virEventPollRunOnce(void);
int virEventPollFromNativeEvents(int events);
int virEventPollToNativeEvents(int events);
/**
* virEventPollInterrupt: wakeup any thread waiting in poll()
*
* return -1 if wakup failed
*/
int virEventPollInterrupt(void);
#endif /* __VIRTD_EVENT_H__ */
/* -*- buffer-read-only: t -*- vi: set ro: */
/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
/* ignore a function return without a compiler warning
Copyright (C) 2008-2011 Free Software Foundation, Inc.
This program 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 program 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 program. If not, see <http://www.gnu.org/licenses/>. */
/* Written by Jim Meyering, Eric Blake and Pádraig Brady. */
/* Use "ignore_value" to avoid a warning when using a function declared with
gcc's warn_unused_result attribute, but for which you really do want to
ignore the result. Traditionally, people have used a "(void)" cast to
indicate that a function's return value is deliberately unused. However,
if the function is declared with __attribute__((warn_unused_result)),
gcc issues a warning even with the cast.
Caution: most of the time, you really should heed gcc's warning, and
check the return value. However, in those exceptional cases in which
you're sure you know what you're doing, use this function.
For the record, here's one of the ignorable warnings:
"copy.c:233: warning: ignoring return value of 'fchown',
declared with attribute warn_unused_result". */
#ifndef _GL_IGNORE_VALUE_H
# define _GL_IGNORE_VALUE_H
# ifndef _GL_ATTRIBUTE_DEPRECATED
/* The __attribute__((__deprecated__)) feature
is available in gcc versions 3.1 and newer. */
# if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 1)
# define _GL_ATTRIBUTE_DEPRECATED /* empty */
# else
# define _GL_ATTRIBUTE_DEPRECATED __attribute__ ((__deprecated__))
# endif
# endif
/* The __attribute__((__warn_unused_result__)) feature
is available in gcc versions 3.4 and newer,
while the typeof feature has been available since 2.7 at least. */
# if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4)
# define ignore_value(x) ((void) (x))
# else
# define ignore_value(x) (({ __typeof__ (x) __x = (x); (void) __x; }))
# endif
/* ignore_value works for scalars, pointers and aggregates;
deprecate ignore_ptr. */
static inline void _GL_ATTRIBUTE_DEPRECATED
ignore_ptr (void *p) { (void) p; } /* deprecated: use ignore_value */
#endif
/*
* internal.h: internal definitions just used by code from the library
*
* Copy: Copyright (C) 2005-2006, 2010-2011 Red Hat, Inc.
*
* See libvirt's COPYING.LIB for the License of this software
*
*/
#ifndef __INTERNAL_H__
# define __INTERNAL_H__
# include <stdio.h>
# include <stdlib.h>
# include <stdbool.h>
# include <stddef.h>
# include <errno.h>
# include <string.h>
# include <libvirt/libvirt.h>
# include <libvirt/virterror.h>
/* C99 uses __func__. __FUNCTION__ is legacy. */
# ifndef __GNUC__
# define __FUNCTION__ __func__
# endif
# ifdef __GNUC__
# ifndef __GNUC_PREREQ
# if defined __GNUC__ && defined __GNUC_MINOR__
# define __GNUC_PREREQ(maj, min) \
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
# else
# define __GNUC_PREREQ(maj,min) 0
# endif
/* Work around broken limits.h on debian etch */
# if defined _GCC_LIMITS_H_ && ! defined ULLONG_MAX
# define ULLONG_MAX ULONG_LONG_MAX
# endif
# endif /* __GNUC__ */
/**
* ATTRIBUTE_UNUSED:
*
* Macro to flag conciously unused parameters to functions
*/
# ifndef ATTRIBUTE_UNUSED
# define ATTRIBUTE_UNUSED __attribute__((__unused__))
# endif
/**
* ATTRIBUTE_SENTINEL:
*
* Macro to check for NULL-terminated varargs lists
*/
# ifndef ATTRIBUTE_SENTINEL
# if __GNUC_PREREQ (4, 0)
# define ATTRIBUTE_SENTINEL __attribute__((__sentinel__))
# else
# define ATTRIBUTE_SENTINEL
# endif
# endif
/**
* ATTRIBUTE_FMT_PRINTF
*
* Macro used to check printf like functions, if compiling
* with gcc.
*
* We use gnulib which guarentees we always have GNU style
* printf format specifiers even on broken Win32 platforms
* hence we have to force 'gnu_printf' for new GCC
*/
# ifndef ATTRIBUTE_FMT_PRINTF
# if __GNUC_PREREQ (4, 4)
# define ATTRIBUTE_FMT_PRINTF(fmtpos,argpos) __attribute__((__format__ (gnu_printf, fmtpos,argpos)))
# else
# define ATTRIBUTE_FMT_PRINTF(fmtpos,argpos) __attribute__((__format__ (printf, fmtpos,argpos)))
# endif
# 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
/**
* ATTRIBUTE_PACKED
*
* force a structure to be packed, i.e. not following architecture and
* compiler best alignments for its sub components. It's needed for example
* for the network filetering code when defining the content of raw
* ethernet packets.
* Others compiler than gcc may use something different e.g. #pragma pack(1)
*/
# ifndef ATTRIBUTE_PACKED
# if __GNUC_PREREQ (3, 3)
# define ATTRIBUTE_PACKED __attribute__((packed))
# else
# error "Need an __attribute__((packed)) equivalent"
# endif
# endif
# ifndef ATTRIBUTE_NONNULL
# if __GNUC_PREREQ (3, 3)
# define ATTRIBUTE_NONNULL(m) __attribute__((__nonnull__(m)))
# else
# define ATTRIBUTE_NONNULL(m)
# endif
# endif
# else
# ifndef ATTRIBUTE_UNUSED
# define ATTRIBUTE_UNUSED
# endif
# ifndef ATTRIBUTE_FMT_PRINTF
# define ATTRIBUTE_FMT_PRINTF(...)
# endif
# ifndef ATTRIBUTE_RETURN_CHECK
# define ATTRIBUTE_RETURN_CHECK
# endif
# endif /* __GNUC__ */
extern int verbose;
#define VIR_DEBUG0(fmt) if (verbose) fprintf(stderr, "%s:%d :: " fmt "\n", \
__func__, __LINE__)
#define VIR_DEBUG(fmt, ...) if (verbose) fprintf(stderr, "%s:%d: " fmt "\n", \
__func__, __LINE__, __VA_ARGS__)
#define VIR_WARN(fmt, ...) if (verbose) fprintf(stderr, "%s:%d: " fmt "\n", \
__func__, __LINE__, __VA_ARGS__)
#endif
......@@ -157,9 +157,7 @@ void libvirtGuestTable_rowreq_ctx_cleanup(libvirtGuestTable_rowreq_ctx *rowreq_c
netsnmp_assert(NULL != rowreq_ctx);
/*
* TODO:211:o: |-> Perform extra libvirtGuestTable rowreq cleanup.
*/
free(rowreq_ctx->data.libvirtGuestName);
} /* libvirtGuestTable_rowreq_ctx_cleanup */
/**
......
......@@ -20,14 +20,14 @@
* Author: Michal Privoznik <mprivozn@redhat.com>
*/
#ifndef LIBVIRTNOTIFICATIONS_H
#define LIBVIRTNOTIFICATIONS_H
#ifndef __LIBVIRT_NOTIFICATIONS_H__
# define __LIBVIRT_NOTIFICATIONS_H__
#include "libvirtSnmp.h"
# include <libvirt/libvirt.h>
/*
* function declarations
*/
int send_libvirtGuestNotif_trap(virDomainPtr dom);
#endif /* LIBVIRTNOTIFICATIONS_H */
#endif /* __LIBVIRT_NOTIFICATIONS_H__ */
This diff is collapsed.
......@@ -20,45 +20,41 @@
* Author: Michal Privoznik <mprivozn@redhat.com>
*/
#ifndef __VIR_SNMP_H__
#define __VIR_SNMP_H__
/* standard libvirt includes */
#include <libvirt/libvirt.h>
#include <libvirt/virterror.h>
#ifndef __LIBVIRT_SNMP_H__
# define __LIBVIRT_SNMP_H__
/* standard Net-SNMP includes */
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
# include <net-snmp/net-snmp-config.h>
# include <net-snmp/net-snmp-includes.h>
# include <net-snmp/agent/net-snmp-agent-includes.h>
/*
* Populate libvirtGuestTable into given container.
*/
extern int
int
libvirtSnmpLoadGuests(netsnmp_container *container);
extern int
int
libvirtSnmpInit(void);
extern void
void
libvirtSnmpShutdown(void);
/**
* Check that domain with given UUID exists.
* Return 0 if so, -1 if not.
*/
extern int
int
libvirtSnmpCheckDomainExists(unsigned char *uuid);
extern int
int
libvirtSnmpCreate(unsigned char *uuid, int state);
extern int
int
libvirtSnmpDestroy(unsigned char *uuid);
extern int
int
libvirtSnmpChangeState(unsigned char *uuid, int newstate, int oldstate);
#endif /* __VIR_SNMP_H__ */
#endif /* __LIBVIRT_SNMP_H__ */
......@@ -20,15 +20,86 @@
* Author: Michal Privoznik <mprivozn@redhat.com>
*/
#include "libvirtSnmpError.h"
#include <config.h>
#include <stdio.h>
#include <libvirt/libvirt.h>
#include <libvirt/virterror.h>
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include "libvirtSnmpError.h"
/**
* printLibvirtError:
* @fmt: Error message format string
*
* Print and reset Libvirt error.
*/
void
printLibvirtError(const char *fmt, ...)
{
const char *libvirtErr = virGetLastErrorMessage();
char ebuf[1024];
int rc;
int size = 0;
va_list ap;
va_start(ap, fmt);
rc = vsnprintf(ebuf, sizeof(ebuf), fmt, ap);
size += rc;
va_end(ap);
if (rc < 0 || size >= sizeof(ebuf))
return;
rc = snprintf(ebuf + size, sizeof(ebuf) - size, ": %s\n", libvirtErr);
size += rc;
if (rc < 0 || size >= sizeof(ebuf))
return;
fputs(ebuf, stderr);
snmp_log(LOG_ERR, "%s", ebuf);
virResetLastError();
}
/**
* Print libvirt error
* @msg Error message
* printSystemError:
* @theerrno: the errno value
* @fmt: Error message format string
*
* Print system error with @theerrno translated into human readable form.
*/
void printLibvirtError(const char *msg) {
virErrorPtr err = virGetLastError();
void
printSystemError(int theerrno, const char *fmt, ...)
{
char ebuf[1024];
char sysebuf[1024];
int rc;
int size = 0;
va_list ap;
if (!strerror_r(theerrno, sysebuf, sizeof(sysebuf)))
return;
va_start(ap, fmt);
rc = vsnprintf(ebuf, sizeof(ebuf), fmt, ap);
size += rc;
va_end(ap);
if (rc < 0 || size >= sizeof(ebuf))
return;
rc = snprintf(ebuf + size, sizeof(ebuf) - size, ": %s\n", sysebuf);
size += rc;
if (rc < 0 || size >= sizeof(ebuf))
return;
fprintf(stderr, "%s: %s", msg, err ? err->message : "Unknown error");
fputs(ebuf, stderr);
snmp_log(LOG_ERR, "%s", ebuf);
}
......@@ -20,12 +20,23 @@
* Author: Michal Privoznik <mprivozn@redhat.com>
*/
#ifndef __VIR_SNMP_ERROR_H__
#define __VIR_SNMP_ERROR_H__
#ifndef __LIBVIRT_SNMP_ERROR_H__
# define __LIBVIRT_SNMP_ERROR_H__
#include <libvirt/libvirt.h>
#include <libvirt/virterror.h>
# ifndef ATTRIBUTE_FMT_PRINTF
# ifndef __clang__
# define ATTRIBUTE_FMT_PRINTF(fmtpos, argpos) \
__attribute__((__format__ (__gnu_printf__, fmtpos, argpos)))
# else
# define ATTRIBUTE_FMT_PRINTF(fmtpos, argpos) \
__attribute__((__format__ (__printf__, fmtpos, argpos)))
# endif
# endif
extern void printLibvirtError(const char *msg);
void printLibvirtError(const char *fmt, ...)
ATTRIBUTE_FMT_PRINTF(1, 2);
#endif
void printSystemError(int theerrno, const char *fmt, ...)
ATTRIBUTE_FMT_PRINTF(2, 3);
#endif /* __LIBVIRT_SNMP_ERROR_H__ */
/*
* memory.c: safer memory allocation
*
* Copyright (C) 2010-2011 Red Hat, Inc.
* 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 <config.h>
#include <stdlib.h>
#include "memory.h"
#include "ignore-value.h"
#if TEST_OOM
static int testMallocNext = 0;
static int testMallocFailFirst = 0;
static int testMallocFailLast = 0;
static void (*testMallocHook)(int, void*) = NULL;
static void *testMallocHookData = NULL;
void virAllocTestInit(void)
{
testMallocNext = 1;
testMallocFailFirst = 0;
testMallocFailLast = 0;
}
int virAllocTestCount(void)
{
return testMallocNext - 1;
}
void virAllocTestHook(void (*func)(int, void*), void *data)
{
testMallocHook = func;
testMallocHookData = data;
}
void virAllocTestOOM(int n, int m)
{
testMallocNext = 1;
testMallocFailFirst = n;
testMallocFailLast = n + m - 1;
}
static int virAllocTestFail(void)
{
int fail = 0;
if (testMallocNext == 0)
return 0;
fail =
testMallocNext >= testMallocFailFirst &&
testMallocNext <= testMallocFailLast;
if (fail && testMallocHook)
(testMallocHook)(testMallocNext, testMallocHookData);
testMallocNext++;
return fail;
}
#endif
/**
* 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 TEST_OOM
if (virAllocTestFail()) {
*(void **)ptrptr = NULL;
return -1;
}
#endif
*(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 TEST_OOM
if (virAllocTestFail()) {
*(void **)ptrptr = NULL;
return -1;
}
#endif
*(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. Any newly allocated memory in 'ptrptr' is uninitialized.
*
* Returns -1 on failure to allocate, zero on success
*/
int virReallocN(void *ptrptr, size_t size, size_t count)
{
void *tmp;
#if TEST_OOM
if (virAllocTestFail())
return -1;
#endif
if (xalloc_oversized(count, size)) {
errno = ENOMEM;
return -1;
}
tmp = realloc(*(void**)ptrptr, size * count);
if (!tmp && (size * count))
return -1;
*(void**)ptrptr = tmp;
return 0;
}
/**
* virExpandN:
* @ptrptr: pointer to pointer for address of allocated memory
* @size: number of bytes per element
* @countptr: pointer to number of elements in array
* @add: number of elements to add
*
* Resize the block of memory in 'ptrptr' to be an array of
* '*countptr' + 'add' elements, each 'size' bytes in length.
* Update 'ptrptr' and 'countptr' with the details of the newly
* allocated memory. On failure, 'ptrptr' and 'countptr' are not
* changed. Any newly allocated memory in 'ptrptr' is zero-filled.
*
* Returns -1 on failure to allocate, zero on success
*/
int virExpandN(void *ptrptr, size_t size, size_t *countptr, size_t add)
{
int ret;
if (*countptr + add < *countptr) {
errno = ENOMEM;
return -1;
}
ret = virReallocN(ptrptr, size, *countptr + add);
if (ret == 0) {
memset(*(char **)ptrptr + (size * *countptr), 0, size * add);
*countptr += add;
}
return ret;
}
/**
* virResizeN:
* @ptrptr: pointer to pointer for address of allocated memory
* @size: number of bytes per element
* @allocptr: pointer to number of elements allocated in array
* @count: number of elements currently used in array
* @add: minimum number of additional elements to support in array
*
* If 'count' + 'add' is larger than '*allocptr', then resize the
* block of memory in 'ptrptr' to be an array of at least 'count' +
* 'add' elements, each 'size' bytes in length. Update 'ptrptr' and
* 'allocptr' with the details of the newly allocated memory. On
* failure, 'ptrptr' and 'allocptr' are not changed. Any newly
* allocated memory in 'ptrptr' is zero-filled.
*
* Returns -1 on failure to allocate, zero on success
*/
int virResizeN(void *ptrptr, size_t size, size_t *allocptr, size_t count,
size_t add)
{
size_t delta;
if (count + add < count) {
errno = ENOMEM;
return -1;
}
if (count + add <= *allocptr)
return 0;
delta = count + add - *allocptr;
if (delta < *allocptr / 2)
delta = *allocptr / 2;
return virExpandN(ptrptr, size, allocptr, delta);
}
/**
* virShrinkN:
* @ptrptr: pointer to pointer for address of allocated memory
* @size: number of bytes per element
* @countptr: pointer to number of elements in array
* @toremove: number of elements to remove
*
* Resize the block of memory in 'ptrptr' to be an array of
* '*countptr' - 'toremove' elements, each 'size' bytes in length.
* Update 'ptrptr' and 'countptr' with the details of the newly
* allocated memory. If 'toremove' is larger than 'countptr', free
* the entire array.
*/
void virShrinkN(void *ptrptr, size_t size, size_t *countptr, size_t toremove)
{
if (toremove < *countptr)
ignore_value(virReallocN(ptrptr, size, *countptr -= toremove));
else {
virFree(ptrptr);
*countptr = 0;
}
}
/**
* Vir_Alloc_Var:
* @ptrptr: pointer to hold address of allocated memory
* @struct_size: size of initial struct
* @element_size: size of array elements
* @count: number of array elements to allocate
*
* Allocate struct_size bytes plus an array of 'count' elements, each
* of size element_size. This sort of allocation is useful for
* receiving the data of certain ioctls and other APIs which return a
* struct in which the last element is an array of undefined length.
* The caller of this type of API is expected to know the length of
* the array that will be returned and allocate a suitable buffer to
* contain the returned data. C99 refers to these variable length
* objects as structs containing flexible array members.
*
* Returns -1 on failure, 0 on success
*/
int virAllocVar(void *ptrptr, size_t struct_size, size_t element_size, size_t count)
{
size_t alloc_size = 0;
#if TEST_OOM
if (virAllocTestFail())
return -1;
#endif
if (VIR_ALLOC_VAR_OVERSIZED(struct_size, count, element_size)) {
errno = ENOMEM;
return -1;
}
alloc_size = struct_size + (element_size * count);
*(void **)ptrptr = calloc(1, alloc_size);
if (*(void **)ptrptr == NULL)
return -1;
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)
{
int save_errno = errno;
free(*(void**)ptrptr);
*(void**)ptrptr = NULL;
errno = save_errno;
}
/*
* memory.c: safer memory allocation
*
* Copyright (C) 2010 Red Hat, Inc.
* 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"
/* 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. */
# ifndef xalloc_oversized
# define xalloc_oversized(n, s) \
((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n))
# endif
/* Don't call these directly - use the macros below */
int virAlloc(void *ptrptr, size_t size) ATTRIBUTE_RETURN_CHECK
ATTRIBUTE_NONNULL(1);
int virAllocN(void *ptrptr, size_t size, size_t count) ATTRIBUTE_RETURN_CHECK
ATTRIBUTE_NONNULL(1);
int virReallocN(void *ptrptr, size_t size, size_t count) ATTRIBUTE_RETURN_CHECK
ATTRIBUTE_NONNULL(1);
int virExpandN(void *ptrptr, size_t size, size_t *count, size_t add)
ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3);
int virResizeN(void *ptrptr, size_t size, size_t *alloc, size_t count,
size_t desired)
ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3);
void virShrinkN(void *ptrptr, size_t size, size_t *count, size_t toremove)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3);
int virAllocVar(void *ptrptr,
size_t struct_size,
size_t element_size,
size_t count) ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NONNULL(1);
void virFree(void *ptrptr) ATTRIBUTE_NONNULL(1);
/**
* 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'. If 'ptr' grew, the added memory is uninitialized.
*
* Returns -1 on failure, 0 on success
*/
# define VIR_REALLOC_N(ptr, count) virReallocN(&(ptr), sizeof(*(ptr)), (count))
/**
* VIR_EXPAND_N:
* @ptr: pointer to hold address of allocated memory
* @count: variable tracking number of elements currently allocated
* @add: number of elements to add
*
* Re-allocate an array of 'count' elements, each sizeof(*ptr)
* bytes long, to be 'count' + 'add' elements long, then store the
* address of allocated memory in 'ptr' and the new size in 'count'.
* The new elements are filled with zero.
*
* Returns -1 on failure, 0 on success
*/
# define VIR_EXPAND_N(ptr, count, add) \
virExpandN(&(ptr), sizeof(*(ptr)), &(count), add)
/**
* VIR_RESIZE_N:
* @ptr: pointer to hold address of allocated memory
* @alloc: variable tracking number of elements currently allocated
* @count: number of elements currently in use
* @add: minimum number of elements to additionally support
*
* Blindly using VIR_EXPAND_N(array, alloc, 1) in a loop scales
* quadratically, because every iteration must copy contents from
* all prior iterations. But amortized linear scaling can be achieved
* by tracking allocation size separately from the number of used
* elements, and growing geometrically only as needed.
*
* If 'count' + 'add' is larger than 'alloc', then geometrically reallocate
* the array of 'alloc' elements, each sizeof(*ptr) bytes long, and store
* the address of allocated memory in 'ptr' and the new size in 'alloc'.
* The new elements are filled with zero.
*
* Returns -1 on failure, 0 on success
*/
# define VIR_RESIZE_N(ptr, alloc, count, add) \
virResizeN(&(ptr), sizeof(*(ptr)), &(alloc), count, add)
/**
* VIR_SHRINK_N:
* @ptr: pointer to hold address of allocated memory
* @count: variable tracking number of elements currently allocated
* @remove: number of elements to remove
*
* Re-allocate an array of 'count' elements, each sizeof(*ptr)
* bytes long, to be 'count' - 'remove' elements long, then store the
* address of allocated memory in 'ptr' and the new size in 'count'.
* If 'count' <= 'remove', the entire array is freed.
*
* No return value.
*/
# define VIR_SHRINK_N(ptr, count, remove) \
virShrinkN(&(ptr), sizeof(*(ptr)), &(count), remove)
/*
* VIR_ALLOC_VAR_OVERSIZED:
* @M: size of base structure
* @N: number of array elements in trailing array
* @S: size of trailing array elements
*
* Check to make sure that the requested allocation will not cause
* arithmetic overflow in the allocation size. The check is
* essentially the same as that in gnulib's xalloc_oversized.
*/
# define VIR_ALLOC_VAR_OVERSIZED(M, N, S) ((((size_t)-1) - (M)) / (S) < (N))
/**
* VIR_ALLOC_VAR:
* @ptr: pointer to hold address of allocated memory
* @type: element type of trailing array
* @count: number of array elements to allocate
*
* Allocate sizeof(*ptr) bytes plus an array of 'count' elements, each
* sizeof('type'). This sort of allocation is useful for receiving
* the data of certain ioctls and other APIs which return a struct in
* which the last element is an array of undefined length. The caller
* of this type of API is expected to know the length of the array
* that will be returned and allocate a suitable buffer to contain the
* returned data. C99 refers to these variable length objects as
* structs containing flexible array members.
* Returns -1 on failure, 0 on success
*/
# define VIR_ALLOC_VAR(ptr, type, count) \
virAllocVar(&(ptr), sizeof(*(ptr)), sizeof(type), (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))
# if TEST_OOM
void virAllocTestInit(void);
int virAllocTestCount(void);
void virAllocTestOOM(int n, int m);
void virAllocTestHook(void (*func)(int, void*), void *data);
# endif
#endif /* __VIR_MEMORY_H_ */
/*
* threads.c: basic thread synchronization primitives
*
* Copyright (C) 2009-2010 Red Hat, Inc.
*
* 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 <config.h>
#include <unistd.h>
#include <inttypes.h>
#if HAVE_SYS_SYSCALL_H
# include <sys/syscall.h>
#endif
#include "threads.h"
#include "memory.h"
/* Nothing special required for pthreads */
int virThreadInitialize(void)
{
return 0;
}
void virThreadOnExit(void)
{
}
int virMutexInit(virMutexPtr m)
{
int ret;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
ret = pthread_mutex_init(&m->lock, &attr);
pthread_mutexattr_destroy(&attr);
if (ret != 0) {
errno = ret;
return -1;
}
return 0;
}
int virMutexInitRecursive(virMutexPtr m)
{
int ret;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
ret = pthread_mutex_init(&m->lock, &attr);
pthread_mutexattr_destroy(&attr);
if (ret != 0) {
errno = ret;
return -1;
}
return 0;
}
void virMutexDestroy(virMutexPtr m)
{
pthread_mutex_destroy(&m->lock);
}
void virMutexLock(virMutexPtr m){
pthread_mutex_lock(&m->lock);
}
void virMutexUnlock(virMutexPtr m)
{
pthread_mutex_unlock(&m->lock);
}
int virCondInit(virCondPtr c)
{
int ret;
if ((ret = pthread_cond_init(&c->cond, NULL)) != 0) {
errno = ret;
return -1;
}
return 0;
}
int virCondDestroy(virCondPtr c)
{
int ret;
if ((ret = pthread_cond_destroy(&c->cond)) != 0) {
errno = ret;
return -1;
}
return 0;
}
int virCondWait(virCondPtr c, virMutexPtr m)
{
int ret;
if ((ret = pthread_cond_wait(&c->cond, &m->lock)) != 0) {
errno = ret;
return -1;
}
return 0;
}
int virCondWaitUntil(virCondPtr c, virMutexPtr m, unsigned long long whenms)
{
int ret;
struct timespec ts;
ts.tv_sec = whenms / 1000;
ts.tv_nsec = (whenms % 1000) * 1000;
if ((ret = pthread_cond_timedwait(&c->cond, &m->lock, &ts)) != 0) {
errno = ret;
return -1;
}
return 0;
}
void virCondSignal(virCondPtr c)
{
pthread_cond_signal(&c->cond);
}
void virCondBroadcast(virCondPtr c)
{
pthread_cond_broadcast(&c->cond);
}
struct virThreadArgs {
virThreadFunc func;
void *opaque;
};
static void *virThreadHelper(void *data)
{
struct virThreadArgs *args = data;
args->func(args->opaque);
VIR_FREE(args);
return NULL;
}
int virThreadCreate(virThreadPtr thread,
bool joinable,
virThreadFunc func,
void *opaque)
{
struct virThreadArgs *args;
pthread_attr_t attr;
int ret = -1;
int err;
if ((err = pthread_attr_init(&attr)) != 0)
goto cleanup;
if (VIR_ALLOC(args) < 0) {
err = ENOMEM;
goto cleanup;
}
args->func = func;
args->opaque = opaque;
if (!joinable)
pthread_attr_setdetachstate(&attr, 1);
err = pthread_create(&thread->thread, &attr, virThreadHelper, args);
if (err != 0) {
VIR_FREE(args);
goto cleanup;
}
/* New thread owns 'args' in success case, so don't free */
ret = 0;
cleanup:
pthread_attr_destroy(&attr);
if (ret < 0)
errno = err;
return ret;
}
void virThreadSelf(virThreadPtr thread)
{
thread->thread = pthread_self();
}
bool virThreadIsSelf(virThreadPtr thread)
{
return pthread_equal(pthread_self(), thread->thread) ? true : false;
}
/* For debugging use only; this result is not guaranteed unique on BSD
* systems when pthread_t is a 64-bit pointer. */
int virThreadSelfID(void)
{
#if defined(HAVE_SYS_SYSCALL_H) && defined(SYS_gettid)
pid_t tid;
tid = syscall(SYS_gettid);
return (int)tid;
#else
return (int)pthread_self();
#endif
}
/* For debugging use only; this result is not guaranteed unique on BSD
* systems when pthread_t is a 64-bit pointer, nor does it match the
* thread id of virThreadSelfID on Linux. */
int virThreadID(virThreadPtr thread)
{
return (int)(uintptr_t)thread->thread;
}
void virThreadJoin(virThreadPtr thread)
{
pthread_join(thread->thread, NULL);
}
int virThreadLocalInit(virThreadLocalPtr l,
virThreadLocalCleanup c)
{
int ret;
if ((ret = pthread_key_create(&l->key, c)) != 0) {
errno = ret;
return -1;
}
return 0;
}
void *virThreadLocalGet(virThreadLocalPtr l)
{
return pthread_getspecific(l->key);
}
void virThreadLocalSet(virThreadLocalPtr l, void *val)
{
pthread_setspecific(l->key, val);
}
/*
* threads.h: basic thread synchronization primitives
*
* Copyright (C) 2009-2010 Red Hat, Inc.
*
* 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 __THREADS_H_
# define __THREADS_H_
# include "internal.h"
# include <pthread.h>
typedef struct virMutex virMutex;
typedef virMutex *virMutexPtr;
typedef struct virCond virCond;
typedef virCond *virCondPtr;
typedef struct virThreadLocal virThreadLocal;
typedef virThreadLocal *virThreadLocalPtr;
typedef struct virThread virThread;
typedef virThread *virThreadPtr;
int virThreadInitialize(void) ATTRIBUTE_RETURN_CHECK;
void virThreadOnExit(void);
typedef void (*virThreadFunc)(void *opaque);
int virThreadCreate(virThreadPtr thread,
bool joinable,
virThreadFunc func,
void *opaque) ATTRIBUTE_RETURN_CHECK;
void virThreadSelf(virThreadPtr thread);
bool virThreadIsSelf(virThreadPtr thread);
void virThreadJoin(virThreadPtr thread);
/* These next two functions are for debugging only, since they are not
* guaranteed to give unique values for distinct threads on all
* architectures, nor are the two functions guaranteed to give the same
* value for the same thread. */
int virThreadSelfID(void);
int virThreadID(virThreadPtr thread);
int virMutexInit(virMutexPtr m) ATTRIBUTE_RETURN_CHECK;
int virMutexInitRecursive(virMutexPtr m) ATTRIBUTE_RETURN_CHECK;
void virMutexDestroy(virMutexPtr m);
void virMutexLock(virMutexPtr m);
void virMutexUnlock(virMutexPtr m);
int virCondInit(virCondPtr c) ATTRIBUTE_RETURN_CHECK;
int virCondDestroy(virCondPtr c) ATTRIBUTE_RETURN_CHECK;
int virCondWait(virCondPtr c, virMutexPtr m) ATTRIBUTE_RETURN_CHECK;
int virCondWaitUntil(virCondPtr c, virMutexPtr m, unsigned long long whenms) ATTRIBUTE_RETURN_CHECK;
void virCondSignal(virCondPtr c);
void virCondBroadcast(virCondPtr c);
typedef void (*virThreadLocalCleanup)(void *);
int virThreadLocalInit(virThreadLocalPtr l,
virThreadLocalCleanup c) ATTRIBUTE_RETURN_CHECK;
void *virThreadLocalGet(virThreadLocalPtr l);
void virThreadLocalSet(virThreadLocalPtr l, void*);
struct virMutex {
pthread_mutex_t lock;
};
struct virCond {
pthread_cond_t cond;
};
struct virThread {
pthread_t thread;
};
struct virThreadLocal {
pthread_key_t key;
};
#endif
/*
* utils.c: common, generic utility functions
*
* Copyright (C) 2006-2011 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
* Copyright (C) 2006, 2007 Binary Karma
* Copyright (C) 2006 Shuveb Hussain
*
* 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
*
* Author: Daniel P. Berrange <berrange@redhat.com>
* File created Jul 18, 2007 - Shuveb Hussain <shuveb@binarykarma.com>
*/
#include "util.h"
#include <unistd.h>
#include <fcntl.h>
/* Like read(), but restarts after EINTR */
ssize_t
saferead(int fd, void *buf, size_t count)
{
size_t nread = 0;
while (count > 0) {
ssize_t r = read(fd, buf, count);
if (r < 0 && errno == EINTR)
continue;
if (r < 0)
return r;
if (r == 0)
return nread;
buf = (char *)buf + r;
count -= r;
nread += r;
}
return nread;
}
/* Like write(), but restarts after EINTR */
ssize_t
safewrite(int fd, const void *buf, size_t count)
{
size_t nwritten = 0;
while (count > 0) {
ssize_t r = write(fd, buf, count);
if (r < 0 && errno == EINTR)
continue;
if (r < 0)
return r;
if (r == 0)
return nwritten;
buf = (const char *)buf + r;
count -= r;
nwritten += r;
}
return nwritten;
}
int virSetBlocking(int fd, bool blocking) {
int flags;
if ((flags = fcntl(fd, F_GETFL)) < 0)
return -1;
if (blocking)
flags &= ~O_NONBLOCK;
else
flags |= O_NONBLOCK;
if ((fcntl(fd, F_SETFL, flags)) < 0)
return -1;
return 0;
}
int virSetNonBlock(int fd) {
return virSetBlocking(fd, false);
}
int virSetCloseExec(int fd)
{
return virSetInherit(fd, false);
}
int virSetInherit(int fd, bool inherit) {
int flags;
if ((flags = fcntl(fd, F_GETFD)) < 0)
return -1;
if (inherit)
flags &= ~FD_CLOEXEC;
else
flags |= FD_CLOEXEC;
if ((fcntl(fd, F_SETFD, flags)) < 0)
return -1;