From 058d89b9df8c769a78fd23678919f84920b866dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A1n=20Tomko?= Date: Fri, 27 Jun 2014 09:23:13 +0200 Subject: [PATCH] Introduce virBufferCheckError Check if the buffer is in error state and report an error if it is. This replaces the pattern: if (virBufferError(buf)) { virReportOOMError(); goto cleanup; } with: if (virBufferCheckError(buf) < 0) goto cleanup; Document typical buffer usage to favor this. Also remove the redundant FreeAndReset - if an error has been set via virBufferSetError, the content is already freed. --- HACKING | 7 ++----- docs/hacking.html.in | 7 ++----- po/POTFILES.in | 1 + src/libvirt_private.syms | 1 + src/util/virbuffer.c | 31 +++++++++++++++++++++++++++++++ src/util/virbuffer.h | 17 +++++++++++++++++ 6 files changed, 54 insertions(+), 10 deletions(-) diff --git a/HACKING b/HACKING index ac3e9d7f97..0745d5f337 100644 --- a/HACKING +++ b/HACKING @@ -776,7 +776,7 @@ Variable length string buffer ============================= If there is a need for complex string concatenations, avoid using the usual sequence of malloc/strcpy/strcat/snprintf functions and make use of the -virBuffer API described in buf.h +virBuffer API described in virbuffer.h Typical usage is as follows: @@ -794,11 +794,8 @@ Typical usage is as follows: ... - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); + if (virBufferCheckError(&buf) < 0) return NULL; - } return virBufferContentAndReset(&buf); } diff --git a/docs/hacking.html.in b/docs/hacking.html.in index 9c6dd26820..9456520d46 100644 --- a/docs/hacking.html.in +++ b/docs/hacking.html.in @@ -948,7 +948,7 @@

If there is a need for complex string concatenations, avoid using the usual sequence of malloc/strcpy/strcat/snprintf functions and - make use of the virBuffer API described in buf.h + make use of the virBuffer API described in virbuffer.h

Typical usage is as follows:

@@ -968,11 +968,8 @@ ... - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); + if (virBufferCheckError(&buf) < 0) return NULL; - } return virBufferContentAndReset(&buf); } diff --git a/po/POTFILES.in b/po/POTFILES.in index 31a8381748..d338151cae 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -156,6 +156,7 @@ src/util/viraudit.c src/util/virauth.c src/util/virauthconfig.c src/util/virbitmap.c +src/util/virbuffer.c src/util/vircgroup.c src/util/virclosecallbacks.c src/util/vircommand.c diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index ed56103a17..cc5fd325af 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1008,6 +1008,7 @@ virBufferAdd; virBufferAddChar; virBufferAdjustIndent; virBufferAsprintf; +virBufferCheckErrorInternal; virBufferContentAndReset; virBufferCurrentContent; virBufferError; diff --git a/src/util/virbuffer.c b/src/util/virbuffer.c index eb29012ec8..025f0ab7d2 100644 --- a/src/util/virbuffer.c +++ b/src/util/virbuffer.c @@ -32,6 +32,7 @@ #include "virbuffer.h" #include "viralloc.h" +#include "virerror.h" /* If adding more fields, ensure to edit buf.h to match @@ -263,6 +264,36 @@ virBufferError(const virBuffer *buf) return buf->error; } +/** + * virBufferCheckErrorInternal: + * @buf: the buffer + * + * Report an error if the buffer is in an error state. + * + * Return -1 if an error has been reported, 0 otherwise. + */ +int +virBufferCheckErrorInternal(const virBuffer *buf, + int domcode, + const char *filename, + const char *funcname, + size_t linenr) +{ + if (buf->error == 0) + return 0; + + if (buf->error == ENOMEM) { + virReportOOMErrorFull(domcode, filename, funcname, linenr); + errno = ENOMEM; + } else { + virReportErrorHelper(domcode, VIR_ERR_INTERNAL_ERROR, filename, + funcname, linenr, "%s", + _("Invalid buffer API usage")); + errno = EINVAL; + } + return -1; +} + /** * virBufferUse: * @buf: the usage of the string in the buffer diff --git a/src/util/virbuffer.h b/src/util/virbuffer.h index a0cc4e6777..bdfff5e817 100644 --- a/src/util/virbuffer.h +++ b/src/util/virbuffer.h @@ -53,6 +53,23 @@ const char *virBufferCurrentContent(virBufferPtr buf); char *virBufferContentAndReset(virBufferPtr buf); void virBufferFreeAndReset(virBufferPtr buf); int virBufferError(const virBuffer *buf); +int virBufferCheckErrorInternal(const virBuffer *buf, + int domcode, + const char *filename, + const char *funcname, + size_t linenr) + ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NONNULL(1); +/** + * virBufferCheckError + * + * Checks if the buffer is in error state and reports an error. + * + * Returns 0 if no error has occured, otherwise an error is reported + * and -1 is returned. + */ +# define virBufferCheckError(buf) \ + virBufferCheckErrorInternal(buf, VIR_FROM_THIS, __FILE__, __FUNCTION__, \ + __LINE__) unsigned int virBufferUse(const virBuffer *buf); void virBufferAdd(virBufferPtr buf, const char *str, int len); void virBufferAddChar(virBufferPtr buf, char c);