mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-04 21:47:16 +03:00
Use virBufferPtr for sexpr2string instead of manual buffer handling
Removes 4kb stack allocation in the XenD subdriver.
This commit is contained in:
parent
9faf3d084c
commit
9e3550dc4e
142
src/util/sexpr.c
142
src/util/sexpr.c
@ -199,78 +199,56 @@ sexpr_append(struct sexpr *lst, const struct sexpr *value)
|
|||||||
* sexpr2string:
|
* sexpr2string:
|
||||||
* @sexpr: an S-Expression pointer
|
* @sexpr: an S-Expression pointer
|
||||||
* @buffer: the output buffer
|
* @buffer: the output buffer
|
||||||
* @n_buffer: the size of the buffer in bytes
|
|
||||||
*
|
*
|
||||||
* Serialize the S-Expression in the buffer.
|
* Serialize the S-Expression in the buffer.
|
||||||
* Note that the output may be truncated if @n_buffer is too small
|
|
||||||
* resulting in an unparseable value.
|
|
||||||
*
|
*
|
||||||
* Returns the number of bytes used by the serialization in the buffer or
|
* Returns 0 on success, -1 on error.
|
||||||
* 0 in case of error.
|
|
||||||
*/
|
*/
|
||||||
size_t
|
int
|
||||||
sexpr2string(const struct sexpr * sexpr, char *buffer, size_t n_buffer)
|
sexpr2string(const struct sexpr *sexpr, virBufferPtr buffer)
|
||||||
{
|
{
|
||||||
size_t ret = 0, tmp;
|
if ((sexpr == NULL) || (buffer == NULL))
|
||||||
|
return -1;
|
||||||
if ((sexpr == NULL) || (buffer == NULL) || (n_buffer <= 0))
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
switch (sexpr->kind) {
|
switch (sexpr->kind) {
|
||||||
case SEXPR_CONS:
|
case SEXPR_CONS:
|
||||||
tmp = snprintf(buffer + ret, n_buffer - ret, "(");
|
virBufferAddChar(buffer, '(');
|
||||||
if (tmp == 0)
|
|
||||||
goto error;
|
if (sexpr2string(sexpr->u.s.car, buffer) < 0)
|
||||||
ret += tmp;
|
|
||||||
tmp = sexpr2string(sexpr->u.s.car, buffer + ret, n_buffer - ret);
|
|
||||||
if (tmp == 0)
|
|
||||||
goto error;
|
|
||||||
ret += tmp;
|
|
||||||
while (sexpr->u.s.cdr->kind != SEXPR_NIL) {
|
|
||||||
sexpr = sexpr->u.s.cdr;
|
|
||||||
tmp = snprintf(buffer + ret, n_buffer - ret, " ");
|
|
||||||
if (tmp == 0)
|
|
||||||
goto error;
|
|
||||||
ret += tmp;
|
|
||||||
tmp =
|
|
||||||
sexpr2string(sexpr->u.s.car, buffer + ret, n_buffer - ret);
|
|
||||||
if (tmp == 0)
|
|
||||||
goto error;
|
|
||||||
ret += tmp;
|
|
||||||
}
|
|
||||||
tmp = snprintf(buffer + ret, n_buffer - ret, ")");
|
|
||||||
if (tmp == 0)
|
|
||||||
goto error;
|
|
||||||
ret += tmp;
|
|
||||||
break;
|
|
||||||
case SEXPR_VALUE:
|
|
||||||
if (strchr(sexpr->u.value, ' ') ||
|
|
||||||
strchr(sexpr->u.value, ')') ||
|
|
||||||
strchr(sexpr->u.value, '('))
|
|
||||||
tmp = snprintf(buffer + ret, n_buffer - ret, "'%s'",
|
|
||||||
sexpr->u.value);
|
|
||||||
else
|
|
||||||
tmp = snprintf(buffer + ret, n_buffer - ret, "%s",
|
|
||||||
sexpr->u.value);
|
|
||||||
if (tmp == 0)
|
|
||||||
goto error;
|
|
||||||
ret += tmp;
|
|
||||||
break;
|
|
||||||
case SEXPR_NIL:
|
|
||||||
tmp = snprintf(buffer + ret, n_buffer - ret, "()");
|
|
||||||
if (tmp == 0)
|
|
||||||
goto error;
|
|
||||||
ret += tmp;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
while (sexpr->u.s.cdr->kind != SEXPR_NIL) {
|
||||||
|
sexpr = sexpr->u.s.cdr;
|
||||||
|
|
||||||
|
virBufferAddChar(buffer, ' ');
|
||||||
|
|
||||||
|
if (sexpr2string(sexpr->u.s.car, buffer) < 0)
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
virBufferAddChar(buffer, ')');
|
||||||
|
break;
|
||||||
|
case SEXPR_VALUE:
|
||||||
|
if (strchr(sexpr->u.value, ' ') ||
|
||||||
|
strchr(sexpr->u.value, ')') ||
|
||||||
|
strchr(sexpr->u.value, '('))
|
||||||
|
virBufferVSprintf(buffer, "'%s'", sexpr->u.value);
|
||||||
|
else
|
||||||
|
virBufferVSprintf(buffer, "%s", sexpr->u.value);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case SEXPR_NIL:
|
||||||
|
virBufferAddLit(buffer, "()");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ret);
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
buffer[n_buffer - 1] = 0;
|
virSexprError(VIR_ERR_SEXPR_SERIAL, NULL);
|
||||||
virSexprError(VIR_ERR_SEXPR_SERIAL, "%s", buffer);
|
return -1;
|
||||||
return (0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define IS_SPACE(c) ((c == 0x20) || (c == 0x9) || (c == 0xD) || (c == 0xA))
|
#define IS_SPACE(c) ((c == 0x20) || (c == 0x9) || (c == 0xD) || (c == 0xA))
|
||||||
@ -413,22 +391,28 @@ string2sexpr(const char *buffer)
|
|||||||
static struct sexpr *
|
static struct sexpr *
|
||||||
sexpr_lookup_key(const struct sexpr *sexpr, const char *node)
|
sexpr_lookup_key(const struct sexpr *sexpr, const char *node)
|
||||||
{
|
{
|
||||||
char buffer[4096], *ptr, *token;
|
struct sexpr *result = NULL;
|
||||||
|
char *buffer, *ptr, *token;
|
||||||
|
|
||||||
if ((node == NULL) || (sexpr == NULL))
|
if ((node == NULL) || (sexpr == NULL))
|
||||||
return (NULL);
|
return NULL;
|
||||||
|
|
||||||
snprintf(buffer, sizeof(buffer), "%s", node);
|
buffer = strdup(node);
|
||||||
|
|
||||||
|
if (buffer == NULL) {
|
||||||
|
virReportOOMError();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
ptr = buffer;
|
ptr = buffer;
|
||||||
token = strsep(&ptr, "/");
|
token = strsep(&ptr, "/");
|
||||||
|
|
||||||
if (sexpr->kind != SEXPR_CONS || sexpr->u.s.car->kind != SEXPR_VALUE) {
|
if (sexpr->kind != SEXPR_CONS || sexpr->u.s.car->kind != SEXPR_VALUE) {
|
||||||
return NULL;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (STRNEQ(sexpr->u.s.car->u.value, token)) {
|
if (STRNEQ(sexpr->u.s.car->u.value, token)) {
|
||||||
return NULL;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (token = strsep(&ptr, "/"); token; token = strsep(&ptr, "/")) {
|
for (token = strsep(&ptr, "/"); token; token = strsep(&ptr, "/")) {
|
||||||
@ -454,10 +438,15 @@ sexpr_lookup_key(const struct sexpr *sexpr, const char *node)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (token != NULL) {
|
if (token != NULL) {
|
||||||
return NULL;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (struct sexpr *) sexpr;
|
result = (struct sexpr *) sexpr;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(buffer);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -550,21 +539,30 @@ int sexpr_node_copy(const struct sexpr *sexpr, const char *node, char **dst)
|
|||||||
* @... extra data to build the path
|
* @... extra data to build the path
|
||||||
*
|
*
|
||||||
* Search a node value in the S-Expression based on its path
|
* Search a node value in the S-Expression based on its path
|
||||||
* NOTE: path are limited to 4096 bytes.
|
|
||||||
*
|
*
|
||||||
* Returns the value of the node or NULL if not found.
|
* Returns the value of the node or NULL if not found.
|
||||||
*/
|
*/
|
||||||
const char *
|
const char *
|
||||||
sexpr_fmt_node(const struct sexpr *sexpr, const char *fmt, ...)
|
sexpr_fmt_node(const struct sexpr *sexpr, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
|
int result;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
char node[4096];
|
char *node;
|
||||||
|
const char *value;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
vsnprintf(node, sizeof(node), fmt, ap);
|
result = virVasprintf(&node, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
return sexpr_node(sexpr, node);
|
if (result < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = sexpr_node(sexpr, node);
|
||||||
|
|
||||||
|
VIR_FREE(node);
|
||||||
|
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
# define _LIBVIR_SEXPR_H_
|
# define _LIBVIR_SEXPR_H_
|
||||||
|
|
||||||
# include "internal.h"
|
# include "internal.h"
|
||||||
|
# include "buf.h"
|
||||||
|
|
||||||
# include <sys/types.h>
|
# include <sys/types.h>
|
||||||
# include <stdint.h>
|
# include <stdint.h>
|
||||||
@ -36,7 +37,7 @@ struct sexpr {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* conversion to/from strings */
|
/* conversion to/from strings */
|
||||||
size_t sexpr2string(const struct sexpr *sexpr, char *buffer, size_t n_buffer);
|
int sexpr2string(const struct sexpr *sexpr, virBufferPtr buffer);
|
||||||
struct sexpr *string2sexpr(const char *buffer);
|
struct sexpr *string2sexpr(const char *buffer);
|
||||||
|
|
||||||
/* constructors and destructors */
|
/* constructors and destructors */
|
||||||
|
@ -3023,7 +3023,8 @@ xenDaemonDomainSetAutostart(virDomainPtr domain,
|
|||||||
int autostart)
|
int autostart)
|
||||||
{
|
{
|
||||||
struct sexpr *root, *autonode;
|
struct sexpr *root, *autonode;
|
||||||
char buf[4096];
|
virBuffer buffer = VIR_BUFFER_INITIALIZER;
|
||||||
|
char *content = NULL;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
xenUnifiedPrivatePtr priv;
|
xenUnifiedPrivatePtr priv;
|
||||||
|
|
||||||
@ -3065,12 +3066,20 @@ xenDaemonDomainSetAutostart(virDomainPtr domain,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sexpr2string(root, buf, sizeof(buf)) == 0) {
|
if (sexpr2string(root, &buffer) < 0) {
|
||||||
virXendError(VIR_ERR_INTERNAL_ERROR,
|
virXendError(VIR_ERR_INTERNAL_ERROR,
|
||||||
"%s", _("sexpr2string failed"));
|
"%s", _("sexpr2string failed"));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (xend_op(domain->conn, "", "op", "new", "config", buf, NULL) != 0) {
|
|
||||||
|
if (virBufferError(&buffer)) {
|
||||||
|
virReportOOMError();
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
content = virBufferContentAndReset(&buffer);
|
||||||
|
|
||||||
|
if (xend_op(domain->conn, "", "op", "new", "config", content, NULL) != 0) {
|
||||||
virXendError(VIR_ERR_XEN_CALL,
|
virXendError(VIR_ERR_XEN_CALL,
|
||||||
"%s", _("Failed to redefine sexpr"));
|
"%s", _("Failed to redefine sexpr"));
|
||||||
goto error;
|
goto error;
|
||||||
@ -3083,6 +3092,8 @@ xenDaemonDomainSetAutostart(virDomainPtr domain,
|
|||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
error:
|
error:
|
||||||
|
virBufferFreeAndReset(&buffer);
|
||||||
|
VIR_FREE(content);
|
||||||
sexpr_free(root);
|
sexpr_free(root);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user