/** * virBufferVasprintf: * @buf: the buffer to append to * @format: the format * @argptr: the variable list of arguments * * Do a formatted print to an XML buffer. Auto indentation may be applied. */ void virBufferVasprintf(virBufferPtr buf, const char *format, va_list argptr) { int size, count, grow_size; va_list copy; if ((format == NULL) || (buf == NULL)) return; if (buf->error) return; virBufferAddLit(buf, ""); /* auto-indent */ if (buf->size == 0 && virBufferGrow(buf, 100) < 0) return; va_copy(copy, argptr); size = buf->size - buf->use; if ((count = vsnprintf(&buf->content[buf->use], size, format, copy)) < 0) { virBufferSetError(buf, errno); va_end(copy); return; } va_end(copy); /* Grow buffer if necessary and retry */ if (count >= size) { buf->content[buf->use] = 0; grow_size = (count + 1 > 1000) ? count + 1 : 1000; if (virBufferGrow(buf, grow_size) < 0) { return; } size = buf->size - buf->use; if ((count = vsnprintf(&buf->content[buf->use], size, format, argptr)) < 0) { virBufferSetError(buf, errno); return; } } buf->use += count; }
/** * 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 * embedded in an appended string). If @indent would cause overflow, * the buffer error indicator is set. */ void virBufferAdjustIndent(virBufferPtr buf, int indent) { if (!buf || buf->error) return; if (indent > 0 ? INT_MAX - indent < buf->indent : buf->indent < -indent) { virBufferSetError(buf, -1); return; } buf->indent += indent; }
/** * virBufferEscapeShell: * @buf: the buffer to append to * @str: an unquoted string * * Quotes a string so that the shell (/bin/sh) will interpret the * quoted string to mean str. Auto indentation may be applied. */ void virBufferEscapeShell(virBufferPtr buf, const char *str) { int len; char *escaped, *out; const char *cur; if ((buf == NULL) || (str == NULL)) return; if (buf->error) return; /* Only quote if str includes shell metacharacters. */ if (*str && !strpbrk(str, "\r\t\n !\"#$&'()*;<>?[\\]^`{|}~")) { virBufferAdd(buf, str, -1); return; } if (*str) { len = strlen(str); if (xalloc_oversized(4, len) || VIR_ALLOC_N_QUIET(escaped, 4 * len + 3) < 0) { virBufferSetError(buf, errno); return; } } else { virBufferAddLit(buf, "''"); return; } cur = str; out = escaped; *out++ = '\''; while (*cur != 0) { if (*cur == '\'') { *out++ = '\''; /* Replace literal ' with a close ', a \', and a open ' */ *out++ = '\\'; *out++ = '\''; } *out++ = *cur++; } *out++ = '\''; *out = 0; virBufferAdd(buf, escaped, -1); VIR_FREE(escaped); }
/** * virBufferEscape: * @buf: the buffer to append to * @escape: the escape character to inject * @toescape: NUL-terminated list of characters to escape * @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. Any characters * in the provided list are escaped with the given escape. Auto indentation * may be applied. */ void virBufferEscape(virBufferPtr buf, char escape, const char *toescape, const char *format, const char *str) { int len; char *escaped, *out; const char *cur; if ((format == NULL) || (buf == NULL) || (str == NULL)) return; if (buf->error) return; len = strlen(str); if (strcspn(str, toescape) == len) { virBufferAsprintf(buf, format, str); return; } if (xalloc_oversized(2, len) || VIR_ALLOC_N(escaped, 2 * len + 1) < 0) { virBufferSetError(buf, errno); return; } cur = str; out = escaped; while (*cur != 0) { /* strchr work-around for gcc 4.3 & 4.4 bug with -Wlogical-op * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36513 */ char needle[2] = { *cur, 0 }; if (strstr(toescape, needle)) *out++ = escape; *out++ = *cur; cur++; } *out = 0; virBufferAsprintf(buf, format, escaped); VIR_FREE(escaped); }
/** * virBufferGrow: * @buf: the buffer * @len: the minimum free size to allocate on top of existing used space * * Grow the available space of a buffer to at least @len bytes. * * Returns zero on success or -1 on error */ static int virBufferGrow(virBufferPtr buf, unsigned int len) { int size; if (buf->error) return -1; if ((len + buf->use) < buf->size) return 0; size = buf->use + len + 1000; if (VIR_REALLOC_N_QUIET(buf->content, size) < 0) { virBufferSetError(buf, errno); return -1; } buf->size = size; return 0; }
/** * virBufferEscape: * @buf: the buffer to append to * @escape: the escape character to inject * @toescape: NUL-terminated list of characters to escape * @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. Any characters * 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. */ void virBufferEscape(virBufferPtr buf, char escape, const char *toescape, const char *format, const char *str) { int len; char *escaped, *out; const char *cur; if ((format == NULL) || (buf == NULL) || (str == NULL)) return; if (buf->error) return; len = strlen(str); if (strcspn(str, toescape) == len) { virBufferAsprintf(buf, format, str); return; } if (xalloc_oversized(2, len) || VIR_ALLOC_N_QUIET(escaped, 2 * len + 1) < 0) { virBufferSetError(buf, errno); return; } cur = str; out = escaped; while (*cur != 0) { if (strchr(toescape, *cur)) *out++ = escape; *out++ = *cur; cur++; } *out = 0; virBufferAsprintf(buf, format, escaped); VIR_FREE(escaped); }
/** * virBufferTrim: * @buf: the buffer to trim * @str: the optional string, to force an exact trim * @len: the number of bytes to trim, or -1 to use @str * * Trim the tail of a buffer. If @str is provided, the trim only occurs * if the current tail of the buffer matches @str; a non-negative @len * further limits how much of the tail is trimmed. If @str is NULL, then * @len must be non-negative. * * Sets error to -1 (usage) if str is NULL and len is less than zero. */ void virBufferTrim(virBufferPtr buf, const char *str, int len) { size_t len2 = 0; if (!buf || buf->error) return; if (!str && len < 0) { virBufferSetError(buf, -1); return; } if (len > 0 && len > buf->use) return; if (str) { len2 = strlen(str); if (len2 > buf->use || memcmp(&buf->content[buf->use - len2], str, len2) != 0) return; } buf->use -= len < 0 ? len2 : len; buf->content[buf->use] = '\0'; }
/** * virBufferEscapeString: * @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 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. */ void virBufferEscapeString(virBufferPtr buf, const char *format, const char *str) { int len; char *escaped, *out; const char *cur; 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' }; if ((format == NULL) || (buf == NULL) || (str == NULL)) return; if (buf->error) return; len = strlen(str); if (strcspn(str, forbidden_characters) == len) { virBufferAsprintf(buf, format, str); return; } if (xalloc_oversized(6, len) || VIR_ALLOC_N_QUIET(escaped, 6 * len + 1) < 0) { virBufferSetError(buf, errno); return; } cur = str; out = escaped; while (*cur != 0) { if (*cur == '<') { *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++ = ';'; } 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++ = ';'; } else if (!strchr(forbidden_characters, *cur)) { /* * 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; } else { /* silently ignore control characters */ } cur++; } *out = 0; virBufferAsprintf(buf, format, escaped); VIR_FREE(escaped); }
/** * virBufferEscapeString: * @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 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. */ void virBufferEscapeString(virBufferPtr buf, const char *format, const char *str) { int len; char *escaped, *out; const char *cur; if ((format == NULL) || (buf == NULL) || (str == NULL)) return; if (buf->error) return; len = strlen(str); if (strcspn(str, "<>&'\"") == len) { virBufferAsprintf(buf, format, str); return; } if (xalloc_oversized(6, len) || VIR_ALLOC_N(escaped, 6 * len + 1) < 0) { virBufferSetError(buf, errno); return; } cur = str; out = escaped; while (*cur != 0) { if (*cur == '<') { *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++ = ';'; } 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++ = ';'; } else if (((unsigned char)*cur >= 0x20) || (*cur == '\n') || (*cur == '\t') || (*cur == '\r')) { /* * 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; } cur++; } *out = 0; virBufferAsprintf(buf, format, escaped); VIR_FREE(escaped); }