* 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:
Daniel Veillard 2006-01-11 13:58:32 +00:00
parent 2b019dd2f7
commit f18b6c0ec6
6 changed files with 513 additions and 3 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
View 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
View 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