2007-03-15 17:30:04 +00:00
|
|
|
/*
|
2012-12-04 12:04:07 +00:00
|
|
|
* virbuffer.c: buffers for libvirt
|
2007-03-15 17:30:04 +00:00
|
|
|
*
|
2015-03-13 15:41:42 +00:00
|
|
|
* Copyright (C) 2005-2008, 2010-2015 Red Hat, Inc.
|
2007-03-15 17:30:04 +00:00
|
|
|
*
|
2012-07-27 09:39:53 +00:00
|
|
|
* 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
|
2012-09-20 22:30:55 +00:00
|
|
|
* License along with this library. If not, see
|
2012-07-27 09:39:53 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2007-03-15 17:30:04 +00:00
|
|
|
*/
|
|
|
|
|
2008-01-29 18:15:54 +00:00
|
|
|
#include <config.h>
|
2007-12-05 21:40:15 +00:00
|
|
|
|
2007-03-15 17:30:04 +00:00
|
|
|
#include <stdarg.h>
|
2007-12-17 10:05:35 +00:00
|
|
|
|
2012-12-04 12:04:07 +00:00
|
|
|
#include "virbuffer.h"
|
2017-02-23 12:43:32 +00:00
|
|
|
#include "virstring.h"
|
2019-04-01 14:28:05 +00:00
|
|
|
#include "viralloc.h"
|
2007-03-15 17:30:04 +00:00
|
|
|
|
2018-07-24 15:52:04 +00:00
|
|
|
#define VIR_FROM_THIS VIR_FROM_NONE
|
2008-04-28 15:14:59 +00:00
|
|
|
|
2011-10-20 21:48:47 +00:00
|
|
|
/**
|
|
|
|
* virBufferAdjustIndent:
|
|
|
|
* @buf: the buffer
|
|
|
|
* @indent: adjustment to make
|
|
|
|
*
|
|
|
|
* Alter the auto-indent value by adding indent (positive to increase,
|
|
|
|
* negative to decrease). Automatic indentation is performed by all
|
|
|
|
* additive functions when the existing buffer is empty or ends with a
|
|
|
|
* newline (however, note that no indentation is added after newlines
|
2019-10-24 07:25:20 +00:00
|
|
|
* embedded in an appended string). If @indent would cause overflow, the
|
|
|
|
* indentation level is truncated.
|
2011-10-20 21:48:47 +00:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
virBufferAdjustIndent(virBufferPtr buf, int indent)
|
|
|
|
{
|
2019-10-24 12:09:42 +00:00
|
|
|
if (!buf)
|
2011-10-20 21:48:47 +00:00
|
|
|
return;
|
2019-10-24 06:06:21 +00:00
|
|
|
|
|
|
|
if (indent > 0) {
|
|
|
|
if (INT_MAX - indent < buf->indent) {
|
2019-10-24 07:25:20 +00:00
|
|
|
buf->indent = INT_MAX;
|
2019-10-24 06:06:21 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (buf->indent < -indent) {
|
2019-10-24 07:25:20 +00:00
|
|
|
buf->indent = 0;
|
2019-10-24 06:06:21 +00:00
|
|
|
return;
|
|
|
|
}
|
2011-10-20 21:48:47 +00:00
|
|
|
}
|
2019-10-24 06:06:21 +00:00
|
|
|
|
2011-10-20 21:48:47 +00:00
|
|
|
buf->indent += indent;
|
|
|
|
}
|
|
|
|
|
2017-03-09 16:02:19 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* virBufferSetIndent:
|
|
|
|
* @buf: the buffer
|
|
|
|
* @indent: new indentation size.
|
|
|
|
*
|
|
|
|
* Set the auto-indent value to @indent. See virBufferAdjustIndent on how auto
|
|
|
|
* indentation is applied.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
virBufferSetIndent(virBufferPtr buf, int indent)
|
|
|
|
{
|
2019-10-24 12:09:42 +00:00
|
|
|
if (!buf)
|
2017-03-09 16:02:19 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
buf->indent = indent;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-20 21:48:47 +00:00
|
|
|
/**
|
|
|
|
* virBufferGetIndent:
|
|
|
|
* @buf: the buffer
|
|
|
|
*
|
2019-10-24 10:51:24 +00:00
|
|
|
* Return the current auto-indent setting of @buf.
|
2011-10-20 21:48:47 +00:00
|
|
|
*/
|
2019-10-24 10:51:24 +00:00
|
|
|
size_t
|
|
|
|
virBufferGetIndent(const virBuffer *buf)
|
2011-10-20 21:48:47 +00:00
|
|
|
{
|
|
|
|
return buf->indent;
|
|
|
|
}
|
|
|
|
|
2019-10-24 10:29:12 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* virBufferGetEffectiveIndent:
|
|
|
|
* @buf: the buffer
|
|
|
|
*
|
|
|
|
* Returns the number of spaces that need to be appended to @buf to honour
|
|
|
|
* auto-indentation.
|
|
|
|
*/
|
|
|
|
size_t
|
|
|
|
virBufferGetEffectiveIndent(const virBuffer *buf)
|
|
|
|
{
|
2019-10-24 11:02:41 +00:00
|
|
|
if (buf->str && buf->str->len && buf->str->str[buf->str->len - 1] != '\n')
|
2019-10-24 10:29:12 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
return buf->indent;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-03-15 17:30:04 +00:00
|
|
|
/**
|
2019-10-24 11:02:41 +00:00
|
|
|
* virBufferInitialize
|
2012-12-19 22:00:13 +00:00
|
|
|
* @buf: the buffer
|
2007-03-15 17:30:04 +00:00
|
|
|
*
|
2019-10-24 11:02:41 +00:00
|
|
|
* Ensures that the internal GString container is allocated.
|
2007-03-15 17:30:04 +00:00
|
|
|
*/
|
2019-10-24 11:02:41 +00:00
|
|
|
static void
|
|
|
|
virBufferInitialize(virBufferPtr buf)
|
2007-03-15 17:30:04 +00:00
|
|
|
{
|
2019-10-24 11:02:41 +00:00
|
|
|
if (!buf->str)
|
|
|
|
buf->str = g_string_new(NULL);
|
|
|
|
}
|
2007-03-15 17:30:04 +00:00
|
|
|
|
2008-04-28 15:14:59 +00:00
|
|
|
|
2019-10-24 11:02:41 +00:00
|
|
|
static void
|
|
|
|
virBufferApplyIndent(virBufferPtr buf)
|
|
|
|
{
|
|
|
|
const char space[] = " ";
|
|
|
|
size_t spacesz = sizeof(space) - 1;
|
|
|
|
size_t toindent = virBufferGetEffectiveIndent(buf);
|
2007-03-15 17:30:04 +00:00
|
|
|
|
2019-10-24 11:02:41 +00:00
|
|
|
if (toindent == 0)
|
|
|
|
return;
|
2007-03-15 17:30:04 +00:00
|
|
|
|
2019-10-24 11:02:41 +00:00
|
|
|
while (toindent > spacesz) {
|
|
|
|
g_string_append_len(buf->str, space, spacesz);
|
|
|
|
toindent -= spacesz;
|
2008-04-28 15:14:59 +00:00
|
|
|
}
|
2019-10-24 11:02:41 +00:00
|
|
|
|
|
|
|
g_string_append_len(buf->str, space, toindent);
|
2007-03-15 17:30:04 +00:00
|
|
|
}
|
|
|
|
|
2019-10-24 11:02:41 +00:00
|
|
|
|
2007-03-15 17:30:04 +00:00
|
|
|
/**
|
2007-06-26 22:21:22 +00:00
|
|
|
* virBufferAdd:
|
2011-10-20 21:48:47 +00:00
|
|
|
* @buf: the buffer to append to
|
|
|
|
* @str: the string
|
|
|
|
* @len: the number of bytes to add, or -1
|
2007-03-15 17:30:04 +00:00
|
|
|
*
|
2011-10-20 21:48:47 +00:00
|
|
|
* Add a string range to an XML buffer. If @len == -1, the length of
|
|
|
|
* str is recomputed to the full string. Auto indentation may be applied.
|
2007-03-15 17:30:04 +00:00
|
|
|
*
|
|
|
|
*/
|
2008-04-28 15:14:59 +00:00
|
|
|
void
|
2011-09-27 19:50:03 +00:00
|
|
|
virBufferAdd(virBufferPtr buf, const char *str, int len)
|
2007-03-15 17:30:04 +00:00
|
|
|
{
|
2021-03-04 17:09:42 +00:00
|
|
|
if (!str || !buf)
|
2008-04-28 15:14:59 +00:00
|
|
|
return;
|
|
|
|
|
2019-10-24 11:02:41 +00:00
|
|
|
virBufferInitialize(buf);
|
|
|
|
virBufferApplyIndent(buf);
|
2011-10-20 21:48:47 +00:00
|
|
|
|
2007-03-15 17:30:04 +00:00
|
|
|
if (len < 0)
|
2019-10-24 11:02:41 +00:00
|
|
|
g_string_append(buf->str, str);
|
|
|
|
else
|
|
|
|
g_string_append_len(buf->str, str, len);
|
2007-03-15 17:30:04 +00:00
|
|
|
}
|
|
|
|
|
2015-02-19 09:56:58 +00:00
|
|
|
/**
|
|
|
|
* virBufferAddBuffer:
|
|
|
|
* @buf: the buffer to append to
|
|
|
|
* @toadd: the buffer to append
|
|
|
|
*
|
|
|
|
* Add a buffer into another buffer without need to go through:
|
|
|
|
* virBufferContentAndReset(), virBufferAdd(). Auto indentation
|
|
|
|
* is (intentionally) NOT applied!
|
|
|
|
*
|
2016-01-07 13:18:21 +00:00
|
|
|
* The @toadd virBuffer is consumed and cleared.
|
2015-02-19 09:56:58 +00:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
virBufferAddBuffer(virBufferPtr buf, virBufferPtr toadd)
|
|
|
|
{
|
2019-10-24 11:02:41 +00:00
|
|
|
if (!toadd || !toadd->str)
|
2015-02-19 09:56:58 +00:00
|
|
|
return;
|
|
|
|
|
2015-03-13 15:41:42 +00:00
|
|
|
if (!buf)
|
2019-10-24 06:10:18 +00:00
|
|
|
goto cleanup;
|
2015-03-13 15:41:42 +00:00
|
|
|
|
2019-10-24 11:02:41 +00:00
|
|
|
virBufferInitialize(buf);
|
|
|
|
g_string_append_len(buf->str, toadd->str->str, toadd->str->len);
|
2015-03-13 15:41:42 +00:00
|
|
|
|
2019-10-24 06:10:18 +00:00
|
|
|
cleanup:
|
2015-02-19 09:56:58 +00:00
|
|
|
virBufferFreeAndReset(toadd);
|
|
|
|
}
|
|
|
|
|
2007-12-17 10:05:35 +00:00
|
|
|
/**
|
|
|
|
* virBufferAddChar:
|
2011-09-27 19:50:03 +00:00
|
|
|
* @buf: the buffer to append to
|
2007-12-17 10:05:35 +00:00
|
|
|
* @c: the character to add
|
|
|
|
*
|
2011-10-20 21:48:47 +00:00
|
|
|
* Add a single character 'c' to a buffer. Auto indentation may be applied.
|
2007-12-17 10:05:35 +00:00
|
|
|
*
|
|
|
|
*/
|
2008-04-28 15:14:59 +00:00
|
|
|
void
|
2011-10-20 21:48:47 +00:00
|
|
|
virBufferAddChar(virBufferPtr buf, char c)
|
2007-12-17 10:05:35 +00:00
|
|
|
{
|
2011-10-20 21:48:47 +00:00
|
|
|
virBufferAdd(buf, &c, 1);
|
2007-12-17 10:05:35 +00:00
|
|
|
}
|
|
|
|
|
2012-06-08 19:50:23 +00:00
|
|
|
/**
|
|
|
|
* virBufferCurrentContent:
|
|
|
|
* @buf: Buffer
|
|
|
|
*
|
|
|
|
* Get the current content from the buffer. The content is only valid
|
|
|
|
* until the next operation on @buf, and an empty string is returned if
|
|
|
|
* no content is present yet.
|
|
|
|
*
|
|
|
|
* Returns the buffer content or NULL in case of error.
|
|
|
|
*/
|
|
|
|
const char *
|
|
|
|
virBufferCurrentContent(virBufferPtr buf)
|
|
|
|
{
|
2019-10-24 12:09:42 +00:00
|
|
|
if (!buf)
|
2012-06-08 19:50:23 +00:00
|
|
|
return NULL;
|
2019-10-24 11:02:41 +00:00
|
|
|
|
|
|
|
if (!buf->str ||
|
|
|
|
buf->str->len == 0)
|
|
|
|
return "";
|
|
|
|
|
|
|
|
return buf->str->str;
|
2012-06-08 19:50:23 +00:00
|
|
|
}
|
|
|
|
|
2007-06-29 13:23:13 +00:00
|
|
|
/**
|
2008-04-28 15:14:59 +00:00
|
|
|
* virBufferContentAndReset:
|
|
|
|
* @buf: Buffer
|
2007-06-29 13:23:13 +00:00
|
|
|
*
|
2008-04-28 15:14:59 +00:00
|
|
|
* Get the content from the buffer and free (only) the buffer structure.
|
|
|
|
* The caller owns the returned string & should free it when no longer
|
2012-06-08 19:50:23 +00:00
|
|
|
* required. The buffer object is reset to its initial state. This
|
|
|
|
* interface intentionally returns NULL instead of an empty string if
|
|
|
|
* there is no content.
|
2007-06-29 13:23:13 +00:00
|
|
|
*
|
2008-04-28 15:14:59 +00:00
|
|
|
* Returns the buffer content or NULL in case of error.
|
2007-06-29 13:23:13 +00:00
|
|
|
*/
|
2008-04-28 15:14:59 +00:00
|
|
|
char *
|
2011-09-27 19:50:03 +00:00
|
|
|
virBufferContentAndReset(virBufferPtr buf)
|
2007-03-15 17:30:04 +00:00
|
|
|
{
|
2019-10-24 11:02:41 +00:00
|
|
|
char *str = NULL;
|
2007-03-15 17:30:04 +00:00
|
|
|
|
2019-10-24 11:02:41 +00:00
|
|
|
if (!buf)
|
2007-03-15 17:30:04 +00:00
|
|
|
return NULL;
|
|
|
|
|
2019-10-24 11:02:41 +00:00
|
|
|
if (buf->str)
|
|
|
|
str = g_string_free(buf->str, false);
|
|
|
|
|
2008-04-28 15:14:59 +00:00
|
|
|
memset(buf, 0, sizeof(*buf));
|
|
|
|
return str;
|
2007-03-15 17:30:04 +00:00
|
|
|
}
|
|
|
|
|
2009-12-09 23:00:50 +00:00
|
|
|
/**
|
|
|
|
* virBufferFreeAndReset:
|
|
|
|
* @buf: the buffer to free and reset
|
|
|
|
*
|
|
|
|
* Frees the buffer content and resets the buffer structure.
|
|
|
|
*/
|
2011-09-27 19:50:03 +00:00
|
|
|
void virBufferFreeAndReset(virBufferPtr buf)
|
2009-12-09 23:00:50 +00:00
|
|
|
{
|
2019-10-24 11:02:41 +00:00
|
|
|
if (!buf)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (buf->str)
|
|
|
|
g_string_free(buf->str, true);
|
|
|
|
|
|
|
|
memset(buf, 0, sizeof(*buf));
|
2009-12-09 23:00:50 +00:00
|
|
|
}
|
|
|
|
|
2007-03-15 17:30:04 +00:00
|
|
|
/**
|
2008-04-28 15:14:59 +00:00
|
|
|
* virBufferUse:
|
|
|
|
* @buf: the usage of the string in the buffer
|
2007-03-15 17:30:04 +00:00
|
|
|
*
|
2008-04-28 15:14:59 +00:00
|
|
|
* Return the string usage in bytes
|
2007-03-15 17:30:04 +00:00
|
|
|
*/
|
2019-03-26 17:02:06 +00:00
|
|
|
size_t
|
maint: avoid 'const fooPtr' in several util files
'const fooPtr' is the same as 'foo * const' (the pointer won't
change, but it's contents can). But in general, if an interface
is trying to be const-correct, it should be using 'const foo *'
(the pointer is to data that can't be changed).
Fix up offenders in src/util outside of the virnet namespace.
Also, make a few virSocketAddr functions const-correct, for easier
conversions in future patches.
* src/util/virbuffer.h (virBufferError, virBufferUse)
(virBufferGetIndent): Use intended type.
* src/util/virmacaddr.h (virMacAddrCmp, virMacAddrCmpRaw)
(virMacAddrSet, virMcAddrFormat, virMacAddrIsUnicast)
(virMacAddrIsMulticast): Likewise.
* src/util/virebtables.h (ebtablesAddForwardAllowIn)
(ebtablesRemoveForwardAllowIn): Likewise.
* src/util/virsocketaddr.h (virSocketAddrSetIPv4Addr): Drop
incorrect const.
(virMacAddrGetRaw, virSocketAddrFormat, virSocketAddrFormatFull):
Make const-correct.
(virSocketAddrMask, virSocketAddrMaskByPrefix)
(virSocketAddrBroadcast, virSocketAddrBroadcastByPrefix)
(virSocketAddrGetNumNetmaskBits, virSocketAddrGetIpPrefix)
(virSocketAddrEqual, virSocketAddrIsPrivate)
(virSocketAddrIsWildcard): Use intended type.
* src/util/virbuffer.c (virBufferError, virBufferUse)
(virBufferGetIndent): Fix fallout.
* src/util/virmacaddr.c (virMacAddrCmp, virMacAddrCmpRaw)
(virMacAddrSet, virMcAddrFormat, virMacAddrIsUnicast)
(virMacAddrIsMulticast): Likewise.
* src/util/virebtables.c (ebtablesAddForwardAllowIn)
(ebtablesRemoveForwardAllowIn): Likewise.
* src/util/virsocketaddr.c (virSocketAddrMask, virMacAddrGetRaw)
(virSocketAddrMaskByPrefix, virSocketAddrBroadcast)
(virSocketAddrBroadcastByPrefix, virSocketAddrGetNumNetmaskBits)
(virSocketAddrGetIpPrefix, virSocketAddrEqual)
(virSocketAddrIsPrivate, virSocketAddrIsWildcard)
(virSocketAddrGetIPv4Addr, virSocketAddrGetIPv6Addr)
(virSocketAddrFormat, virSocketAddrFormatFull): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-10-05 15:51:55 +00:00
|
|
|
virBufferUse(const virBuffer *buf)
|
2007-03-15 17:30:04 +00:00
|
|
|
{
|
2019-10-24 11:02:41 +00:00
|
|
|
if (!buf || !buf->str)
|
2008-04-28 15:14:59 +00:00
|
|
|
return 0;
|
2007-03-15 17:30:04 +00:00
|
|
|
|
2019-10-24 11:02:41 +00:00
|
|
|
return buf->str->len;
|
2007-03-15 17:30:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2011-04-30 16:34:49 +00:00
|
|
|
* virBufferAsprintf:
|
2011-09-27 19:50:03 +00:00
|
|
|
* @buf: the buffer to append to
|
2012-12-19 22:00:13 +00:00
|
|
|
* @format: the format
|
|
|
|
* @...: the variable list of arguments
|
2007-03-15 17:30:04 +00:00
|
|
|
*
|
2011-10-20 21:48:47 +00:00
|
|
|
* Do a formatted print to an XML buffer. Auto indentation may be applied.
|
2007-03-15 17:30:04 +00:00
|
|
|
*/
|
2008-04-28 15:14:59 +00:00
|
|
|
void
|
2011-09-27 19:50:03 +00:00
|
|
|
virBufferAsprintf(virBufferPtr buf, const char *format, ...)
|
2007-03-15 17:30:04 +00:00
|
|
|
{
|
buf: Fix possible infinite loop in EscapeString, VSnprintf
The current code will go into an infinite loop if the printf generated
string is >= 1000, AND exactly 1 character smaller than the amount of free
space in the buffer. When this happens, we are dropped into the loop body,
but nothing will actually change, because count == (buf->size - buf->use - 1),
and virBufferGrow returns unchanged if count < (buf->size - buf->use)
Fix this by removing the '- 1' bit from 'size'. The *nprintf functions handle
the NULL byte for us anyways, so we shouldn't need to manually accommodate
for it.
Here's a bug where we are actually hitting this issue:
https://bugzilla.redhat.com/show_bug.cgi?id=602772
v2: Eric's improvements: while -> if (), remove extra va_list variable,
make sure we report buffer error if snprintf fails
v3: Add tests/virbuftest which reproduces the infinite loop before this
patch, works correctly after
2010-09-01 17:51:35 +00:00
|
|
|
va_list argptr;
|
2011-04-30 16:44:42 +00:00
|
|
|
va_start(argptr, format);
|
|
|
|
virBufferVasprintf(buf, format, argptr);
|
|
|
|
va_end(argptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virBufferVasprintf:
|
2011-10-20 21:48:47 +00:00
|
|
|
* @buf: the buffer to append to
|
2012-12-19 22:00:13 +00:00
|
|
|
* @format: the format
|
|
|
|
* @argptr: the variable list of arguments
|
2011-04-30 16:44:42 +00:00
|
|
|
*
|
2011-10-20 21:48:47 +00:00
|
|
|
* Do a formatted print to an XML buffer. Auto indentation may be applied.
|
2011-04-30 16:44:42 +00:00
|
|
|
*/
|
|
|
|
void
|
2011-09-27 19:50:03 +00:00
|
|
|
virBufferVasprintf(virBufferPtr buf, const char *format, va_list argptr)
|
2011-04-30 16:44:42 +00:00
|
|
|
{
|
2008-04-28 15:14:59 +00:00
|
|
|
if ((format == NULL) || (buf == NULL))
|
|
|
|
return;
|
|
|
|
|
2019-10-24 11:02:41 +00:00
|
|
|
virBufferInitialize(buf);
|
|
|
|
virBufferApplyIndent(buf);
|
2011-10-20 21:48:47 +00:00
|
|
|
|
2019-10-24 11:02:41 +00:00
|
|
|
g_string_append_vprintf(buf->str, format, argptr);
|
2007-03-15 17:30:04 +00:00
|
|
|
}
|
|
|
|
|
2016-04-10 16:21:13 +00:00
|
|
|
|
2007-07-09 11:24:52 +00:00
|
|
|
/**
|
|
|
|
* virBufferEscapeString:
|
2011-09-27 19:50:03 +00:00
|
|
|
* @buf: the buffer to append to
|
2007-07-09 11:24:52 +00:00
|
|
|
* @format: a printf like format string but with only one %s parameter
|
2011-10-20 21:48:47 +00:00
|
|
|
* @str: the string argument which needs to be escaped
|
2007-07-09 11:24:52 +00:00
|
|
|
*
|
2011-10-20 21:48:47 +00:00
|
|
|
* Do a formatted print with a single string to an XML buffer. The
|
|
|
|
* string is escaped for use in XML. If @str is NULL, nothing is
|
|
|
|
* added (not even the rest of @format). Auto indentation may be
|
|
|
|
* applied.
|
2007-07-09 11:24:52 +00:00
|
|
|
*/
|
2008-04-28 15:14:59 +00:00
|
|
|
void
|
2011-09-27 19:50:03 +00:00
|
|
|
virBufferEscapeString(virBufferPtr buf, const char *format, const char *str)
|
2007-07-09 11:24:52 +00:00
|
|
|
{
|
2010-11-22 17:04:45 +00:00
|
|
|
int len;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *escaped = NULL;
|
2018-07-24 15:52:05 +00:00
|
|
|
char *out;
|
2007-07-09 11:24:52 +00:00
|
|
|
const char *cur;
|
2015-03-30 10:41:40 +00:00
|
|
|
const char forbidden_characters[] = {
|
|
|
|
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
|
|
|
|
/*\t*/ /*\n*/ 0x0B, 0x0C, /*\r*/ 0x0E, 0x0F, 0x10,
|
|
|
|
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
|
|
|
|
0x19, '"', '&', '\'', '<', '>',
|
|
|
|
'\0'
|
|
|
|
};
|
2007-07-09 11:24:52 +00:00
|
|
|
|
2008-04-28 15:14:59 +00:00
|
|
|
if ((format == NULL) || (buf == NULL) || (str == NULL))
|
|
|
|
return;
|
|
|
|
|
2007-07-09 11:24:52 +00:00
|
|
|
len = strlen(str);
|
2015-03-30 10:41:40 +00:00
|
|
|
if (strcspn(str, forbidden_characters) == len) {
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(buf, format, str);
|
2010-11-22 17:04:45 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-10-24 06:49:57 +00:00
|
|
|
escaped = g_malloc0_n(len + 1, 6);
|
2008-04-28 15:14:59 +00:00
|
|
|
|
2007-07-09 11:24:52 +00:00
|
|
|
cur = str;
|
|
|
|
out = escaped;
|
|
|
|
while (*cur != 0) {
|
|
|
|
if (*cur == '<') {
|
2008-04-10 16:54:54 +00:00
|
|
|
*out++ = '&';
|
|
|
|
*out++ = 'l';
|
|
|
|
*out++ = 't';
|
|
|
|
*out++ = ';';
|
|
|
|
} else if (*cur == '>') {
|
|
|
|
*out++ = '&';
|
|
|
|
*out++ = 'g';
|
|
|
|
*out++ = 't';
|
|
|
|
*out++ = ';';
|
|
|
|
} else if (*cur == '&') {
|
|
|
|
*out++ = '&';
|
|
|
|
*out++ = 'a';
|
|
|
|
*out++ = 'm';
|
|
|
|
*out++ = 'p';
|
|
|
|
*out++ = ';';
|
2009-05-13 16:19:59 +00:00
|
|
|
} else if (*cur == '"') {
|
|
|
|
*out++ = '&';
|
|
|
|
*out++ = 'q';
|
|
|
|
*out++ = 'u';
|
|
|
|
*out++ = 'o';
|
|
|
|
*out++ = 't';
|
|
|
|
*out++ = ';';
|
|
|
|
} else if (*cur == '\'') {
|
|
|
|
*out++ = '&';
|
|
|
|
*out++ = 'a';
|
|
|
|
*out++ = 'p';
|
|
|
|
*out++ = 'o';
|
|
|
|
*out++ = 's';
|
|
|
|
*out++ = ';';
|
2015-03-30 10:41:40 +00:00
|
|
|
} else if (!strchr(forbidden_characters, *cur)) {
|
2008-04-10 16:54:54 +00:00
|
|
|
/*
|
|
|
|
* default case, just copy !
|
|
|
|
* Note that character over 0x80 are likely to give problem
|
|
|
|
* with UTF-8 XML, but since our string don't have an encoding
|
|
|
|
* it's hard to handle properly we have to assume it's UTF-8 too
|
|
|
|
*/
|
|
|
|
*out++ = *cur;
|
2015-03-30 10:41:40 +00:00
|
|
|
} else {
|
|
|
|
/* silently ignore control characters */
|
2008-04-10 16:54:54 +00:00
|
|
|
}
|
|
|
|
cur++;
|
2007-07-09 11:24:52 +00:00
|
|
|
}
|
|
|
|
*out = 0;
|
|
|
|
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(buf, format, escaped);
|
2007-07-09 11:24:52 +00:00
|
|
|
}
|
|
|
|
|
2010-11-19 15:51:57 +00:00
|
|
|
/**
|
|
|
|
* virBufferEscapeSexpr:
|
2011-09-27 19:50:03 +00:00
|
|
|
* @buf: the buffer to append to
|
2010-11-19 15:51:57 +00:00
|
|
|
* @format: a printf like format string but with only one %s parameter
|
2011-10-20 21:48:47 +00:00
|
|
|
* @str: the string argument which needs to be escaped
|
2010-11-19 15:51:57 +00:00
|
|
|
*
|
2011-10-20 21:48:47 +00:00
|
|
|
* Do a formatted print with a single string to an sexpr buffer. The
|
|
|
|
* string is escaped to avoid generating a sexpr that xen will choke
|
|
|
|
* on. This doesn't fully escape the sexpr, just enough for our code
|
|
|
|
* to work. Auto indentation may be applied.
|
2010-11-19 15:51:57 +00:00
|
|
|
*/
|
|
|
|
void
|
2011-09-27 19:50:03 +00:00
|
|
|
virBufferEscapeSexpr(virBufferPtr buf,
|
2010-11-19 15:51:57 +00:00
|
|
|
const char *format,
|
|
|
|
const char *str)
|
2011-09-20 04:13:42 +00:00
|
|
|
{
|
2012-03-09 19:13:30 +00:00
|
|
|
virBufferEscape(buf, '\\', "\\'", format, str);
|
2017-05-12 12:26:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virBufferEscapeRegex:
|
|
|
|
* @buf: the buffer to append to
|
|
|
|
* @format: a printf like format string but with only one %s parameter
|
|
|
|
* @str: the string argument which needs to be escaped
|
|
|
|
*
|
|
|
|
* Do a formatted print with a single string to a buffer. The @str is
|
|
|
|
* escaped to avoid using POSIX extended regular expression meta-characters.
|
|
|
|
* Escaping is not applied to characters specified in @format. Auto
|
|
|
|
* indentation may be applied.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
virBufferEscapeRegex(virBufferPtr buf,
|
|
|
|
const char *format,
|
|
|
|
const char *str)
|
|
|
|
{
|
|
|
|
virBufferEscape(buf, '\\', "^$.|?*+()[]{}\\", format, str);
|
2011-09-20 04:13:42 +00:00
|
|
|
}
|
|
|
|
|
2017-10-06 06:47:34 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* virBufferEscapeSQL:
|
|
|
|
* @buf: the buffer to append to
|
|
|
|
* @format: a printf like format string but with only one %s parameter
|
|
|
|
* @str: the string argument which needs to be escaped
|
|
|
|
*
|
|
|
|
* Do a formatted print with a single string to a buffer. The @str is
|
|
|
|
* escaped to prevent SQL injection (format is expected to contain \"%s\").
|
|
|
|
* Auto indentation may be applied.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
virBufferEscapeSQL(virBufferPtr buf,
|
|
|
|
const char *format,
|
|
|
|
const char *str)
|
|
|
|
{
|
|
|
|
virBufferEscape(buf, '\\', "'\"\\", format, str);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-09-20 04:13:42 +00:00
|
|
|
/**
|
|
|
|
* virBufferEscape:
|
2011-09-27 19:50:03 +00:00
|
|
|
* @buf: the buffer to append to
|
2012-03-09 19:13:30 +00:00
|
|
|
* @escape: the escape character to inject
|
2011-09-27 19:50:03 +00:00
|
|
|
* @toescape: NUL-terminated list of characters to escape
|
2011-09-20 04:13:42 +00:00
|
|
|
* @format: a printf like format string but with only one %s parameter
|
2011-09-27 19:50:03 +00:00
|
|
|
* @str: the string argument which needs to be escaped
|
2011-09-20 04:13:42 +00:00
|
|
|
*
|
|
|
|
* Do a formatted print with a single string to a buffer. Any characters
|
2014-11-11 16:23:49 +00:00
|
|
|
* in the provided list that are contained in @str are escaped with the
|
|
|
|
* given escape. Escaping is not applied to characters specified in @format.
|
|
|
|
* Auto indentation may be applied.
|
2011-09-20 04:13:42 +00:00
|
|
|
*/
|
|
|
|
void
|
2012-03-09 19:13:30 +00:00
|
|
|
virBufferEscape(virBufferPtr buf, char escape, const char *toescape,
|
2011-09-27 19:50:03 +00:00
|
|
|
const char *format, const char *str)
|
2010-11-19 15:51:57 +00:00
|
|
|
{
|
|
|
|
int len;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *escaped = NULL;
|
2018-07-24 15:52:05 +00:00
|
|
|
char *out;
|
2010-11-19 15:51:57 +00:00
|
|
|
const char *cur;
|
|
|
|
|
|
|
|
if ((format == NULL) || (buf == NULL) || (str == NULL))
|
|
|
|
return;
|
|
|
|
|
|
|
|
len = strlen(str);
|
2011-09-20 04:13:42 +00:00
|
|
|
if (strcspn(str, toescape) == len) {
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(buf, format, str);
|
2010-11-19 15:51:57 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-10-24 06:49:57 +00:00
|
|
|
escaped = g_malloc0_n(len + 1, 2);
|
2010-11-19 15:51:57 +00:00
|
|
|
|
|
|
|
cur = str;
|
|
|
|
out = escaped;
|
|
|
|
while (*cur != 0) {
|
2012-12-19 19:28:48 +00:00
|
|
|
if (strchr(toescape, *cur))
|
2012-03-09 19:13:30 +00:00
|
|
|
*out++ = escape;
|
2011-09-20 04:13:42 +00:00
|
|
|
*out++ = *cur;
|
2010-11-19 15:51:57 +00:00
|
|
|
cur++;
|
|
|
|
}
|
|
|
|
*out = 0;
|
|
|
|
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(buf, format, escaped);
|
2010-11-19 15:51:57 +00:00
|
|
|
}
|
|
|
|
|
2017-02-23 12:43:32 +00:00
|
|
|
|
2007-12-17 10:05:35 +00:00
|
|
|
/**
|
|
|
|
* virBufferURIEncodeString:
|
2011-09-27 19:50:03 +00:00
|
|
|
* @buf: the buffer to append to
|
2012-12-19 22:00:13 +00:00
|
|
|
* @str: the string argument which will be URI-encoded
|
2007-12-17 10:05:35 +00:00
|
|
|
*
|
|
|
|
* Append the string to the buffer. The string will be URI-encoded
|
2020-10-02 14:07:27 +00:00
|
|
|
* during the append (ie any non alphanumeric characters are replaced
|
2011-10-20 21:48:47 +00:00
|
|
|
* with '%xx' hex sequences). Auto indentation may be applied.
|
2007-12-17 10:05:35 +00:00
|
|
|
*/
|
2008-04-28 15:14:59 +00:00
|
|
|
void
|
2011-09-27 19:50:03 +00:00
|
|
|
virBufferURIEncodeString(virBufferPtr buf, const char *str)
|
2007-12-17 10:05:35 +00:00
|
|
|
{
|
2008-04-28 15:14:59 +00:00
|
|
|
if ((buf == NULL) || (str == NULL))
|
|
|
|
return;
|
|
|
|
|
2019-10-24 11:02:41 +00:00
|
|
|
virBufferInitialize(buf);
|
|
|
|
virBufferApplyIndent(buf);
|
2007-12-17 10:05:35 +00:00
|
|
|
|
2019-10-24 11:02:41 +00:00
|
|
|
g_string_append_uri_escaped(buf->str, str, NULL, false);
|
2007-12-17 10:05:35 +00:00
|
|
|
}
|
|
|
|
|
2011-07-28 13:25:00 +00:00
|
|
|
/**
|
|
|
|
* virBufferEscapeShell:
|
2011-10-20 21:48:47 +00:00
|
|
|
* @buf: the buffer to append to
|
|
|
|
* @str: an unquoted string
|
2011-07-28 13:25:00 +00:00
|
|
|
*
|
|
|
|
* Quotes a string so that the shell (/bin/sh) will interpret the
|
2011-10-20 21:48:47 +00:00
|
|
|
* quoted string to mean str. Auto indentation may be applied.
|
2011-07-28 13:25:00 +00:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
virBufferEscapeShell(virBufferPtr buf, const char *str)
|
|
|
|
{
|
|
|
|
int len;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *escaped = NULL;
|
2018-07-24 15:52:05 +00:00
|
|
|
char *out;
|
2011-07-28 13:25:00 +00:00
|
|
|
const char *cur;
|
|
|
|
|
|
|
|
if ((buf == NULL) || (str == NULL))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Only quote if str includes shell metacharacters. */
|
2011-10-13 21:48:40 +00:00
|
|
|
if (*str && !strpbrk(str, "\r\t\n !\"#$&'()*;<>?[\\]^`{|}~")) {
|
2011-07-28 13:25:00 +00:00
|
|
|
virBufferAdd(buf, str, -1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-10-13 21:48:40 +00:00
|
|
|
if (*str) {
|
|
|
|
len = strlen(str);
|
2019-10-24 06:49:57 +00:00
|
|
|
|
|
|
|
escaped = g_malloc0_n(len + 1, 4);
|
2011-10-13 21:48:40 +00:00
|
|
|
} else {
|
2011-10-19 08:44:08 +00:00
|
|
|
virBufferAddLit(buf, "''");
|
2011-07-28 13:25:00 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
cur = str;
|
|
|
|
out = escaped;
|
|
|
|
|
|
|
|
*out++ = '\'';
|
|
|
|
while (*cur != 0) {
|
|
|
|
if (*cur == '\'') {
|
2011-10-18 07:07:41 +00:00
|
|
|
*out++ = '\'';
|
2011-07-28 13:25:00 +00:00
|
|
|
/* Replace literal ' with a close ', a \', and a open ' */
|
|
|
|
*out++ = '\\';
|
|
|
|
*out++ = '\'';
|
|
|
|
}
|
2011-10-18 07:07:41 +00:00
|
|
|
*out++ = *cur++;
|
2011-07-28 13:25:00 +00:00
|
|
|
}
|
|
|
|
*out++ = '\'';
|
|
|
|
*out = 0;
|
|
|
|
|
|
|
|
virBufferAdd(buf, escaped, -1);
|
|
|
|
}
|
|
|
|
|
2017-07-24 16:54:15 +00:00
|
|
|
/**
|
|
|
|
* virBufferStrcatVArgs:
|
|
|
|
* @buf: the buffer to append to
|
|
|
|
* @ap: variable argument structure
|
|
|
|
*
|
|
|
|
* See virBufferStrcat.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
virBufferStrcatVArgs(virBufferPtr buf,
|
|
|
|
va_list ap)
|
|
|
|
{
|
|
|
|
char *str;
|
|
|
|
|
|
|
|
while ((str = va_arg(ap, char *)) != NULL)
|
|
|
|
virBufferAdd(buf, str, -1);
|
|
|
|
}
|
|
|
|
|
2007-03-15 17:30:04 +00:00
|
|
|
/**
|
2007-06-26 22:21:22 +00:00
|
|
|
* virBufferStrcat:
|
2011-09-27 19:50:03 +00:00
|
|
|
* @buf: the buffer to append to
|
2012-12-19 22:00:13 +00:00
|
|
|
* @...: the variable list of strings, the last argument must be NULL
|
2007-03-15 17:30:04 +00:00
|
|
|
*
|
2011-10-20 21:48:47 +00:00
|
|
|
* Concatenate strings to an XML buffer. Auto indentation may be applied
|
|
|
|
* after each string argument.
|
2007-03-15 17:30:04 +00:00
|
|
|
*/
|
2008-04-28 15:14:59 +00:00
|
|
|
void
|
2007-06-26 22:21:22 +00:00
|
|
|
virBufferStrcat(virBufferPtr buf, ...)
|
2007-03-15 17:30:04 +00:00
|
|
|
{
|
|
|
|
va_list ap;
|
2008-04-28 15:14:59 +00:00
|
|
|
|
2018-03-22 12:10:40 +00:00
|
|
|
if (!buf)
|
|
|
|
return;
|
|
|
|
|
2007-03-15 17:30:04 +00:00
|
|
|
va_start(ap, buf);
|
2017-07-24 16:54:15 +00:00
|
|
|
virBufferStrcatVArgs(buf, ap);
|
2007-03-15 17:30:04 +00:00
|
|
|
va_end(ap);
|
|
|
|
}
|
virBuffer: add way to trim back extra text
I'm tired of writing:
bool sep = false;
while (...) {
if (sep)
virBufferAddChar(buf, ',');
sep = true;
virBufferAdd(buf, str);
}
This makes it easier, allowing one to write:
while (...)
virBufferAsprintf(buf, "%s,", str);
virBufferTrim(buf, ",", -1);
to trim any remaining comma.
* src/util/buf.h (virBufferTrim): Declare.
* src/util/buf.c (virBufferTrim): New function.
* tests/virbuftest.c (testBufTrim): Test it.
2012-05-18 22:36:59 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* virBufferTrim:
|
|
|
|
* @buf: the buffer to trim
|
2020-02-02 19:26:38 +00:00
|
|
|
* @str: the string to be trimmed from the tail
|
virBuffer: add way to trim back extra text
I'm tired of writing:
bool sep = false;
while (...) {
if (sep)
virBufferAddChar(buf, ',');
sep = true;
virBufferAdd(buf, str);
}
This makes it easier, allowing one to write:
while (...)
virBufferAsprintf(buf, "%s,", str);
virBufferTrim(buf, ",", -1);
to trim any remaining comma.
* src/util/buf.h (virBufferTrim): Declare.
* src/util/buf.c (virBufferTrim): New function.
* tests/virbuftest.c (testBufTrim): Test it.
2012-05-18 22:36:59 +00:00
|
|
|
*
|
2020-02-02 19:26:38 +00:00
|
|
|
* Trim the supplied string from the tail of the buffer.
|
virBuffer: add way to trim back extra text
I'm tired of writing:
bool sep = false;
while (...) {
if (sep)
virBufferAddChar(buf, ',');
sep = true;
virBufferAdd(buf, str);
}
This makes it easier, allowing one to write:
while (...)
virBufferAsprintf(buf, "%s,", str);
virBufferTrim(buf, ",", -1);
to trim any remaining comma.
* src/util/buf.h (virBufferTrim): Declare.
* src/util/buf.c (virBufferTrim): New function.
* tests/virbuftest.c (testBufTrim): Test it.
2012-05-18 22:36:59 +00:00
|
|
|
*/
|
2013-06-18 15:52:00 +00:00
|
|
|
void
|
2020-02-02 19:26:38 +00:00
|
|
|
virBufferTrim(virBufferPtr buf, const char *str)
|
virBuffer: add way to trim back extra text
I'm tired of writing:
bool sep = false;
while (...) {
if (sep)
virBufferAddChar(buf, ',');
sep = true;
virBufferAdd(buf, str);
}
This makes it easier, allowing one to write:
while (...)
virBufferAsprintf(buf, "%s,", str);
virBufferTrim(buf, ",", -1);
to trim any remaining comma.
* src/util/buf.h (virBufferTrim): Declare.
* src/util/buf.c (virBufferTrim): New function.
* tests/virbuftest.c (testBufTrim): Test it.
2012-05-18 22:36:59 +00:00
|
|
|
{
|
2020-02-02 19:26:38 +00:00
|
|
|
size_t len = 0;
|
virBuffer: add way to trim back extra text
I'm tired of writing:
bool sep = false;
while (...) {
if (sep)
virBufferAddChar(buf, ',');
sep = true;
virBufferAdd(buf, str);
}
This makes it easier, allowing one to write:
while (...)
virBufferAsprintf(buf, "%s,", str);
virBufferTrim(buf, ",", -1);
to trim any remaining comma.
* src/util/buf.h (virBufferTrim): Declare.
* src/util/buf.c (virBufferTrim): New function.
* tests/virbuftest.c (testBufTrim): Test it.
2012-05-18 22:36:59 +00:00
|
|
|
|
2019-10-24 12:09:42 +00:00
|
|
|
if (!buf || !buf->str)
|
2013-06-18 15:52:00 +00:00
|
|
|
return;
|
2019-10-24 11:02:41 +00:00
|
|
|
|
2020-02-02 19:26:38 +00:00
|
|
|
if (!str)
|
2013-06-18 15:52:00 +00:00
|
|
|
return;
|
virBuffer: add way to trim back extra text
I'm tired of writing:
bool sep = false;
while (...) {
if (sep)
virBufferAddChar(buf, ',');
sep = true;
virBufferAdd(buf, str);
}
This makes it easier, allowing one to write:
while (...)
virBufferAsprintf(buf, "%s,", str);
virBufferTrim(buf, ",", -1);
to trim any remaining comma.
* src/util/buf.h (virBufferTrim): Declare.
* src/util/buf.c (virBufferTrim): New function.
* tests/virbuftest.c (testBufTrim): Test it.
2012-05-18 22:36:59 +00:00
|
|
|
|
2020-02-02 19:26:38 +00:00
|
|
|
len = strlen(str);
|
2019-10-24 11:02:41 +00:00
|
|
|
|
2020-02-02 19:26:38 +00:00
|
|
|
if (len > buf->str->len ||
|
|
|
|
memcmp(&buf->str->str[buf->str->len - len], str, len) != 0)
|
2013-06-18 15:52:00 +00:00
|
|
|
return;
|
2019-10-24 11:02:41 +00:00
|
|
|
|
|
|
|
g_string_truncate(buf->str, buf->str->len - len);
|
virBuffer: add way to trim back extra text
I'm tired of writing:
bool sep = false;
while (...) {
if (sep)
virBufferAddChar(buf, ',');
sep = true;
virBufferAdd(buf, str);
}
This makes it easier, allowing one to write:
while (...)
virBufferAsprintf(buf, "%s,", str);
virBufferTrim(buf, ",", -1);
to trim any remaining comma.
* src/util/buf.h (virBufferTrim): Declare.
* src/util/buf.c (virBufferTrim): New function.
* tests/virbuftest.c (testBufTrim): Test it.
2012-05-18 22:36:59 +00:00
|
|
|
}
|
2015-03-24 09:53:29 +00:00
|
|
|
|
2020-01-14 07:04:14 +00:00
|
|
|
/**
|
|
|
|
* virBufferTrimChars:
|
|
|
|
* @buf: the buffer to trim
|
|
|
|
* @trim: the characters to be trimmed
|
|
|
|
*
|
|
|
|
* Trim the tail of the buffer. The longest string that can be formed with
|
|
|
|
* the characters from @trim is trimmed.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
virBufferTrimChars(virBufferPtr buf, const char *trim)
|
|
|
|
{
|
|
|
|
ssize_t i;
|
|
|
|
|
|
|
|
if (!buf || !buf->str)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!trim)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (i = buf->str->len - 1; i > 0; i--) {
|
|
|
|
if (!strchr(trim, buf->str->str[i]))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_string_truncate(buf->str, i + 1);
|
|
|
|
}
|
2015-03-24 09:53:29 +00:00
|
|
|
|
2020-02-02 19:16:36 +00:00
|
|
|
/**
|
|
|
|
* virBufferTrimLen:
|
|
|
|
* @buf: the buffer to trim
|
|
|
|
* @len: the number of bytes to trim
|
|
|
|
*
|
|
|
|
* Trim the tail of a buffer.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
virBufferTrimLen(virBufferPtr buf, int len)
|
|
|
|
{
|
|
|
|
if (!buf || !buf->str)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (len > buf->str->len)
|
|
|
|
return;
|
|
|
|
|
|
|
|
g_string_truncate(buf->str, buf->str->len - len);
|
|
|
|
}
|
|
|
|
|
2015-03-24 09:53:29 +00:00
|
|
|
/**
|
|
|
|
* virBufferAddStr:
|
|
|
|
* @buf: the buffer to append to
|
|
|
|
* @str: string to append
|
|
|
|
*
|
|
|
|
* Appends @str to @buffer. Applies autoindentation on the separate lines of
|
|
|
|
* @str.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
virBufferAddStr(virBufferPtr buf,
|
|
|
|
const char *str)
|
|
|
|
{
|
|
|
|
const char *end;
|
|
|
|
|
2019-10-24 12:09:42 +00:00
|
|
|
if (!buf || !str)
|
2015-03-24 09:53:29 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
while (*str) {
|
|
|
|
if ((end = strchr(str, '\n'))) {
|
|
|
|
virBufferAdd(buf, str, (end - str) + 1);
|
|
|
|
str = end + 1;
|
|
|
|
} else {
|
|
|
|
virBufferAdd(buf, str, -1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|