mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 17:34:18 +03:00
* docs/libvir.html: grammatical fix
* src/Makefile.am src/sexpr.c src/sexpr.h: starting to integrate Anthony Liquori libxend code * src/libvir.c: fix an uninitialized value Daniel
This commit is contained in:
parent
2b019dd2f7
commit
f18b6c0ec6
@ -1,3 +1,10 @@
|
||||
Wed Jan 11 14:57:01 CET 2006 Daniel Veillard <veillard@redhat.com>
|
||||
|
||||
* docs/libvir.html: grammatical fix
|
||||
* src/Makefile.am src/sexpr.c src/sexpr.h: starting to integrate
|
||||
Anthony Liquori libxend code
|
||||
* src/libvir.c: fix an uninitialized value
|
||||
|
||||
Wed Dec 21 17:58:45 CET 2005 Daniel Veillard <veillard@redhat.com>
|
||||
|
||||
* docs/architecture.* docs/*: added a section on the architecture
|
||||
|
@ -46,7 +46,7 @@ progresses.</p>
|
||||
|
||||
<h2><a name="architecture">libvir architecture</a></h2>
|
||||
|
||||
<p>In a Xen environment, program using libvir have to execute in "Domain 0",
|
||||
<p>In a Xen environment, programs using libvir have to execute in "Domain 0",
|
||||
which is the primary Linux OS loaded on the machine. That OS kernel provides
|
||||
most if not all of the actual drivers used by the set of domains. It also
|
||||
runs the Xen Store, a database of informations shared by the hypervisor, the
|
||||
|
@ -15,7 +15,8 @@ libvir_la_SOURCES = \
|
||||
libvir.c internal.h \
|
||||
hash.c hash.h \
|
||||
xen_internal.c xen_internal.h \
|
||||
xml.c
|
||||
xml.c \
|
||||
sexpr.c sexpr.h
|
||||
|
||||
bin_PROGRAMS=virsh
|
||||
|
||||
|
@ -642,7 +642,7 @@ virDomainLookupByName(virConnectPtr conn, const char *name) {
|
||||
struct xs_transaction_handle* t;
|
||||
virDomainPtr ret = NULL;
|
||||
unsigned int num, i, len;
|
||||
long id;
|
||||
long id = -1;
|
||||
char **idlist = NULL, *endptr;
|
||||
char prop[200], *tmp;
|
||||
int found = 0;
|
||||
|
446
src/sexpr.c
Normal file
446
src/sexpr.c
Normal file
@ -0,0 +1,446 @@
|
||||
/*
|
||||
* sexpr.c : S-Expression routines to communicate with the Xen Daemon
|
||||
*
|
||||
* Copyright (C) 2005
|
||||
*
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser General
|
||||
* Public License. See the file COPYING.LIB in the main directory of this
|
||||
* archive for more details.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "sexpr.h"
|
||||
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
|
||||
/**
|
||||
* sexpr_new:
|
||||
*
|
||||
* Create a new S-Expression
|
||||
*
|
||||
* Returns the new node or NULL in case of memory allocation error
|
||||
*/
|
||||
static struct sexpr *
|
||||
sexpr_new(void)
|
||||
{
|
||||
struct sexpr *ret;
|
||||
|
||||
ret = (struct sexpr *) malloc(sizeof(*ret));
|
||||
if (ret == NULL) {
|
||||
return(NULL);
|
||||
}
|
||||
ret->kind = SEXPR_NIL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* sexpr_free:
|
||||
* @sexpr: the S-Expression pointer
|
||||
*
|
||||
* Free an S-Expression
|
||||
*/
|
||||
void
|
||||
sexpr_free(struct sexpr *sexpr)
|
||||
{
|
||||
int serrno = errno;
|
||||
|
||||
if (sexpr == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (sexpr->kind) {
|
||||
case SEXPR_CONS:
|
||||
sexpr_free(sexpr->car);
|
||||
sexpr_free(sexpr->cdr);
|
||||
break;
|
||||
case SEXPR_VALUE:
|
||||
free(sexpr->value);
|
||||
break;
|
||||
case SEXPR_NIL:
|
||||
break;
|
||||
}
|
||||
|
||||
free(sexpr);
|
||||
|
||||
errno = serrno;
|
||||
}
|
||||
|
||||
/**
|
||||
* sexpr_nil:
|
||||
*
|
||||
* Provide a NIL S-Expression (the pointer is not shared so NIL equality
|
||||
* testing won't work at the pointer level).
|
||||
*
|
||||
* Returns a new NIL S-Expression of NULL in case of error.
|
||||
*/
|
||||
struct sexpr *
|
||||
sexpr_nil(void)
|
||||
{
|
||||
return sexpr_new();
|
||||
}
|
||||
|
||||
/**
|
||||
* sexpr_string:
|
||||
* @str: the input string, assumed to be UTF-8
|
||||
* @len: the length in bytes of the input
|
||||
*
|
||||
* Parse the input S-Expression and return a pointer to the result
|
||||
*
|
||||
* Returns the S-Expression pointer or NULL in case of error
|
||||
*/
|
||||
struct sexpr *
|
||||
sexpr_string(const char *str, ssize_t len)
|
||||
{
|
||||
struct sexpr *ret = sexpr_new();
|
||||
|
||||
if (ret == NULL)
|
||||
return ret;
|
||||
ret->kind = SEXPR_VALUE;
|
||||
if (len > 0) {
|
||||
ret->value = strndup(str, len);
|
||||
} else {
|
||||
ret->value = strdup(str);
|
||||
}
|
||||
|
||||
if (ret->value == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* sexpr_cons:
|
||||
* @car: the left operand
|
||||
* @cdr: the right operand
|
||||
*
|
||||
* Implement the CONS operation assembling 2 existing S-Expressions.
|
||||
* Note that in case of error the input data are not freed.
|
||||
*
|
||||
* Returns the resulting S-Expression pointer or NULL in case of error.
|
||||
*/
|
||||
struct sexpr *
|
||||
sexpr_cons(struct sexpr *car, struct sexpr *cdr)
|
||||
{
|
||||
struct sexpr *ret = sexpr_new();
|
||||
|
||||
if (ret == NULL)
|
||||
return ret;
|
||||
ret->kind = SEXPR_CONS;
|
||||
ret->car = car;
|
||||
ret->cdr = cdr;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* append:
|
||||
* @lst: an existing list
|
||||
* @value: the value
|
||||
*
|
||||
* Internal operation appending a value at the end of an existing list
|
||||
*/
|
||||
static void
|
||||
append(struct sexpr *lst, struct sexpr *value)
|
||||
{
|
||||
while (lst->kind != SEXPR_NIL) {
|
||||
lst = lst->cdr;
|
||||
}
|
||||
|
||||
lst->kind = SEXPR_CONS;
|
||||
lst->car = value;
|
||||
lst->cdr = sexpr_nil();
|
||||
}
|
||||
|
||||
/**
|
||||
* @lst: an existing list
|
||||
* @value: the value
|
||||
*
|
||||
* Append a value at the end of an existing list
|
||||
*
|
||||
* Returns lst or NULL in case of error
|
||||
*/
|
||||
struct sexpr *
|
||||
sexpr_append(struct sexpr *lst, struct sexpr *value)
|
||||
{
|
||||
if (lst == NULL)
|
||||
return(NULL);
|
||||
if (value == NULL)
|
||||
return(lst);
|
||||
append(lst, value);
|
||||
return(lst);
|
||||
}
|
||||
|
||||
/**
|
||||
* sexpr2string:
|
||||
* @sexpr: an S-Expression pointer
|
||||
* @buffer: the output buffer
|
||||
* @n_buffer: the size of the buffer in bytes
|
||||
*
|
||||
* 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
|
||||
* 0 in case of error.
|
||||
*/
|
||||
size_t
|
||||
sexpr2string(struct sexpr * sexpr, char *buffer, size_t n_buffer)
|
||||
{
|
||||
size_t ret = 0, tmp;
|
||||
|
||||
if ((sexpr == NULL) || (buffer == NULL) || (n_buffer <= 0))
|
||||
return(0);
|
||||
|
||||
switch (sexpr->kind) {
|
||||
case SEXPR_CONS:
|
||||
tmp = snprintf(buffer + ret, n_buffer - ret, "(");
|
||||
if (tmp == 0)
|
||||
return(0);
|
||||
ret += tmp;
|
||||
tmp = sexpr2string(sexpr->car, buffer + ret, n_buffer - ret);
|
||||
if (tmp == 0)
|
||||
return(0);
|
||||
ret += tmp;
|
||||
while (sexpr->cdr->kind != SEXPR_NIL) {
|
||||
sexpr = sexpr->cdr;
|
||||
tmp = snprintf(buffer + ret, n_buffer - ret, " ");
|
||||
if (tmp == 0)
|
||||
return(0);
|
||||
ret += tmp;
|
||||
tmp = sexpr2string(sexpr->car, buffer + ret, n_buffer - ret);
|
||||
if (tmp == 0)
|
||||
return(0);
|
||||
ret += tmp;
|
||||
}
|
||||
tmp = snprintf(buffer + ret, n_buffer - ret, ")");
|
||||
if (tmp == 0)
|
||||
return(0);
|
||||
ret += tmp;
|
||||
break;
|
||||
case SEXPR_VALUE:
|
||||
if (strchr(sexpr->value, ' '))
|
||||
tmp = snprintf(buffer + ret, n_buffer - ret, "'%s'",
|
||||
sexpr->value);
|
||||
else
|
||||
tmp = snprintf(buffer + ret, n_buffer - ret, "%s",
|
||||
sexpr->value);
|
||||
if (tmp == 0)
|
||||
return(0);
|
||||
ret += tmp;
|
||||
break;
|
||||
case SEXPR_NIL:
|
||||
break;
|
||||
default:
|
||||
return(0);
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
#define IS_SPACE(c) ((c == 0x20) || (c == 0x9) || (c == 0xD) || (c == 0xA))
|
||||
|
||||
static const char *
|
||||
trim(const char *string)
|
||||
{
|
||||
while (IS_SPACE(*string))
|
||||
string++;
|
||||
return(string);
|
||||
}
|
||||
|
||||
/**
|
||||
* _string2sexpr:
|
||||
* @buffer: a zero terminated buffer containing an S-Expression in UTF-8
|
||||
* @end: pointer to an index in the buffer for the already parsed bytes
|
||||
*
|
||||
* Internal routine implementing the parse of S-Expression
|
||||
* Note that failure in this function is catrosphic. If it returns
|
||||
* NULL, you've leaked memory and you're currently OOM. It will always
|
||||
* parse an SEXPR given a buffer
|
||||
*
|
||||
* Returns a pointer to the resulting parsed S-Expression, or NULL in case of
|
||||
* hard error.
|
||||
*/
|
||||
static struct sexpr *
|
||||
_string2sexpr(const char *buffer, size_t * end)
|
||||
{
|
||||
const char *ptr = buffer + *end;
|
||||
struct sexpr *ret = sexpr_new();
|
||||
|
||||
if (ret == NULL)
|
||||
return NULL;
|
||||
|
||||
ptr = trim(ptr);
|
||||
|
||||
if (ptr[0] == '(') {
|
||||
ret->kind = SEXPR_NIL;
|
||||
|
||||
ptr = trim(ptr + 1);
|
||||
while (*ptr && *ptr != ')') {
|
||||
struct sexpr *tmp;
|
||||
size_t tmp_len = 0;
|
||||
|
||||
tmp = _string2sexpr(ptr, &tmp_len);
|
||||
if (tmp == NULL)
|
||||
return NULL;
|
||||
append(ret, tmp);
|
||||
#if 0
|
||||
if (0) {
|
||||
char buf[4096];
|
||||
|
||||
sexpr2string(ret, buf, sizeof(buf));
|
||||
printf("%s\n", buffer);
|
||||
}
|
||||
#endif
|
||||
ptr = trim(ptr + tmp_len);
|
||||
}
|
||||
|
||||
if (*ptr == ')') {
|
||||
ptr++;
|
||||
}
|
||||
} else {
|
||||
const char *start;
|
||||
|
||||
if (*ptr == '\'') {
|
||||
ptr++;
|
||||
start = ptr;
|
||||
|
||||
while (*ptr && *ptr != '\'') {
|
||||
if (*ptr == '\\' && ptr[1])
|
||||
ptr++;
|
||||
ptr++;
|
||||
}
|
||||
|
||||
ret->value = strndup(start, ptr - start);
|
||||
|
||||
if (*ptr == '\'')
|
||||
ptr++;
|
||||
} else {
|
||||
start = ptr;
|
||||
|
||||
while (*ptr && !isspace(*ptr) && *ptr != ')' && *ptr != '(') {
|
||||
ptr++;
|
||||
}
|
||||
|
||||
ret->value = strndup(start, ptr - start);
|
||||
}
|
||||
|
||||
ret->kind = SEXPR_VALUE;
|
||||
}
|
||||
|
||||
*end = ptr - buffer;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* string2sexpr:
|
||||
* @buffer: a zero terminated buffer containing an S-Expression in UTF-8
|
||||
*
|
||||
* Parse the S-Expression in the buffer.
|
||||
* Note that failure in this function is catrosphic. If it returns
|
||||
* NULL, you've leaked memory and you're currently OOM. It will always
|
||||
* parse an SEXPR given a buffer
|
||||
*
|
||||
* Returns a pointer to the resulting parsed S-Expression, or NULL in case of
|
||||
* hard error.
|
||||
*/
|
||||
struct sexpr *
|
||||
string2sexpr(const char *buffer)
|
||||
{
|
||||
size_t dummy = 0;
|
||||
|
||||
return _string2sexpr(buffer, &dummy);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* sexpr_lookup:
|
||||
* @sexpr: a pointer to a parsed S-Expression
|
||||
* @node: a path for the sub expression to lookup in the S-Expression
|
||||
*
|
||||
* Search a sub expression in the S-Expression based on its path
|
||||
* NOTE: path are limited to 4096 bytes.
|
||||
*
|
||||
* Returns the pointer to the sub expression or NULL if not found.
|
||||
*/
|
||||
struct sexpr *
|
||||
sexpr_lookup(struct sexpr *sexpr, const char *node)
|
||||
{
|
||||
char buffer[4096], *ptr, *token;
|
||||
|
||||
if ((node == NULL) || (sexpr == NULL))
|
||||
return(NULL);
|
||||
|
||||
snprintf(buffer, sizeof(buffer), "%s", node);
|
||||
|
||||
ptr = buffer;
|
||||
token = strsep(&ptr, "/");
|
||||
|
||||
if (sexpr->kind != SEXPR_CONS || sexpr->car->kind != SEXPR_VALUE) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (strcmp(sexpr->car->value, token) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (token = strsep(&ptr, "/"); token; token = strsep(&ptr, "/")) {
|
||||
struct sexpr *i;
|
||||
|
||||
if (token == NULL)
|
||||
continue;
|
||||
|
||||
sexpr = sexpr->cdr;
|
||||
for (i=sexpr; i->kind != SEXPR_NIL; i=i->cdr) {
|
||||
if (i->kind != SEXPR_CONS ||
|
||||
i->car->kind != SEXPR_CONS ||
|
||||
i->car->car->kind != SEXPR_VALUE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(i->car->car->value, token) == 0) {
|
||||
sexpr = i->car;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i->kind == SEXPR_NIL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (token != NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (sexpr->kind != SEXPR_CONS || sexpr->cdr->kind != SEXPR_CONS)
|
||||
return NULL;
|
||||
|
||||
return sexpr->cdr;
|
||||
}
|
||||
|
||||
/**
|
||||
* sexpr_node:
|
||||
* @sexpr: a pointer to a parsed S-Expression
|
||||
* @node: a path for the node to lookup in the S-Expression
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
const char *
|
||||
sexpr_node(struct sexpr *sexpr, const char *node)
|
||||
{
|
||||
struct sexpr *n = sexpr_lookup(sexpr, node);
|
||||
|
||||
return (n && n->car->kind == SEXPR_VALUE) ? n->car->value : NULL;
|
||||
}
|
56
src/sexpr.h
Normal file
56
src/sexpr.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* sexpr.h : S-Expression interfaces needed to communicate with the Xen Daemon
|
||||
*
|
||||
* Copyright (C) 2005
|
||||
*
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser General
|
||||
* Public License. See the file COPYING.LIB in the main directory of this
|
||||
* archive for more details.
|
||||
*/
|
||||
|
||||
#ifndef _LIBVIR_SEXPR_H_
|
||||
#define _LIBVIR_SEXPR_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
enum sexpr_type {
|
||||
SEXPR_NIL,
|
||||
SEXPR_CONS,
|
||||
SEXPR_VALUE,
|
||||
};
|
||||
|
||||
struct sexpr {
|
||||
enum sexpr_type kind;
|
||||
union {
|
||||
struct {
|
||||
struct sexpr *car;
|
||||
struct sexpr *cdr;
|
||||
};
|
||||
char *value;
|
||||
};
|
||||
};
|
||||
|
||||
/* conversion to/from strings */
|
||||
size_t sexpr2string (struct sexpr *sexpr,
|
||||
char *buffer,
|
||||
size_t n_buffer);
|
||||
struct sexpr * string2sexpr (const char *buffer);
|
||||
|
||||
/* constructors and destructors */
|
||||
struct sexpr * sexpr_nil (void);
|
||||
struct sexpr * sexpr_string (const char *str,
|
||||
ssize_t len);
|
||||
struct sexpr * sexpr_cons (struct sexpr *car,
|
||||
struct sexpr *cdr);
|
||||
struct sexpr * sexpr_append (struct sexpr *lst,
|
||||
struct sexpr *item);
|
||||
void sexpr_free (struct sexpr *sexpr);
|
||||
|
||||
/* lookup in S-Expressions */
|
||||
const char * sexpr_node (struct sexpr *sexpr,
|
||||
const char *node);
|
||||
struct sexpr * sexpr_lookup (struct sexpr *sexpr,
|
||||
const char *node);
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user