aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.hgignore3
-rw-r--r--Config.mk3
-rw-r--r--README1
-rw-r--r--tools/libxl/Makefile59
-rw-r--r--tools/libxl/libxlu_cfg.c341
-rw-r--r--tools/libxl/libxlu_cfg_i.h25
-rw-r--r--tools/libxl/libxlu_cfg_l.l74
-rw-r--r--tools/libxl/libxlu_cfg_y.y57
-rw-r--r--tools/libxl/libxlu_internal.h48
-rw-r--r--tools/libxl/libxlutil.h58
-rw-r--r--tools/libxl/xl.c163
11 files changed, 702 insertions, 130 deletions
diff --git a/.hgignore b/.hgignore
index 92df552894..b40ca44c0c 100644
--- a/.hgignore
+++ b/.hgignore
@@ -180,7 +180,8 @@
^tools/libxen/libxenapi-
^tools/libxen/test/test_bindings$
^tools/libxen/test/test_event_handling$
-^tools/libxl/libconfig.*$
+^tools/libxl/libxlu_cfg_[yl]\.[ch]$
+^tools/libxl/libxlu_cfg_y\.output
^tools/libxl/xl$
^tools/libaio/src/.*\.ol$
^tools/libaio/src/.*\.os$
diff --git a/Config.mk b/Config.mk
index cd27af756d..1cebb31004 100644
--- a/Config.mk
+++ b/Config.mk
@@ -35,6 +35,9 @@ EXTRA_INCLUDES += $(EXTRA_PREFIX)/include
EXTRA_LIB += $(EXTRA_PREFIX)/$(LIBLEAFDIR)
endif
+BISON ?= bison
+FLEX ?= flex
+
PYTHON ?= python
PYTHON_PREFIX_ARG ?= --prefix="$(PREFIX)"
# The above requires that PREFIX contains *no spaces*. This variable is here
diff --git a/README b/README
index e32cd680f5..9869e911b0 100644
--- a/README
+++ b/README
@@ -49,6 +49,7 @@ provided by your Linux distributor:
* bridge-utils package (/sbin/brctl)
* iproute package (/sbin/ip)
* hotplug or udev
+ * GNU bison and GNU flex
[NB. Unless noted otherwise, all the following steps should be
performed with root privileges.]
diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
index 3ddcd48513..dbf8c436d1 100644
--- a/tools/libxl/Makefile
+++ b/tools/libxl/Makefile
@@ -8,24 +8,40 @@ include $(XEN_ROOT)/tools/Rules.mk
MAJOR = 1.0
MINOR = 0
+XLUMAJOR = 1.0
+XLUMINOR = 0
+
#CFLAGS += -Werror
CFLAGS += -I. -fPIC
CFLAGS += $(CFLAGS_libxenctrl) $(CFLAGS_libxenguest) $(CFLAGS_libxenstore)
LIBS = $(LDFLAGS_libxenctrl) $(LDFLAGS_libxenguest) $(LDFLAGS_libxenstore)
-#LIBCONFIG_URL ?= http://www.hyperrealm.com/libconfig
-LIBCONFIG_URL = $(XEN_EXTFILES_URL)
-LIBCONFIG_SOURCE = libconfig-1.3.2
-LIBCONFIG_OUTPUT = $(LIBCONFIG_SOURCE)/.libs
-
LIBXL_OBJS-y = osdeps.o
LIBXL_OBJS = flexarray.o libxl.o libxl_dom.o libxl_exec.o libxl_xshelp.o libxl_device.o libxl_internal.o xenguest.o libxl_utils.o $(LIBXL_OBJS-y)
+AUTOINCS= libxlu_cfg_y.h libxlu_cfg_l.h
+AUTOSRCS= libxlu_cfg_y.c libxlu_cfg_l.c
+LIBXLU_OBJS = libxlu_cfg_y.o libxlu_cfg_l.o libxlu_cfg.o
+
CLIENTS = xl
.PHONY: all
-all: $(CLIENTS) libxenlight.so libxenlight.a
+all: $(CLIENTS) libxenlight.so libxenlight.a libxlutil.so libxlutil.a \
+ $(AUTOSRCS) $(AUTOINCS)
+
+$(AUTOINCS): $(AUTOSRCS)
+
+#%_y.h: %_y.c
+#%_l.h: %_l.c
+
+$(LIBXLU_OBJS): $(AUTOINCS)
+
+%.c: %.y
+ $(BISON) --output=$@ $<
+
+%.c: %.l
+ $(FLEX) --header-file=$*.h --outfile=$@ $<
libxenlight.so: libxenlight.so.$(MAJOR)
ln -sf $< $@
@@ -39,18 +55,23 @@ libxenlight.so.$(MAJOR).$(MINOR): $(LIBXL_OBJS)
libxenlight.a: $(LIBXL_OBJS)
$(AR) rcs libxenlight.a $^
-$(LIBCONFIG_SOURCE).tar.gz:
- $(WGET) $(LIBCONFIG_URL)/$@
+libxlutil.so: libxlutil.so.$(XLUMAJOR)
+ ln -sf $< $@
+
+libxlutil.so.$(XLUMAJOR): libxlutil.so.$(XLUMAJOR).$(XLUMINOR)
+ ln -sf $< $@
+
+libxlutil.so.$(XLUMAJOR).$(XLUMINOR): $(LIBXLU_OBJS)
+ $(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxlutil.so.$(XLUMAJOR) $(SHLIB_CFLAGS) -o $@ $^
-$(LIBCONFIG_OUTPUT)/libconfig.so: $(LIBCONFIG_SOURCE).tar.gz
- [ ! -d "$(LIBCONFIG_SOURCE)" ] && tar xzf $<
- cd $(LIBCONFIG_SOURCE) && ./configure --prefix=$(PREFIX) --libdir=$(LIBDIR) --disable-cxx && $(MAKE)
+libxlutil.a: $(LIBXLU_OBJS)
+ $(AR) rcs libxlutil.a $^
-xl.o: $(LIBCONFIG_OUTPUT)/libconfig.so xl.c
- $(CC) $(CFLAGS) -I$(LIBCONFIG_SOURCE) -c xl.c
+xl.o: xl.c
+ $(CC) $(CFLAGS) -c xl.c
-$(CLIENTS): xl.o libxenlight.so $(LIBCONFIG_OUTPUT)/libconfig.so
- $(CC) $(LDFLAGS) -o $@ $< $(LIBS) -L . -lxenlight -L$(LIBCONFIG_OUTPUT) -lconfig
+$(CLIENTS): xl.o libxlutil.so libxenlight.so
+ $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
.PHONY: install
install: all
@@ -59,15 +80,17 @@ install: all
ln -sf libxenlight.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)/libxenlight.so.$(MAJOR)
ln -sf libxenlight.so.$(MAJOR) $(DESTDIR)$(LIBDIR)/libxenlight.so
$(INSTALL_DATA) libxenlight.a $(DESTDIR)$(LIBDIR)
+ $(INSTALL_PROG) libxlutil.so.$(XLUMAJOR).$(XLUMINOR) $(DESTDIR)$(LIBDIR)
+ ln -sf libxlutil.so.$(XLUMAJOR).$(XLUMINOR) $(DESTDIR)$(LIBDIR)/libxlutil.so.$(XLUMAJOR)
+ ln -sf libxlutil.so.$(XLUMAJOR) $(DESTDIR)$(LIBDIR)/libxlutil.so
+ $(INSTALL_DATA) libxlutil.a $(DESTDIR)$(LIBDIR)
$(INSTALL_DATA) libxl.h $(DESTDIR)$(INCLUDEDIR)
- cd $(LIBCONFIG_SOURCE) && DESTDIR=$(DESTDIR) $(MAKE) install
.PHONY: clean
clean:
$(RM) -f *.o *.so* *.a $(CLIENTS) $(DEPS)
- $(RM) -rf $(LIBCONFIG_SOURCE)
+ $(RM) -f $(AUTOSRCS) $(AUTOINCS)
distclean: clean
- $(RM) -f $(LIBCONFIG_SOURCE).tar.gz
-include $(DEPS)
diff --git a/tools/libxl/libxlu_cfg.c b/tools/libxl/libxlu_cfg.c
new file mode 100644
index 0000000000..632c371cf5
--- /dev/null
+++ b/tools/libxl/libxlu_cfg.c
@@ -0,0 +1,341 @@
+
+#include "libxlu_internal.h"
+#include "libxlu_cfg_y.h"
+#include "libxlu_cfg_l.h"
+#include "libxlu_cfg_i.h"
+
+XLU_Config *xlu_cfg_init(FILE *report, const char *report_filename) {
+ XLU_Config *cfg;
+
+ cfg= malloc(sizeof(*cfg));
+ if (!cfg) return 0;
+
+ cfg->report= report;
+ cfg->filename= strdup(report_filename);
+ if (!cfg->filename) { free(cfg); return 0; }
+
+ cfg->settings= 0;
+ return cfg;
+}
+
+int xlu_cfg_readfile(XLU_Config *cfg, const char *real_filename) {
+ CfgParseContext ctx;
+ FILE *f;
+ int e, r;
+
+ ctx.cfg= cfg;
+ ctx.err= 0;
+ ctx.lexerrlineno= -1;
+
+ f= fopen(real_filename, "r");
+ if (!f) {
+ e= errno;
+ fprintf(cfg->report,"%s: unable to open configuration file: %s\n",
+ real_filename, strerror(e));
+ return e;
+ }
+
+ e= xlu__cfg_yylex_init_extra(&ctx, &ctx.scanner);
+ if (e) {
+ fprintf(cfg->report,"%s: unable to create scanner: %s\n",
+ cfg->filename, strerror(e));
+ return e;
+ }
+
+ xlu__cfg_yyrestart(f, ctx.scanner);
+
+ r= xlu__cfg_yyparse(&ctx);
+ if (r) assert(ctx.err);
+
+ xlu__cfg_yylex_destroy(ctx.scanner);
+ fclose(f);
+
+ return ctx.err;
+}
+
+void xlu__cfg_set_free(XLU_ConfigSetting *set) {
+ free(set->name);
+ free(set->values);
+ free(set);
+}
+
+void xlu_cfg_destroy(XLU_Config *cfg) {
+ XLU_ConfigSetting *set, *set_next;
+
+ for (set= cfg->settings;
+ set;
+ set= set_next) {
+ set_next= set->next;
+ xlu__cfg_set_free(set);
+ }
+ free(cfg->filename);
+ free(cfg);
+}
+
+static XLU_ConfigSetting *find(const XLU_Config *cfg, const char *n) {
+ XLU_ConfigSetting *set;
+
+ for (set= cfg->settings;
+ set;
+ set= set->next)
+ if (!strcmp(set->name, n))
+ return set;
+ return 0;
+}
+
+static int find_atom(const XLU_Config *cfg, const char *n,
+ XLU_ConfigSetting **set_r) {
+ XLU_ConfigSetting *set;
+
+ set= find(cfg,n);
+ if (!set) return ESRCH;
+
+ if (set->avalues!=1) {
+ fprintf(cfg->report,
+ "%s:%d: warning: parameter `%s' is"
+ " a list but should be a single value\n",
+ cfg->filename, set->lineno, n);
+ return EINVAL;
+ }
+ *set_r= set;
+ return 0;
+}
+
+int xlu_cfg_get_string(const XLU_Config *cfg, const char *n,
+ const char **value_r) {
+ XLU_ConfigSetting *set;
+ int e;
+
+ e= find_atom(cfg,n,&set); if (e) return e;
+ *value_r= set->values[0];
+ return 0;
+}
+
+int xlu_cfg_get_long(const XLU_Config *cfg, const char *n,
+ long *value_r) {
+ long l;
+ XLU_ConfigSetting *set;
+ int e;
+ char *ep;
+
+ e= find_atom(cfg,n,&set); if (e) return e;
+ errno= 0; l= strtol(set->values[0], &ep, 0);
+ e= errno;
+ if (errno) {
+ e= errno;
+ assert(e==EINVAL || e==ERANGE);
+ fprintf(cfg->report,
+ "%s:%d: warning: parameter `%s' could not be parsed"
+ " as a number: %s\n",
+ cfg->filename, set->lineno, n, strerror(e));
+ return e;
+ }
+ if (*ep || ep==set->values[0]) {
+ fprintf(cfg->report,
+ "%s:%d: warning: parameter `%s' is not a valid number\n",
+ cfg->filename, set->lineno, n);
+ return EINVAL;
+ }
+ *value_r= l;
+ return 0;
+}
+
+
+int xlu_cfg_get_list(const XLU_Config *cfg, const char *n,
+ XLU_ConfigList **list_r, int *entries_r) {
+ XLU_ConfigSetting *set;
+ set= find(cfg,n); if (!set) return ESRCH;
+ if (set->avalues==1) {
+ fprintf(cfg->report,
+ "%s:%d: warning: parameter `%s' is a single value"
+ " but should be a list\n",
+ cfg->filename, set->lineno, n);
+ return EINVAL;
+ }
+ if (list_r) *list_r= set;
+ if (entries_r) *entries_r= set->nvalues;
+ return 0;
+}
+
+const char *xlu_cfg_get_listitem(const XLU_ConfigList *set, int entry) {
+ if (entry < 0 || entry >= set->nvalues) return 0;
+ return set->values[entry];
+}
+
+
+XLU_ConfigSetting *xlu__cfg_set_mk(CfgParseContext *ctx,
+ int alloc, char *atom) {
+ XLU_ConfigSetting *set= 0;
+
+ if (ctx->err) goto x;
+ assert(!!alloc == !!atom);
+
+ set= malloc(sizeof(*set));
+ if (!set) goto xe;
+
+ set->name= 0; /* tbd */
+ set->avalues= alloc;
+
+ if (!alloc) {
+ set->nvalues= 0;
+ set->values= 0;
+ } else {
+ set->values= malloc(sizeof(*set->values) * alloc);
+ if (!set->values) goto xe;
+
+ set->nvalues= 1;
+ set->values[0]= atom;
+ }
+ return set;
+
+ xe:
+ ctx->err= errno;
+ x:
+ free(set);
+ free(atom);
+ return 0;
+}
+
+void xlu__cfg_set_add(CfgParseContext *ctx, XLU_ConfigSetting *set,
+ char *atom) {
+ if (ctx->err) return;
+
+ assert(atom);
+
+ if (set->nvalues >= set->avalues) {
+ int new_avalues;
+ char **new_values;
+
+ if (set->avalues > INT_MAX / 100) { ctx->err= ERANGE; return; }
+ new_avalues= set->avalues * 4;
+ new_values= realloc(set->values,
+ sizeof(*new_values) * new_avalues);
+ if (!new_values) { ctx->err= errno; free(atom); return; }
+ set->values= new_values;
+ set->avalues= new_avalues;
+ }
+ set->values[set->nvalues++]= atom;
+}
+
+void xlu__cfg_set_store(CfgParseContext *ctx, char *name,
+ XLU_ConfigSetting *set, int lineno) {
+ if (ctx->err) return;
+
+ assert(name);
+ set->name= name;
+ set->lineno= lineno;
+ set->next= ctx->cfg->settings;
+ ctx->cfg->settings= set;
+}
+
+char *xlu__cfgl_strdup(CfgParseContext *ctx, const char *src) {
+ char *result;
+
+ if (ctx->err) return 0;
+ result= strdup(src);
+ if (!result) ctx->err= errno;
+ return result;
+}
+
+char *xlu__cfgl_dequote(CfgParseContext *ctx, const char *src) {
+ char *result;
+ const char *p;
+ char *q;
+ int len, c, nc;
+
+ if (ctx->err) return 0;
+
+ len= strlen(src);
+ assert(len>=2 && src[0]==src[len-1]);
+
+ result= malloc(len-1);
+ if (!result) { ctx->err= errno; return 0; }
+
+ q= result;
+
+ for (p= src+1;
+ p < src+len-1;
+ ) {
+ c= *p++;
+ if (c=='\\') {
+ assert(p < src+len-1);
+ nc= *p++;
+ if (nc=='"' || nc=='\'' || nc=='\\') {
+ *q++= nc;
+ } else if (nc=='a') { *q++= '\007';
+ } else if (nc=='b') { *q++= '\010';
+ } else if (nc=='f') { *q++= '\014';
+ } else if (nc=='n') { *q++= '\n';
+ } else if (nc=='r') { *q++= '\r';
+ } else if (nc=='t') { *q++= '\t';
+ } else if (nc=='v') { *q++= '\013';
+ } else if (nc=='x') {
+
+#define NUMERIC_CHAR(minlen,maxlen,base,basetext) do{ \
+ char numbuf[(maxlen)+1], *ep; \
+ unsigned long val; \
+ \
+ strncpy(numbuf,p,(maxlen)); \
+ numbuf[(maxlen)]= 0; \
+ val= strtoul(numbuf, &ep, (base)); \
+ if (ep <= numbuf+(minlen)) { \
+ xlu__cfgl_lexicalerror(ctx,"invalid digit after" \
+ " backslash " basetext "numerical character escape" \
+ " in quoted string"); \
+ ctx->err= EINVAL; \
+ goto x; \
+ } \
+ p += (ep - numbuf); \
+ }while(0)
+
+ p++;
+ NUMERIC_CHAR(2,2,16,"hex");
+ } else if (nc>='0' && nc<='7') {
+ NUMERIC_CHAR(1,3,10,"octal");
+ }
+ assert(p <= src+len-1);
+ } else {
+ *q++= c;
+ }
+ }
+
+ x:
+ *q++= 0;
+ return result;
+}
+
+void xlu__cfgl_lexicalerror(CfgParseContext *ctx, char const *msg) {
+ YYLTYPE loc;
+ loc.first_line= xlu__cfg_yyget_lineno(ctx->scanner);
+ xlu__cfg_yyerror(&loc, ctx, msg);
+ ctx->lexerrlineno= loc.first_line;
+}
+
+void xlu__cfg_yyerror(YYLTYPE *loc, CfgParseContext *ctx, char const *msg) {
+ const char *text, *newline;
+ int len, lineno;
+
+ lineno= loc->first_line;
+ if (lineno <= ctx->lexerrlineno) return;
+
+ text= xlu__cfg_yyget_text(ctx->scanner);
+ len= xlu__cfg_yyget_leng(ctx->scanner);
+ newline= "";
+ if (len>0 && text[len-1]=='\n') {
+ len--;
+ lineno--;
+ if (!len) {
+ newline= "<newline>";
+ }
+ }
+ while (len>0 && (text[len-1]=='\t' || text[len-1]==' ')) {
+ len--;
+ }
+
+ fprintf(ctx->cfg->report,
+ "%s:%d: config parsing error near %s%.*s%s%s: %s\n",
+ ctx->cfg->filename, lineno,
+ len?"`":"", len, text, len?"'":"", newline,
+ msg);
+ if (!ctx->err) ctx->err= EINVAL;
+}
diff --git a/tools/libxl/libxlu_cfg_i.h b/tools/libxl/libxlu_cfg_i.h
new file mode 100644
index 0000000000..f6b241cf09
--- /dev/null
+++ b/tools/libxl/libxlu_cfg_i.h
@@ -0,0 +1,25 @@
+#ifndef LIBXLU_CFG_I_H
+#define LIBXLU_CFG_I_H
+
+#include "libxlu_internal.h"
+#include "libxlu_cfg_y.h"
+
+void xlu__cfg_set_free(XLU_ConfigSetting *set);
+XLU_ConfigSetting *xlu__cfg_set_mk(CfgParseContext*, int alloc, char *atom);
+void xlu__cfg_set_add(CfgParseContext*, XLU_ConfigSetting *set, char *atom);
+void xlu__cfg_set_store(CfgParseContext*, char *name,
+ XLU_ConfigSetting *set, int lineno);
+
+char *xlu__cfgl_strdup(CfgParseContext*, const char *src);
+char *xlu__cfgl_dequote(CfgParseContext*, const char *src);
+
+void xlu__cfg_yyerror(YYLTYPE *locp, CfgParseContext*, char const *msg);
+void xlu__cfgl_lexicalerror(CfgParseContext*, char const *msg);
+
+
+
+/* Why oh why does bison not declare this in its autogenerated .h ? */
+int xlu__cfg_yyparse(CfgParseContext *ctx);
+
+
+#endif /*LIBXLU_CFG_I_H*/
diff --git a/tools/libxl/libxlu_cfg_l.l b/tools/libxl/libxlu_cfg_l.l
new file mode 100644
index 0000000000..b3700281cb
--- /dev/null
+++ b/tools/libxl/libxlu_cfg_l.l
@@ -0,0 +1,74 @@
+/* -*- fundamental -*- */
+
+%{
+#include "libxlu_cfg_i.h"
+
+#define ctx ((CfgParseContext*)yyextra)
+#define YY_NO_INPUT
+
+#define GOT(x) do{ \
+ yylloc->first_line= yylineno; \
+ return (x); \
+ }while(0)
+
+%}
+
+%option warn
+%option nodefault
+%option batch
+%option 8bit
+%option yylineno
+%option noyywrap
+%option bison-bridge
+%option bison-locations
+%option reentrant
+%option prefix="xlu__cfg_yy"
+%option nounput
+
+%x lexerr
+
+%%
+
+[a-z][_0-9a-z]* {
+ yylval->string= xlu__cfgl_strdup(ctx,yytext);
+ GOT(IDENT);
+ }
+[0-9][0-9a-fx]* {
+ yylval->string= xlu__cfgl_strdup(ctx,yytext);
+ GOT(NUMBER);
+ }
+
+[ \t]
+
+, { GOT(','); }
+\[ { GOT('['); }
+\] { GOT(']'); }
+\= { GOT('='); }
+\; { GOT(';'); }
+
+\n|\#.*\n { yylloc->first_line= yylineno-1; return NEWLINE; }
+
+\'([^\'\\\n]|\\.)*\' {
+ yylval->string= xlu__cfgl_dequote(ctx,yytext);
+ GOT(STRING);
+ }
+\"([^\"\\\n]|\\.)*\" {
+ yylval->string= xlu__cfgl_dequote(ctx,yytext);
+ GOT(STRING);
+ }
+
+. {
+ BEGIN(lexerr);
+ yymore();
+ }
+
+<lexerr>[^ \t\n]*|[ \t] {
+ xlu__cfgl_lexicalerror(ctx,"lexical error");
+ BEGIN(0);
+ }
+
+<lexerr>\n {
+ xlu__cfgl_lexicalerror(ctx,"lexical error");
+ BEGIN(0);
+ GOT(NEWLINE);
+ }
diff --git a/tools/libxl/libxlu_cfg_y.y b/tools/libxl/libxlu_cfg_y.y
new file mode 100644
index 0000000000..cdf8e0b66c
--- /dev/null
+++ b/tools/libxl/libxlu_cfg_y.y
@@ -0,0 +1,57 @@
+/* -*- fundamental -*- */
+
+%{
+#define YYLEX_PARAM ctx->scanner
+#include "libxlu_cfg_i.h"
+#include "libxlu_cfg_l.h"
+%}
+
+%union {
+ char *string;
+ XLU_ConfigSetting *setting;
+}
+
+%locations
+%pure-parser
+%defines
+%error-verbose
+%name-prefix="xlu__cfg_yy"
+%parse-param { CfgParseContext *ctx }
+%lex-param { void *scanner }
+
+%token <string> IDENT STRING NUMBER NEWLINE
+%type <string> atom
+%destructor { free($$); } atom IDENT STRING NUMBER
+
+%type <setting> value valuelist values
+%destructor { xlu__cfg_set_free($$); } value valuelist values
+
+%%
+
+file: /* empty */
+ | file setting
+
+setting: IDENT '=' value { xlu__cfg_set_store(ctx,$1,$3,@3.first_line); }
+ endstmt
+ | endstmt
+ | error NEWLINE
+
+endstmt: NEWLINE
+ | ';'
+
+value: atom { $$= xlu__cfg_set_mk(ctx,1,$1); }
+ | '[' nlok valuelist ']' { $$= $3; }
+
+atom: STRING { $$= $1; }
+ | NUMBER { $$= $1; }
+
+valuelist: /* empty */ { $$= xlu__cfg_set_mk(ctx,0,0); }
+ | values { $$= $1; }
+ | values ',' nlok { $$= $1; }
+
+values: atom nlok { $$= xlu__cfg_set_mk(ctx,2,$1); }
+ | values ',' nlok atom nlok { xlu__cfg_set_add(ctx,$1,$4); $$= $1; }
+
+nlok:
+ /* nothing */
+ | nlok NEWLINE
diff --git a/tools/libxl/libxlu_internal.h b/tools/libxl/libxlu_internal.h
new file mode 100644
index 0000000000..fd7addcfd6
--- /dev/null
+++ b/tools/libxl/libxlu_internal.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2010 Citrix Ltd.
+ * Author Ian Jackson <ian.jackson@eu.citrix.com>
+ *
+ * This program 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; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program 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.
+ */
+
+#ifndef LIBXLU_INTERNAL_H
+#define LIBXLU_INTERNAL_H
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <assert.h>
+
+#define XLU_ConfigList XLU_ConfigSetting
+
+#include "libxlutil.h"
+
+struct XLU_ConfigSetting { /* transparent */
+ struct XLU_ConfigSetting *next;
+ char *name;
+ int nvalues, avalues; /* lists have avalues>1 */
+ char **values;
+ int lineno;
+};
+
+struct XLU_Config {
+ XLU_ConfigSetting *settings;
+ FILE *report;
+ char *filename;
+};
+
+typedef struct {
+ XLU_Config *cfg;
+ int err, lexerrlineno;
+ void *scanner;
+} CfgParseContext;
+
+#endif /*LIBXLU_INTERNAL_H*/
diff --git a/tools/libxl/libxlutil.h b/tools/libxl/libxlutil.h
new file mode 100644
index 0000000000..97b16aa134
--- /dev/null
+++ b/tools/libxl/libxlutil.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2010 Citrix Ltd.
+ * Author Ian Jackson <ian.jackson@eu.citrix.com>
+ *
+ * This program 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; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program 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.
+ */
+
+#ifndef LIBXLUTIL_H
+#define LIBXLUTIL_H
+
+#include <stdio.h>
+
+#include "libxl.h"
+
+/* Unless otherwise stated, all functions return an errno value. */
+typedef struct XLU_Config XLU_Config;
+typedef struct XLU_ConfigList XLU_ConfigList;
+
+XLU_Config *xlu_cfg_init(FILE *report, const char *report_filename);
+ /* 0 means we got ENOMEM. */
+ /* report_filename is copied; report is saved and must remain valid
+ * until the Config is destroyed. */
+
+int xlu_cfg_readfile(XLU_Config*, const char *real_filename);
+ /* If this fails, then it is undefined behaviour to call xlu_cfg_get_...
+ * functions. You have to just xlu_cfg_destroy. */
+
+void xlu_cfg_destroy(XLU_Config*);
+
+
+/* All of the following print warnings to "report" if there is a problem.
+ * Return values are:
+ * 0 OK
+ * ESRCH not defined
+ * EINVAL value found but wrong format for request (prints warning)
+ * ERANGE value out of range (from strtol)
+ */
+
+int xlu_cfg_get_string(const XLU_Config*, const char *n, const char **value_r);
+int xlu_cfg_get_long(const XLU_Config*, const char *n, long *value_r);
+
+int xlu_cfg_get_list(const XLU_Config*, const char *n,
+ XLU_ConfigList **list_r /* may be 0 */,
+ int *entries_r /* may be 0 */);
+ /* there is no need to free *list_r; lifetime is that of the XLU_Config */
+const char *xlu_cfg_get_listitem(const XLU_ConfigList*, int entry);
+ /* xlu_cfg_get_listitem cannot fail, except that if entry is
+ * out of range it returns 0 (not setting errno) */
+
+#endif /* LIBXLUTIL_H */
diff --git a/tools/libxl/xl.c b/tools/libxl/xl.c
index 823c8177ec..6e88c6ee6a 100644
--- a/tools/libxl/xl.c
+++ b/tools/libxl/xl.c
@@ -19,7 +19,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <libconfig.h>
#include <unistd.h>
#include <sys/time.h> /* for time */
#include <getopt.h>
@@ -34,6 +33,7 @@
#include "libxl.h"
#include "libxl_utils.h"
+#include "libxlutil.h"
#define UUID_FMT "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
@@ -320,63 +320,6 @@ static void printf_info(libxl_domain_create_info *c_info,
}
}
-static char* compat_config_file(const char *filename)
-{
- char t;
- char *newfile = (char*) malloc(strlen(filename) + 4);
- char *buf = (char *) malloc(2048);
- int size = 2048, i;
- FILE *s;
- FILE *d;
-
- sprintf(newfile, "%s.xl", filename);
-
- s = fopen(filename, "r");
- if (!s) {
- perror("cannot open file for reading");
- return NULL;
- }
- d = fopen(newfile, "w");
- if (!d) {
- fclose(s);
- perror("cannot open file for writting");
- return NULL;
- }
-
- while (!feof(s)) {
- buf[0] = 0;
- fgets(buf, size, s);
- while (buf[strlen(buf) - 1] != '\n' && !feof(s)) {
- size += 1024;
- buf = realloc(buf, size + 1024);
- fgets(buf + (size - 1025), 1025, s);
- }
- for (i = 0; i < strlen(buf); i++)
- if (buf[i] == '\'')
- buf[i] = '\"';
- if (strchr(buf, '=') != NULL) {
- if ((buf[strlen(buf) - 1] == '\n' && buf[strlen(buf) - 2] == ';') ||
- buf[strlen(buf) - 1] == ';') {
- fputs(buf, d);
- } else {
- t = buf[strlen(buf) - 1];
- buf[strlen(buf) - 1] = ';';
- fputs(buf, d);
- fputc(t, d);
- }
- } else if (buf[0] == '#' || buf[0] == ' ' || buf[0] == '\n') {
- fputs(buf, d);
- }
- }
-
- fclose(s);
- fclose(d);
-
- free(buf);
-
- return newfile;
-}
-
static void parse_config_file(const char *filename,
libxl_domain_create_info *c_info,
libxl_domain_build_info *b_info,
@@ -394,35 +337,33 @@ static void parse_config_file(const char *filename,
{
const char *buf;
long l;
- struct config_t config;
- struct config_setting_t *vbds, *nics, *pcis, *cvfbs;
+ XLU_Config *config;
+ XLU_ConfigList *vbds, *nics, *pcis, *cvfbs;
int pci_power_mgmt = 0;
int pci_msitranslate = 1;
- int i;
+ int i, e;
- config_init (&config);
+ config= xlu_cfg_init(stderr, filename);
+ if (!config) {
+ fprintf(stderr, "Failed to allocate for configuration\n");
+ exit(1);
+ }
- if (!config_read_file(&config, filename)) {
- char *newfilename;
- config_destroy(&config);
- newfilename = compat_config_file(filename);
- config_init (&config);
- if (!config_read_file(&config, newfilename)) {
- fprintf(stderr, "Failed to parse config file %s on line %d, try removing any embedded python code\n", config_error_text(&config), config_error_line(&config));
- exit(1);
- }
- free(newfilename);
+ e= xlu_cfg_readfile (config, filename);
+ if (e) {
+ fprintf(stderr, "Failed to parse config file: %s\n", strerror(e));
+ exit(1);
}
init_create_info(c_info);
c_info->hvm = 0;
- if ((config_lookup_string (&config, "builder", &buf) == CONFIG_TRUE) &&
+ if (!xlu_cfg_get_string (config, "builder", &buf) &&
!strncmp(buf, "hvm", strlen(buf)))
c_info->hvm = 1;
/* hap is missing */
- if (config_lookup_string (&config, "name", &buf) == CONFIG_TRUE)
+ if (!xlu_cfg_get_string (config, "name", &buf))
c_info->name = strdup(buf);
else
c_info->name = "test";
@@ -433,48 +374,48 @@ static void parse_config_file(const char *filename,
init_build_info(b_info, c_info);
/* the following is the actual config parsing with overriding values in the structures */
- if (config_lookup_int (&config, "vcpus", &l) == CONFIG_TRUE)
+ if (!xlu_cfg_get_long (config, "vcpus", &l))
b_info->max_vcpus = l;
- if (config_lookup_int (&config, "memory", &l) == CONFIG_TRUE) {
+ if (!xlu_cfg_get_long (config, "memory", &l)) {
b_info->max_memkb = l * 1024;
b_info->target_memkb = b_info->max_memkb;
}
- if (config_lookup_int (&config, "shadow_memory", &l) == CONFIG_TRUE)
+ if (!xlu_cfg_get_long (config, "shadow_memory", &l))
b_info->shadow_memkb = l * 1024;
- if (config_lookup_int (&config, "videoram", &l) == CONFIG_TRUE)
+ if (!xlu_cfg_get_long (config, "videoram", &l))
b_info->video_memkb = l * 1024;
- if (config_lookup_string (&config, "kernel", &buf) == CONFIG_TRUE)
+ if (!xlu_cfg_get_string (config, "kernel", &buf))
b_info->kernel = strdup(buf);
if (c_info->hvm == 1) {
- if (config_lookup_int (&config, "pae", &l) == CONFIG_TRUE)
+ if (!xlu_cfg_get_long (config, "pae", &l))
b_info->u.hvm.pae = l;
- if (config_lookup_int (&config, "apic", &l) == CONFIG_TRUE)
+ if (!xlu_cfg_get_long (config, "apic", &l))
b_info->u.hvm.apic = l;
- if (config_lookup_int (&config, "acpi", &l) == CONFIG_TRUE)
+ if (!xlu_cfg_get_long (config, "acpi", &l))
b_info->u.hvm.acpi = l;
- if (config_lookup_int (&config, "nx", &l) == CONFIG_TRUE)
+ if (!xlu_cfg_get_long (config, "nx", &l))
b_info->u.hvm.nx = l;
- if (config_lookup_int (&config, "viridian", &l) == CONFIG_TRUE)
+ if (!xlu_cfg_get_long (config, "viridian", &l))
b_info->u.hvm.viridian = l;
} else {
char *cmdline;
- if (config_lookup_string (&config, "root", &buf) == CONFIG_TRUE) {
+ if (!xlu_cfg_get_string (config, "root", &buf)) {
asprintf(&cmdline, "root=%s", buf);
b_info->u.pv.cmdline = cmdline;
}
- if (config_lookup_string (&config, "ramdisk", &buf) == CONFIG_TRUE)
+ if (!xlu_cfg_get_string (config, "ramdisk", &buf))
b_info->u.pv.ramdisk = strdup(buf);
}
- if ((vbds = config_lookup (&config, "disk")) != NULL) {
+ if (!xlu_cfg_get_list (config, "disk", &vbds, 0)) {
*num_disks = 0;
*disks = NULL;
- while ((buf = config_setting_get_string_elem (vbds, *num_disks)) != NULL) {
+ while ((buf = xlu_cfg_get_listitem (vbds, *num_disks)) != NULL) {
char *buf2 = strdup(buf);
char *p, *p2;
*disks = (libxl_device_disk *) realloc(*disks, sizeof (libxl_device_disk) * ((*num_disks) + 1));
@@ -530,10 +471,10 @@ static void parse_config_file(const char *filename,
}
}
- if ((nics = config_lookup (&config, "vif")) != NULL) {
+ if (!xlu_cfg_get_list (config, "vif", &nics, 0)) {
*num_vifs = 0;
*vifs = NULL;
- while ((buf = config_setting_get_string_elem (nics, *num_vifs)) != NULL) {
+ while ((buf = xlu_cfg_get_listitem (nics, *num_vifs)) != NULL) {
char *buf2 = strdup(buf);
char *p, *p2;
*vifs = (libxl_device_nic *) realloc(*vifs, sizeof (libxl_device_nic) * ((*num_vifs) + 1));
@@ -593,12 +534,12 @@ skip:
}
}
- if ((cvfbs = config_lookup (&config, "vfb")) != NULL) {
+ if (!xlu_cfg_get_list (config, "vfb", &cvfbs, 0)) {
*num_vfbs = 0;
*num_vkbs = 0;
*vfbs = NULL;
*vkbs = NULL;
- while ((buf = config_setting_get_string_elem (cvfbs, *num_vfbs)) != NULL) {
+ while ((buf = xlu_cfg_get_listitem (cvfbs, *num_vfbs)) != NULL) {
char *buf2 = strdup(buf);
char *p, *p2;
*vfbs = (libxl_device_vfb *) realloc(*vfbs, sizeof(libxl_device_vfb) * ((*num_vfbs) + 1));
@@ -643,16 +584,16 @@ skip_vfb:
}
}
- if (config_lookup_int (&config, "pci_msitranslate", &l) == CONFIG_TRUE)
+ if (!xlu_cfg_get_long (config, "pci_msitranslate", &l))
pci_msitranslate = l;
- if (config_lookup_int (&config, "pci_power_mgmt", &l) == CONFIG_TRUE)
+ if (!xlu_cfg_get_long (config, "pci_power_mgmt", &l))
pci_power_mgmt = l;
- if ((pcis = config_lookup (&config, "pci")) != NULL) {
+ if (xlu_cfg_get_list (config, "pci", &pcis, 0)) {
*num_pcidevs = 0;
*pcidevs = NULL;
- while ((buf = config_setting_get_string_elem (pcis, *num_pcidevs)) != NULL) {
+ while ((buf = xlu_cfg_get_listitem (pcis, *num_pcidevs)) != NULL) {
unsigned int domain = 0, bus = 0, dev = 0, func = 0, vdevfn = 0;
char *buf2 = strdup(buf);
char *p;
@@ -690,37 +631,37 @@ skip_pci:
init_dm_info(dm_info, c_info, b_info);
/* then process config related to dm */
- if (config_lookup_string (&config, "device_model", &buf) == CONFIG_TRUE)
+ if (!xlu_cfg_get_string (config, "device_model", &buf))
dm_info->device_model = strdup(buf);
- if (config_lookup_int (&config, "stdvga", &l) == CONFIG_TRUE)
+ if (!xlu_cfg_get_long (config, "stdvga", &l))
dm_info->stdvga = l;
- if (config_lookup_int (&config, "vnc", &l) == CONFIG_TRUE)
+ if (!xlu_cfg_get_long (config, "vnc", &l))
dm_info->vnc = l;
- if (config_lookup_string (&config, "vnclisten", &buf) == CONFIG_TRUE)
+ if (!xlu_cfg_get_string (config, "vnclisten", &buf))
dm_info->vnclisten = strdup(buf);
- if (config_lookup_int (&config, "vncdisplay", &l) == CONFIG_TRUE)
+ if (!xlu_cfg_get_long (config, "vncdisplay", &l))
dm_info->vncdisplay = l;
- if (config_lookup_int (&config, "vncunused", &l) == CONFIG_TRUE)
+ if (!xlu_cfg_get_long (config, "vncunused", &l))
dm_info->vncunused = l;
- if (config_lookup_string (&config, "keymap", &buf) == CONFIG_TRUE)
+ if (!xlu_cfg_get_string (config, "keymap", &buf))
dm_info->keymap = strdup(buf);
- if (config_lookup_int (&config, "sdl", &l) == CONFIG_TRUE)
+ if (!xlu_cfg_get_long (config, "sdl", &l))
dm_info->sdl = l;
- if (config_lookup_int (&config, "opengl", &l) == CONFIG_TRUE)
+ if (!xlu_cfg_get_long (config, "opengl", &l))
dm_info->opengl = l;
- if (config_lookup_int (&config, "nographic", &l) == CONFIG_TRUE)
+ if (!xlu_cfg_get_long (config, "nographic", &l))
dm_info->nographic = l;
- if (config_lookup_string (&config, "serial", &buf) == CONFIG_TRUE)
+ if (!xlu_cfg_get_string (config, "serial", &buf))
dm_info->serial = strdup(buf);
- if (config_lookup_string (&config, "boot", &buf) == CONFIG_TRUE)
+ if (!xlu_cfg_get_string (config, "boot", &buf))
dm_info->boot = strdup(buf);
- if (config_lookup_int (&config, "usb", &l) == CONFIG_TRUE)
+ if (!xlu_cfg_get_long (config, "usb", &l))
dm_info->usb = l;
- if (config_lookup_string (&config, "usbdevice", &buf) == CONFIG_TRUE)
+ if (!xlu_cfg_get_string (config, "usbdevice", &buf))
dm_info->usbdevice = strdup(buf);
}
- config_destroy(&config);
+ xlu_cfg_destroy(config);
}
#define MUST( call ) ({ \