diff options
Diffstat (limited to 'tools/libxl')
-rw-r--r-- | tools/libxl/Makefile | 59 | ||||
-rw-r--r-- | tools/libxl/libxlu_cfg.c | 341 | ||||
-rw-r--r-- | tools/libxl/libxlu_cfg_i.h | 25 | ||||
-rw-r--r-- | tools/libxl/libxlu_cfg_l.l | 74 | ||||
-rw-r--r-- | tools/libxl/libxlu_cfg_y.y | 57 | ||||
-rw-r--r-- | tools/libxl/libxlu_internal.h | 48 | ||||
-rw-r--r-- | tools/libxl/libxlutil.h | 58 | ||||
-rw-r--r-- | tools/libxl/xl.c | 163 |
8 files changed, 696 insertions, 129 deletions
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 ) ({ \ |