+Mon Feb 27 16:32:55 EST 2006 Daniel Veillard <veillard@redhat.com>
+
+ * include/virterror.h src/libvirt_sym.version: exported
+ virDefaultErrorFunc()
+ * src/sexpr.c src/xen_internal.c src/virterror.c include/virterror.h:
+ adding more error reporting though the code, nearly complete.
+ * src/sexpr.c: added specific error function to avoid an error report.
+
Mon Feb 27 14:56:57 EST 2006 Daniel Veillard <veillard@redhat.com>
* include/virterror.h src/virterror.c src/xend_internal.c: more work
VIR_ERR_GET_FAILED,/* a HTTP GET command to failed */
VIR_ERR_POST_FAILED,/* a HTTP POST command to failed */
VIR_ERR_HTTP_ERROR,/* unexpected HTTP error code */
+ VIR_ERR_SEXPR_SERIAL,/* failure to serialize an S-Expr */
+ VIR_ERR_NO_XEN,/* could not open Xen hypervisor control */
+ VIR_ERR_XEN_CALL,/* failure doing an hypervisor call */
} virErrorNumber;
/**
void virConnResetLastError (virConnectPtr conn);
int virCopyLastError (virErrorPtr to);
+void virDefaultErrorFunc (virErrorPtr err);
void virSetErrorFunc (void *userData,
virErrorFunc handler);
void virConnSetErrorFunc (virConnectPtr conn,
VIR_ERR_GET_FAILED,/* a HTTP GET command to failed */
VIR_ERR_POST_FAILED,/* a HTTP POST command to failed */
VIR_ERR_HTTP_ERROR,/* unexpected HTTP error code */
+ VIR_ERR_SEXPR_SERIAL,/* failure to serialize an S-Expr */
+ VIR_ERR_NO_XEN,/* could not open Xen hypervisor control */
+ VIR_ERR_XEN_CALL,/* failure doing an hypervisor call */
} virErrorNumber;
/**
void virConnResetLastError (virConnectPtr conn);
int virCopyLastError (virErrorPtr to);
+void virDefaultErrorFunc (virErrorPtr err);
void virSetErrorFunc (void *userData,
virErrorFunc handler);
void virConnSetErrorFunc (virConnectPtr conn,
virSetErrorFunc;
virConnCopyLastError;
virConnResetLastError;
+ virDefaultErrorFunc;
local: *;
};
#define _GNU_SOURCE
#include "sexpr.h"
+#include "internal.h"
#include <malloc.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
+/**
+ * virSexprError:
+ * @conn: the connection if available
+ * @error: the error noumber
+ * @info: extra information string
+ *
+ * Handle an error in the S-Expression code
+ */
+static void
+virSexprError(virErrorNumber error, const char *info) {
+ const char *errmsg;
+
+ if (error == VIR_ERR_OK)
+ return;
+
+ errmsg = __virErrorMsg(error, info);
+ __virRaiseError(NULL, NULL, VIR_FROM_SEXPR, error, VIR_ERR_ERROR,
+ errmsg, info, NULL, 0, 0, errmsg, info);
+}
+
/**
* sexpr_new:
*
ret = (struct sexpr *) malloc(sizeof(*ret));
if (ret == NULL) {
+ virSexprError(VIR_ERR_NO_MEMORY, "failed to allocate a node");
return(NULL);
}
ret->kind = SEXPR_NIL;
case SEXPR_CONS:
tmp = snprintf(buffer + ret, n_buffer - ret, "(");
if (tmp == 0)
- return(0);
+ goto error;
ret += tmp;
tmp = sexpr2string(sexpr->car, buffer + ret, n_buffer - ret);
if (tmp == 0)
- return(0);
+ goto error;
ret += tmp;
while (sexpr->cdr->kind != SEXPR_NIL) {
sexpr = sexpr->cdr;
tmp = snprintf(buffer + ret, n_buffer - ret, " ");
if (tmp == 0)
- return(0);
+ goto error;
ret += tmp;
tmp = sexpr2string(sexpr->car, buffer + ret, n_buffer - ret);
if (tmp == 0)
- return(0);
+ goto error;
ret += tmp;
}
tmp = snprintf(buffer + ret, n_buffer - ret, ")");
if (tmp == 0)
- return(0);
+ goto error;
ret += tmp;
break;
case SEXPR_VALUE:
tmp = snprintf(buffer + ret, n_buffer - ret, "%s",
sexpr->value);
if (tmp == 0)
- return(0);
+ goto error;
ret += tmp;
break;
case SEXPR_NIL:
break;
default:
- return(0);
+ goto error;
}
return(ret);
+error:
+ buffer[n_buffer - 1] = 0;
+ virSexprError(VIR_ERR_SEXPR_SERIAL, buffer);
+ return(0);
}
#define IS_SPACE(c) ((c == 0x20) || (c == 0x9) || (c == 0xD) || (c == 0xA))
}
ret->value = strndup(start, ptr - start);
+ if (ret->value == NULL) {
+ virSexprError(VIR_ERR_NO_MEMORY, "failed to copy a string");
+ }
if (*ptr == '\'')
ptr++;
}
ret->value = strndup(start, ptr - start);
+ if (ret->value == NULL) {
+ virSexprError(VIR_ERR_NO_MEMORY, "failed to copy a string");
+ }
}
ret->kind = SEXPR_VALUE;
+ if (ret->value == NULL)
+ goto error;
}
*end = ptr - buffer;
return ret;
+
+error:
+ sexpr_free(ret);
+ return(NULL);
}
/**
#define _GNU_SOURCE /* isblank() */
#include "libvirt.h"
+#include "virterror.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
VSH_DEBUG5
} vshOutType;
+/*
+ * The error handler for virtsh
+ */
+static void
+virshErrorHandler(void *unused, virErrorPtr error) {
+ if ((unused != NULL) || (error == NULL))
+ return;
+
+ /* Suppress the VIR_ERR_NO_XEN error which fails as non-root */
+ if ((error->code == VIR_ERR_NO_XEN) || (error->code == VIR_ERR_OK))
+ return;
+
+ virDefaultErrorFunc(error);
+}
+
/*
* virsh command line grammar:
*
ctl->uid = getuid();
+ /* set up the library error handler */
+ virSetErrorFunc(NULL, virshErrorHandler);
+
/* basic connection to hypervisor */
if (ctl->uid == 0)
ctl->conn = virConnectOpen(NULL);
}
/**
- * virReportError:
+ * virDefaultErrorFunc:
* @err: pointer to the error.
*
- * Internal routine reporting an error to stderr.
+ * Default routine reporting an error to stderr.
*/
-static void
-virReportError(virErrorPtr err) {
+void
+virDefaultErrorFunc(virErrorPtr err) {
const char *lvl = "", *dom = "", *domain = "";
int len;
if (handler != NULL) {
handler(userData, to);
} else {
- virReportError(to);
+ virDefaultErrorFunc(to);
}
}
errmsg = "got unknown HTTP error code %d";
break;
case VIR_ERR_UNKNOWN_HOST:
- errmsg = "Unknown host %s";
+ errmsg = "unknown host %s";
+ break;
+ case VIR_ERR_SEXPR_SERIAL:
+ if (info != NULL)
+ errmsg = "failed to serialize S-Expr: %s";
+ else
+ errmsg = "failed to serialize S-Expr";
+ break;
+ case VIR_ERR_NO_XEN:
+ if (info == NULL)
+ errmsg = "could not use Xen hypervisor entry";
+ else
+ errmsg = "could not use Xen hypervisor entry %s";
+ break;
+ case VIR_ERR_XEN_CALL:
+ errmsg = "failed Xen syscall %s %d";
break;
}
return(errmsg);
#define XEN_HYPERVISOR_SOCKET "/proc/xen/privcmd"
+/**
+ * virXenError:
+ * @conn: the connection if available
+ * @error: the error number
+ * @info: extra information string
+ *
+ * Handle an error at the xend daemon interface
+ */
+static void
+virXenError(virErrorNumber error, const char *info, int value) {
+ const char *errmsg;
+
+ if (error == VIR_ERR_OK)
+ return;
+
+ errmsg = __virErrorMsg(error, info);
+ __virRaiseError(NULL, NULL, VIR_FROM_XEN, error, VIR_ERR_ERROR,
+ errmsg, info, NULL, value, 0, errmsg, info,
+ value);
+}
+
/**
* xenHypervisorOpen:
*
int ret;
ret = open(XEN_HYPERVISOR_SOCKET, O_RDWR);
- if (ret < 0)
+ if (ret < 0) {
+ virXenError(VIR_ERR_NO_XEN, XEN_HYPERVISOR_SOCKET, 0);
return(-1);
+ }
return(ret);
}
hc.op = __HYPERVISOR_dom0_op;
hc.arg[0] = (unsigned long)op;
- if (mlock(op, sizeof(dom0_op_t)) < 0)
+ if (mlock(op, sizeof(dom0_op_t)) < 0) {
+ virXenError(VIR_ERR_XEN_CALL, " locking", sizeof(dom0_op_t));
return(-1);
+ }
cmd = _IOC(_IOC_NONE, 'P', 0, sizeof(hc));
ret = ioctl(handle, cmd, (unsigned long) &hc);
+ if (ret < 0) {
+ virXenError(VIR_ERR_XEN_CALL, " ioctl ", cmd);
+ }
- if (munlock(op, sizeof(dom0_op_t)) < 0)
+ if (munlock(op, sizeof(dom0_op_t)) < 0) {
+ virXenError(VIR_ERR_XEN_CALL, " releasing", sizeof(dom0_op_t));
ret = -1;
+ }
if (ret < 0)
return(-1);
cmd = _IOC(_IOC_NONE, 'P', 0, sizeof(hc));
ret = ioctl(handle, cmd, (unsigned long) &hc);
- if (ret < 0)
+ if (ret < 0) {
+ virXenError(VIR_ERR_XEN_CALL, " getting version ", XENVER_version);
return(0);
+ }
/*
* use unsigned long in case the version grows behind expectations
* allowed by int
memset(info, 0, sizeof(dom0_getdomaininfo_t));
- if (mlock(info, sizeof(dom0_getdomaininfo_t)) < 0)
+ if (mlock(info, sizeof(dom0_getdomaininfo_t)) < 0) {
+ virXenError(VIR_ERR_XEN_CALL, " locking", sizeof(dom0_getdomaininfo_t));
return(-1);
+ }
op.cmd = DOM0_GETDOMAININFOLIST;
op.u.getdomaininfolist.first_domain = (domid_t) domain;
ret = xenHypervisorDoOp(handle, &op);
- if (munlock(info, sizeof(dom0_getdomaininfo_t)) < 0)
+ if (munlock(info, sizeof(dom0_getdomaininfo_t)) < 0) {
+ virXenError(VIR_ERR_XEN_CALL, " release", sizeof(dom0_getdomaininfo_t));
ret = -1;
+ }
if (ret < 0)
return(-1);