From: Daniel Veillard Date: Mon, 27 Feb 2006 21:34:28 +0000 (+0000) Subject: * include/virterror.h src/libvirt_sym.version: exported X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=87d338374a6d9cda0bbb1039de3ef2e972d7e6cc;p=libvirt.git * 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. Daniel --- diff --git a/ChangeLog b/ChangeLog index e900a14a3f..e97ae328d1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +Mon Feb 27 16:32:55 EST 2006 Daniel Veillard + + * 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 * include/virterror.h src/virterror.c src/xend_internal.c: more work diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index a81bb83a7f..a5c9050233 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -86,6 +86,9 @@ typedef enum { 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; /** @@ -111,6 +114,7 @@ virErrorPtr virConnGetLastError (virConnectPtr conn); void virConnResetLastError (virConnectPtr conn); int virCopyLastError (virErrorPtr to); +void virDefaultErrorFunc (virErrorPtr err); void virSetErrorFunc (void *userData, virErrorFunc handler); void virConnSetErrorFunc (virConnectPtr conn, diff --git a/include/virterror.h b/include/virterror.h index a81bb83a7f..a5c9050233 100644 --- a/include/virterror.h +++ b/include/virterror.h @@ -86,6 +86,9 @@ typedef enum { 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; /** @@ -111,6 +114,7 @@ virErrorPtr virConnGetLastError (virConnectPtr conn); void virConnResetLastError (virConnectPtr conn); int virCopyLastError (virErrorPtr to); +void virDefaultErrorFunc (virErrorPtr err); void virSetErrorFunc (void *userData, virErrorFunc handler); void virConnSetErrorFunc (virConnectPtr conn, diff --git a/src/libvirt_sym.version b/src/libvirt_sym.version index e8c507d915..85e2694b11 100644 --- a/src/libvirt_sym.version +++ b/src/libvirt_sym.version @@ -37,5 +37,6 @@ virSetErrorFunc; virConnCopyLastError; virConnResetLastError; + virDefaultErrorFunc; local: *; }; diff --git a/src/sexpr.c b/src/sexpr.c index e04639bd71..105ed3ec5c 100644 --- a/src/sexpr.c +++ b/src/sexpr.c @@ -13,6 +13,7 @@ #define _GNU_SOURCE #include "sexpr.h" +#include "internal.h" #include #include @@ -20,6 +21,26 @@ #include #include +/** + * 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: * @@ -34,6 +55,7 @@ sexpr_new(void) 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; @@ -203,26 +225,26 @@ sexpr2string(struct sexpr * sexpr, char *buffer, size_t n_buffer) 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: @@ -233,16 +255,20 @@ sexpr2string(struct sexpr * sexpr, char *buffer, size_t n_buffer) 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)) @@ -319,6 +345,9 @@ _string2sexpr(const char *buffer, size_t * end) } ret->value = strndup(start, ptr - start); + if (ret->value == NULL) { + virSexprError(VIR_ERR_NO_MEMORY, "failed to copy a string"); + } if (*ptr == '\'') ptr++; @@ -330,14 +359,23 @@ _string2sexpr(const char *buffer, size_t * end) } 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); } /** diff --git a/src/virsh.c b/src/virsh.c index 523126e51b..faeb4d7e52 100644 --- a/src/virsh.c +++ b/src/virsh.c @@ -14,6 +14,7 @@ #define _GNU_SOURCE /* isblank() */ #include "libvirt.h" +#include "virterror.h" #include #include #include @@ -56,6 +57,21 @@ typedef enum { 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: * @@ -1485,6 +1501,9 @@ vshInit(vshControl *ctl) { ctl->uid = getuid(); + /* set up the library error handler */ + virSetErrorFunc(NULL, virshErrorHandler); + /* basic connection to hypervisor */ if (ctl->uid == 0) ctl->conn = virConnectOpen(NULL); diff --git a/src/virterror.c b/src/virterror.c index f385cc3368..5d24201aae 100644 --- a/src/virterror.c +++ b/src/virterror.c @@ -212,13 +212,13 @@ virConnSetErrorFunc(virConnectPtr conn, void *userData, virErrorFunc handler) { } /** - * 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; @@ -337,7 +337,7 @@ __virRaiseError(virConnectPtr conn, virDomainPtr dom, if (handler != NULL) { handler(userData, to); } else { - virReportError(to); + virDefaultErrorFunc(to); } } @@ -407,7 +407,22 @@ __virErrorMsg(virErrorNumber error, const char *info) { 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); diff --git a/src/xen_internal.c b/src/xen_internal.c index 67260b2054..f04c3674a5 100644 --- a/src/xen_internal.c +++ b/src/xen_internal.c @@ -36,6 +36,27 @@ typedef struct hypercall_struct #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: * @@ -47,8 +68,10 @@ int xenHypervisorOpen(void) { 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); } @@ -92,14 +115,21 @@ xenHypervisorDoOp(int handle, dom0_op_t *op) { 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); @@ -128,8 +158,10 @@ xenHypervisorGetVersion(int handle) { 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 @@ -157,8 +189,10 @@ xenHypervisorGetDomainInfo(int handle, int domain, dom0_getdomaininfo_t *info) { 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; @@ -169,8 +203,10 @@ xenHypervisorGetDomainInfo(int handle, int domain, dom0_getdomaininfo_t *info) { 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);