diff options
author | Ian Jackson <ian.jackson@eu.citrix.com> | 2011-06-28 12:19:11 +0100 |
---|---|---|
committer | Ian Jackson <ian.jackson@eu.citrix.com> | 2011-06-28 12:19:11 +0100 |
commit | 5c206536adf068f418d19195841ee18eb4537b6e (patch) | |
tree | 4c36fe860600999e481333826196143cd9e0cdd8 /tools/libxl/libxlu_disk_l.l | |
parent | eaed6ac8500f4a501ed02cebb4f99b3c8cf94adb (diff) | |
download | xen-5c206536adf068f418d19195841ee18eb4537b6e.tar.gz xen-5c206536adf068f418d19195841ee18eb4537b6e.tar.bz2 xen-5c206536adf068f418d19195841ee18eb4537b6e.zip |
libxl: disks: new xlu_disk_parse function
Introduce new flex/regexp-based parser for disk configuration strings.
Callers will be updated in following patches.
The existing xm command line syntax for block-attach expects multiple
arguments containing different parameters for different parts of the
disk specification, so we supply a parser function which can take
multiple strings and scan them in sequence.
Signed-off-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
Committed-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
Diffstat (limited to 'tools/libxl/libxlu_disk_l.l')
-rw-r--r-- | tools/libxl/libxlu_disk_l.l | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/tools/libxl/libxlu_disk_l.l b/tools/libxl/libxlu_disk_l.l new file mode 100644 index 0000000000..48a1314e0f --- /dev/null +++ b/tools/libxl/libxlu_disk_l.l @@ -0,0 +1,217 @@ +/* -*- fundamental -*- */ +/* + * libxlu_disk_l.l - parser for disk specification strings + * + * Copyright (C) 2011 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. + */ + +/* + * Parsing the old xm/xend/xl-4.1 disk specs is a tricky problem, + * because the target string might in theory contain "," which is the + * delimiter we use for stripping off things on the RHS, and ":", + * which is the delimiter we use for stripping off things on the LHS. + * + * In this parser we do not support such target strings in the old + * syntax; if the target string has to contain "," or ":" the new + * syntax's "target=" should be used. + */ + +%{ +#include "libxlu_disk_i.h" + +#define YY_NO_INPUT + +/* Some versions of flex have a bug (Fedora bugzilla 612465) which causes + * it to fail to declare these functions, which it defines. So declare + * them ourselves. Hopefully we won't have to simultaneously support + * a flex version which declares these differently somehow. */ +int xlu__disk_yyget_column(yyscan_t yyscanner); +void xlu__disk_yyset_column(int column_no, yyscan_t yyscanner); + + +/*----- useful macros and functions used in actions ----- + * we use macros in the actual rules to keep the actions short + * and particularly to avoid repeating boilerplate values such as + * DPC->disk, yytext, etc. */ + +#define DPC ((DiskParseContext*)yyextra) + +/* Sets an enum, checking it hasn't already been set to a different value */ +#define DSET(dpc,member,enumname,str,valname) do{ \ + if (dpc->disk->member != LIBXL_DISK_##enumname##_UNKNOWN && \ + dpc->disk->member != LIBXL_DISK_##enumname##_##valname) { \ + xlu__disk_err(dpc, str, TOSTRING(member) " respecified"); \ + } else { \ + dpc->disk->member = LIBXL_DISK_##enumname##_##valname; \ + } \ + }while(0) + +/* For actions whose patterns contain '=', finds the start of the value */ +#define FROMEQUALS (strchr(yytext,'=')+1) + +/* Chops the delimiter off, modifying yytext and yyleng. */ +#define STRIP(delim) do{ \ + if (yyleng>0 && yytext[yyleng-1]==(delim)) \ + yytext[--yyleng] = 0; \ + }while(0) + +/* Sets a string value, checking it hasn't been set already. */ +#define SAVESTRING(what,loc,val) do{ \ + savestring(DPC, what " respecified", &DPC->disk->loc, (val)); \ + }while(0) +static void savestring(DiskParseContext *dpc, const char *what_respecified, + char **update, const char *value) { + if (*update) { + if (**update) { xlu__disk_err(dpc,value,what_respecified); return; } + free(*update); /* do not complain about overwriting empty strings */ + } + *update = strdup(value); +} + +/* Sets ->readwrite from the string. This ought to be an enum, perhaps. */ +static void setaccess(DiskParseContext *dpc, const char *str) { + if (!strcmp(str, "r") || !strcmp(str, "ro")) { + dpc->disk->readwrite = 0; + } else if (!strcmp(str, "rw") || !strcmp(str, "w") || !strcmp(str,"")) { + dpc->disk->readwrite = 1; + } else { + xlu__disk_err(dpc,str,"unknown value for access"); + } +} + +/* Sets ->format from the string. IDL should provide something for this. */ +static void setformat(DiskParseContext *dpc, const char *str) { + if (!strcmp(str,"") || + !strcmp(str,"raw")) DSET(dpc,format,FORMAT,str,RAW); + else if (!strcmp(str,"qcow")) DSET(dpc,format,FORMAT,str,QCOW); + else if (!strcmp(str,"qcow2")) DSET(dpc,format,FORMAT,str,QCOW2); + else if (!strcmp(str,"vhd")) DSET(dpc,format,FORMAT,str,VHD); + else xlu__disk_err(dpc,str,"unknown value for format"); +} + +#define DEPRECATE(usewhatinstead) /* not currently reported */ + +%} + +%option warn +%option nodefault +%option batch +%option 8bit +%option noyywrap +%option reentrant +%option prefix="xlu__disk_yy" +%option nounput + +%x LEXERR + +%% + + /*----- the scanner rules which do the parsing -----*/ + +[ \t\n]+/([^ \t\n].*)? { /* ignore whitespace before parameters */ } + + /* ordinary parameters setting enums or strings */ + +format=[^,]*,? { STRIP(','); setformat(DPC, FROMEQUALS); } + +cdrom,? { DPC->disk->is_cdrom = 1; } +devtype=cdrom,? { DPC->disk->is_cdrom = 1; } +devtype=disk,? { DPC->disk->is_cdrom = 0; } +devtype=[^,]*,? { xlu__disk_err(DPC,yytext,"unknown value for type"); } + +access=[^,]*,? { STRIP(','); setaccess(DPC, FROMEQUALS); } + +vdev=[^,]*,? { STRIP(','); SAVESTRING("vdev", vdev, FROMEQUALS); } +script=[^,]*,? { STRIP(','); SAVESTRING("script", script, FROMEQUALS); } + + /* the target magic parameter, eats the rest of the string */ + +target=.* { STRIP(','); SAVESTRING("target", pdev_path, FROMEQUALS); } + + /* unknown parameters */ + +[a-z][-a-z0-9]*=[^,],? { xlu__disk_err(DPC,yytext,"unknown parameter"); } + + /* deprecated prefixes */ + + /* the "/.*" in these patterns ensures that they count as if they + * matched the whole string, so these patterns take precedence */ + +(raw|qcow2?|vhd):/.* { + STRIP(':'); + DPC->had_depr_prefix=1; DEPRECATE("use `[format=]...,'"); + setformat(DPC, yytext); + } + +iscsi:|e?nbd:drbd:/.* { + STRIP(':'); + DPC->had_depr_prefix=1; DEPRECATE("use `script=...'"); + SAVESTRING("script", script, yytext); + } + +tapdisk:/.* { DPC->had_depr_prefix=1; DEPRECATE(0); } +tap2?:/.* { DPC->had_depr_prefix=1; DEPRECATE(0); } +aio:/.* { DPC->had_depr_prefix=1; DEPRECATE(0); } +ioemu:/.* { DPC->had_depr_prefix=1; DEPRECATE(0); } +file:/.* { DPC->had_depr_prefix=1; DEPRECATE(0); } +phy:/.* { DPC->had_depr_prefix=1; DEPRECATE(0); } + +[a-z][a-z0-9]*:/([^a-z0-9].*)? { + xlu__disk_err(DPC,yytext,"unknown deprecated disk prefix"); + return 0; + } + + /* positional parameters */ + +[^=,]*,|[^=,]+,? { + char *colon; + STRIP(','); + + if (DPC->err) { + /* previous errors may just lead to subsequent ones */ + } else if (!DPC->disk->pdev_path) { + SAVESTRING("target", pdev_path, yytext); + } else if (!DPC->had_depr_prefix && + DPC->disk->format == LIBXL_DISK_FORMAT_UNKNOWN) { + setformat(DPC,yytext); + } else if (!DPC->disk->vdev) { + colon = strrchr(yytext, ':'); + if (colon) { + DEPRECATE("use `devtype=...'"); + *colon++ = 0; + if (!strcmp(colon,"cdrom")) { + DPC->disk->is_cdrom = 1; + } else if (!strcmp(colon,"disk")) { + DPC->disk->is_cdrom = 0; + } else { + xlu__disk_err(DPC,colon,"unknown deprecated type"); + } + } + SAVESTRING("vdev", vdev, yytext); + } else if (!DPC->access_set) { + DPC->access_set = 1; + setaccess(DPC,yytext); + } else { + xlu__disk_err(DPC,yytext,"too many positional parameters"); + return 0; /* don't print any more errors */ + } +} + +. { + BEGIN(LEXERR); + yymore(); +} +<LEXERR>.* { + xlu__disk_err(DPC,yytext,"bad disk syntax"); return 0; +} |