/src/remote/*_protocol.[ch]
/src/rpc/virkeepaliveprotocol.[ch]
/src/rpc/virnetprotocol.[ch]
+/src/xenconfig/xen_xl_disk.[ch]
/src/test_libvirt*.aug
/src/test_virtlockd.aug
/src/util/virkeymaps.h
endif
# Files that should never cause syntax check failures.
+# (^(HACKING|docs/(news\.html\.in|.*\.patch))|\.(po|fig|gif|ico|png))$$
VC_LIST_ALWAYS_EXCLUDE_REGEX = \
- (^(HACKING|docs/(news\.html\.in|.*\.patch))|\.(po|fig|gif|ico|png))$$
+ (^(HACKING|docs/(news\.html\.in|.*\.patch)|src/xenconfig/xen_xl_disk.[chl])|\.(po|fig|gif|ico|png))$$
# Functions like free() that are no-ops on NULL arguments.
useless_free_options = \
])
AM_PROG_CC_C_O
AM_PROG_LD
+AM_PROG_LEX
AC_MSG_CHECKING([for how to mark DSO non-deletable at runtime])
LIBVIRT_NODELETE=
src/xenapi/xenapi_utils.c
src/xenconfig/xen_common.c
src/xenconfig/xen_sxpr.c
+src/xenconfig/xen_xl.c
src/xenconfig/xen_xm.c
tests/virpolkittest.c
tools/libvirt-guests.sh.in
VMX_SOURCES = \
vmx/vmx.c vmx/vmx.h
+AM_LFLAGS = -Pxl_disk_ --header-file=../$*.h
+LEX_OUTPUT_ROOT = lex.xl_disk_
+BUILT_SOURCES += xenconfig/xen_xl_disk.c xenconfig/xen_xl_disk.h
+# Generated header file is not implicitly added to dist
+EXTRA_DIST += xenconfig/xen_xl_disk.h
+CLEANFILES += xenconfig/xen_xl_disk.h xenconfig/xen_xl_disk.c
+
+XENXLDISKPARSER_SOURCES = xenconfig/xen_xl_disk.l
+
XENCONFIG_SOURCES = \
xenconfig/xenxs_private.h \
- xenconfig/xen_common.c xenconfig/xen_common.h \
+ xenconfig/xen_common.c xenconfig/xen_common.h \
xenconfig/xen_sxpr.c xenconfig/xen_sxpr.h \
- xenconfig/xen_xm.c xenconfig/xen_xm.h
+ xenconfig/xen_xm.c xenconfig/xen_xm.h \
+ xenconfig/xen_xl.c xenconfig/xen_xl.h \
+ xenconfig/xen_xl_disk_i.h
pkgdata_DATA = cpu/cpu_map.xml
endif WITH_VMX
if WITH_XENCONFIG
+# Flex generated XL disk parser needs to be compiled without WARN_FLAGS
+# Add the generated object to its own library to control CFLAGS
+noinst_LTLIBRARIES += libvirt_xenxldiskparser.la
+libvirt_xenxldiskparser_la_CFLAGS = \
+ -I$(top_srcdir)/src/conf $(AM_CFLAGS) -Wno-unused-parameter
+libvirt_xenxldiskparser_la_SOURCES = \
+ $(XENXLDISKPARSER_SOURCES)
+
noinst_LTLIBRARIES += libvirt_xenconfig.la
libvirt_la_BUILT_LIBADD += libvirt_xenconfig.la
libvirt_xenconfig_la_CFLAGS = \
-I$(top_srcdir)/src/conf $(AM_CFLAGS)
+libvirt_xenconfig_la_LIBADD = libvirt_xenxldiskparser.la
libvirt_xenconfig_la_SOURCES = $(XENCONFIG_SOURCES)
endif WITH_XENCONFIG
$(VBOX_DRIVER_EXTRA_DIST) \
$(VMWARE_DRIVER_SOURCES) \
$(XENCONFIG_SOURCES) \
+ $(XENXLDISKPARSER_SOURCES) \
$(ACCESS_DRIVER_POLKIT_POLICY)
check-local: check-augeas
xenParseSxprSound;
xenParseSxprString;
+#xenconfig/xen_xl.h
+xenFormatXL;
+xenParseXL;
+
# xenconfig/xen_xm.h
xenFormatXM;
xenParseXM;
{
int hvm = STREQ(def->os.type, "hvm") ? 1 : 0;
- if (def->ngraphics == 1) {
+ if (def->ngraphics == 1 &&
+ def->graphics[0]->type != VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
if (hvm || (xendConfigVersion < XEND_CONFIG_MIN_VERS_PVFB_NEWCONF)) {
if (def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
if (xenConfigSetInt(conf, "sdl", 1) < 0)
--- /dev/null
+/*
+ * xen_xl.c: Xen XL parsing functions
+ *
+ * This library 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; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Kiarie Kahurani <davidkiarie4@gmail.com>
+ */
+
+#include <config.h>
+
+#include "virconf.h"
+#include "virerror.h"
+#include "domain_conf.h"
+#include "viralloc.h"
+#include "virstring.h"
+#include "xen_xl.h"
+#include "xen_xl_disk.h"
+#include "xen_xl_disk_i.h"
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+
+static int
+xenParseXLSpice(virConfPtr conf, virDomainDefPtr def)
+{
+ virDomainGraphicsDefPtr graphics = NULL;
+ unsigned long port;
+ char *listenAddr = NULL;
+ int val;
+
+ if (STREQ(def->os.type, "hvm")) {
+ if (xenConfigGetBool(conf, "spice", &val, 0) < 0)
+ return -1;
+
+ if (val) {
+ if (VIR_ALLOC(graphics) < 0)
+ return -1;
+
+ graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_SPICE;
+ if (xenConfigCopyStringOpt(conf, "spicehost", &listenAddr) < 0)
+ goto cleanup;
+ if (listenAddr &&
+ virDomainGraphicsListenSetAddress(graphics, 0, listenAddr,
+ -1, true) < 0) {
+ goto cleanup;
+ }
+ VIR_FREE(listenAddr);
+
+ if (xenConfigGetULong(conf, "spicetls_port", &port, 0) < 0)
+ goto cleanup;
+ graphics->data.spice.tlsPort = (int)port;
+
+ if (xenConfigGetULong(conf, "spiceport", &port, 0) < 0)
+ goto cleanup;
+
+ graphics->data.spice.port = (int)port;
+
+ if (!graphics->data.spice.tlsPort &&
+ !graphics->data.spice.port)
+ graphics->data.spice.autoport = 1;
+
+ if (xenConfigGetBool(conf, "spicedisable_ticketing", &val, 0) < 0)
+ goto cleanup;
+ if (val) {
+ if (xenConfigCopyStringOpt(conf, "spicepasswd",
+ &graphics->data.spice.auth.passwd) < 0)
+ goto cleanup;
+ }
+
+ if (xenConfigGetBool(conf, "spiceagent_mouse",
+ &graphics->data.spice.mousemode, 0) < 0)
+ goto cleanup;
+ if (xenConfigGetBool(conf, "spicedvagent", &val, 0) < 0)
+ goto cleanup;
+ if (val) {
+ if (xenConfigGetBool(conf, "spice_clipboard_sharing",
+ &graphics->data.spice.copypaste,
+ 0) < 0)
+ goto cleanup;
+ }
+
+ if (VIR_ALLOC_N(def->graphics, 1) < 0)
+ goto cleanup;
+ def->graphics[0] = graphics;
+ def->ngraphics = 1;
+ }
+ }
+
+ return 0;
+
+ cleanup:
+ virDomainGraphicsDefFree(graphics);
+ return -1;
+}
+
+
+void
+xenXLDiskParserError(xenXLDiskParserContext *dpc,
+ const char *erroneous,
+ const char *message)
+{
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("disk config %s not supported: %s"),
+ erroneous, message);
+
+ if (!dpc->err)
+ dpc->err = EINVAL;
+}
+
+
+static int
+xenXLDiskParserPrep(xenXLDiskParserContext *dpc,
+ const char *spec,
+ virDomainDiskDefPtr disk)
+{
+ int err;
+
+ dpc->spec = spec;
+ dpc->disk = disk;
+ dpc->access_set = 0;
+
+ err = xl_disk_lex_init_extra(dpc, &dpc->scanner);
+ if (err)
+ goto fail;
+
+ dpc->buf = xl_disk__scan_bytes(spec, strlen(spec), dpc->scanner);
+ if (!dpc->buf) {
+ err = ENOMEM;
+ goto fail;
+ }
+
+ return 0;
+
+ fail:
+ virReportSystemError(errno, "%s",
+ _("failed to initialize disk configuration parser"));
+ return err;
+}
+
+
+static void
+xenXLDiskParserCleanup(xenXLDiskParserContext *dpc)
+{
+ if (dpc->buf) {
+ xl_disk__delete_buffer(dpc->buf, dpc->scanner);
+ dpc->buf = NULL;
+ }
+
+ if (dpc->scanner) {
+ xl_disk_lex_destroy(dpc->scanner);
+ dpc->scanner = NULL;
+ }
+}
+
+
+/*
+ * positional parameters
+ * (If the <diskspec> strings are not separated by "="
+ * the string is split following ',' and assigned to
+ * the following options in the following order)
+ * target,format,vdev,access
+ * ================================================================
+ *
+ * The parameters below cannot be specified as positional parameters:
+ *
+ * other parameters
+ * devtype = <devtype>
+ * backendtype = <backend-type>
+ * parameters not taken care of
+ * backend = <domain-name>
+ * script = <script>
+ * direct-io-safe
+ *
+ * ================================================================
+ * The parser does not take any deprecated parameters
+ *
+ * For more information refer to /xen/docs/misc/xl-disk-configuration.txt
+ */
+static int
+xenParseXLDisk(virConfPtr conf, virDomainDefPtr def)
+{
+ virConfValuePtr list = virConfGetValue(conf, "disk");
+ xenXLDiskParserContext dpc;
+ virDomainDiskDefPtr disk;
+
+ memset(&dpc, 0, sizeof(dpc));
+
+ if (list && list->type == VIR_CONF_LIST) {
+ list = list->list;
+ while (list) {
+ char *disk_spec = list->str;
+ const char *driver;
+
+ if ((list->type != VIR_CONF_STRING) || (list->str == NULL))
+ goto skipdisk;
+
+ if (!(disk = virDomainDiskDefNew()))
+ return -1;
+
+ disk->src->readonly = 0;
+ disk->src->format = VIR_STORAGE_FILE_LAST;
+
+ if (xenXLDiskParserPrep(&dpc, disk_spec, disk))
+ goto fail;
+
+ xl_disk_lex(dpc.scanner);
+
+ if (dpc.err)
+ goto fail;
+
+ if (disk->src->format == VIR_STORAGE_FILE_LAST)
+ disk->src->format = VIR_STORAGE_FILE_RAW;
+
+ if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
+ disk->removable = true;
+ disk->src->readonly = true;
+ if (virDomainDiskSetDriver(disk, "qemu") < 0)
+ goto fail;
+
+ virDomainDiskSetType(disk, VIR_STORAGE_TYPE_FILE);
+ if (!disk->src->path || STREQ(disk->src->path, ""))
+ disk->src->format = VIR_STORAGE_FILE_NONE;
+ }
+
+ if (STRPREFIX(disk->dst, "xvd") || !STREQ(def->os.type, "hvm"))
+ disk->bus = VIR_DOMAIN_DISK_BUS_XEN;
+ else if (STRPREFIX(disk->dst, "sd"))
+ disk->bus = VIR_DOMAIN_DISK_BUS_SCSI;
+ else
+ disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
+
+ driver = virDomainDiskGetDriver(disk);
+ if (!driver) {
+ switch (disk->src->format) {
+ case VIR_STORAGE_FILE_QCOW:
+ case VIR_STORAGE_FILE_QCOW2:
+ case VIR_STORAGE_FILE_VHD:
+ driver = "qemu";
+ if (virDomainDiskSetDriver(disk, "qemu") < 0)
+ goto fail;
+ break;
+ default:
+ driver = "phy";
+ if (virDomainDiskSetDriver(disk, "phy") < 0)
+ goto fail;
+ }
+ }
+
+ if (STREQ(driver, "phy"))
+ virDomainDiskSetType(disk, VIR_STORAGE_TYPE_BLOCK);
+ else
+ virDomainDiskSetType(disk, VIR_STORAGE_TYPE_FILE);
+
+ if (VIR_APPEND_ELEMENT(def->disks, def->ndisks, disk) < 0)
+ goto fail;
+
+ skipdisk:
+ list = list->next;
+ xenXLDiskParserCleanup(&dpc);
+ }
+ }
+ return 0;
+
+ fail:
+ xenXLDiskParserCleanup(&dpc);
+ virDomainDiskDefFree(disk);
+ return -1;
+}
+
+
+virDomainDefPtr
+xenParseXL(virConfPtr conf, virCapsPtr caps, int xendConfigVersion)
+{
+ virDomainDefPtr def = NULL;
+
+ if (VIR_ALLOC(def) < 0)
+ return NULL;
+
+ def->virtType = VIR_DOMAIN_VIRT_XEN;
+ def->id = -1;
+
+ if (xenParseConfigCommon(conf, def, caps, xendConfigVersion) < 0)
+ goto cleanup;
+
+ if (xenParseXLDisk(conf, def) < 0)
+ goto cleanup;
+
+ if (xenParseXLSpice(conf, def) < 0)
+ goto cleanup;
+
+ return def;
+
+ cleanup:
+ virDomainDefFree(def);
+ return NULL;
+}
+
+
+static int
+xenFormatXLDisk(virConfValuePtr list, virDomainDiskDefPtr disk)
+{
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ virConfValuePtr val, tmp;
+ const char *src = virDomainDiskGetSource(disk);
+ int format = virDomainDiskGetFormat(disk);
+
+ /* target */
+ virBufferAsprintf(&buf, "%s,", src);
+ /* format */
+ switch (format) {
+ case VIR_STORAGE_FILE_RAW:
+ virBufferAddLit(&buf, "raw,");
+ break;
+ case VIR_STORAGE_FILE_VHD:
+ virBufferAddLit(&buf, "xvhd,");
+ break;
+ case VIR_STORAGE_FILE_QCOW:
+ virBufferAddLit(&buf, "qcow,");
+ break;
+ case VIR_STORAGE_FILE_QCOW2:
+ virBufferAddLit(&buf, "qcow2,");
+ break;
+ /* set default */
+ default:
+ virBufferAddLit(&buf, "raw,");
+ }
+
+ /* device */
+ virBufferAdd(&buf, disk->dst, -1);
+
+ virBufferAddLit(&buf, ",");
+
+ if (disk->src->readonly)
+ virBufferAddLit(&buf, "r,");
+ else if (disk->src->shared)
+ virBufferAddLit(&buf, "!,");
+ else
+ virBufferAddLit(&buf, "w,");
+ if (disk->transient) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("transient disks not supported yet"));
+ goto cleanup;
+ }
+
+ if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
+ virBufferAddLit(&buf, "devtype=cdrom");
+
+ if (virBufferCheckError(&buf) < 0)
+ goto cleanup;
+
+ if (VIR_ALLOC(val) < 0)
+ goto cleanup;
+
+ val->type = VIR_CONF_STRING;
+ val->str = virBufferContentAndReset(&buf);
+ tmp = list->list;
+ while (tmp && tmp->next)
+ tmp = tmp->next;
+ if (tmp)
+ tmp->next = val;
+ else
+ list->list = val;
+ return 0;
+
+ cleanup:
+ virBufferFreeAndReset(&buf);
+ return -1;
+}
+
+
+static int
+xenFormatXLDomainDisks(virConfPtr conf, virDomainDefPtr def)
+{
+ virConfValuePtr diskVal = NULL;
+ size_t i = 0;
+
+ if (VIR_ALLOC(diskVal) < 0)
+ return -1;
+
+ diskVal->type = VIR_CONF_LIST;
+ diskVal->list = NULL;
+
+ for (i = 0; i < def->ndisks; i++) {
+ if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY)
+ continue;
+ if (xenFormatXLDisk(diskVal, def->disks[i]) < 0)
+
+ goto cleanup;
+ }
+
+ if (diskVal->list != NULL) {
+ int ret = virConfSetValue(conf, "disk", diskVal);
+ diskVal = NULL;
+ if (ret < 0)
+ goto cleanup;
+ }
+
+ return 0;
+
+ cleanup:
+ virConfFreeValue(diskVal);
+ return 0;
+}
+
+
+static int
+xenFormatXLSpice(virConfPtr conf, virDomainDefPtr def)
+{
+ const char *listenAddr = NULL;
+
+ if (STREQ(def->os.type, "hvm")) {
+ if (def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
+ /* set others to false but may not be necessary */
+ if (xenConfigSetInt(conf, "sdl", 0) < 0)
+ return -1;
+
+ if (xenConfigSetInt(conf, "vnc", 0) < 0)
+ return -1;
+
+ if (xenConfigSetInt(conf, "spice", 1) < 0)
+ return -1;
+
+ if (xenConfigSetInt(conf, "spiceport",
+ def->graphics[0]->data.spice.port) < 0)
+ return -1;
+
+ if (xenConfigSetInt(conf, "spicetls_port",
+ def->graphics[0]->data.spice.tlsPort) < 0)
+ return -1;
+
+ if (def->graphics[0]->data.spice.auth.passwd) {
+ if (xenConfigSetInt(conf, "spicedisable_ticketing", 1) < 0)
+ return -1;
+
+ if (def->graphics[0]->data.spice.auth.passwd &&
+ xenConfigSetString(conf, "spicepasswd",
+ def->graphics[0]->data.spice.auth.passwd) < 0)
+ return -1;
+ }
+
+ listenAddr = virDomainGraphicsListenGetAddress(def->graphics[0], 0);
+ if (listenAddr &&
+ xenConfigSetString(conf, "spicehost", listenAddr) < 0)
+ return -1;
+
+ if (xenConfigSetInt(conf, "spicemouse_mouse",
+ def->graphics[0]->data.spice.mousemode) < 0)
+ return -1;
+
+ if (def->graphics[0]->data.spice.copypaste) {
+ if (xenConfigSetInt(conf, "spicedvagent", 1) < 0)
+ return -1;
+ if (xenConfigSetInt(conf, "spice_clipboard_sharing",
+ def->graphics[0]->data.spice.copypaste) < 0)
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+virConfPtr
+xenFormatXL(virDomainDefPtr def, virConnectPtr conn, int xendConfigVersion)
+{
+ virConfPtr conf = NULL;
+
+ if (!(conf = virConfNew()))
+ goto cleanup;
+
+ if (xenFormatConfigCommon(conf, def, conn, xendConfigVersion) < 0)
+ goto cleanup;
+
+ if (xenFormatXLDomainDisks(conf, def) < 0)
+ goto cleanup;
+
+ if (xenFormatXLSpice(conf, def) < 0)
+ goto cleanup;
+
+ return conf;
+
+ cleanup:
+ if (conf)
+ virConfFree(conf);
+ return NULL;
+}
--- /dev/null
+/*
+ * xen_xl.h: Xen XL parsing functions
+ *
+ * This library 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; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Kiarie Kahurani<davidkiarie4@gmail.com>
+ */
+
+#ifndef __VIR_XEN_XL_H__
+# define __VIR_XEN_XL_H__
+
+# include "virconf.h"
+# include "domain_conf.h"
+# include "xen_common.h"
+
+virDomainDefPtr xenParseXL(virConfPtr conn, virCapsPtr caps,
+ int xendConfigVersion);
+virConfPtr xenFormatXL(virDomainDefPtr def,
+ virConnectPtr, int xendConfigVersion);
+
+#endif /* __VIR_XEN_XL_H__ */
--- /dev/null
+/*
+ * xen_xl_disk.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 <config.h>
+
+# include <stdio.h>
+
+# include "viralloc.h"
+# include "virstoragefile.h"
+# include "virstring.h"
+# include "domain_conf.h"
+# include "xen_xl.h"
+# include "xen_xl_disk_i.h"
+
+#define YY_NO_INPUT
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+/* 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 xl_disk_lexget_column(yyscan_t yyscanner);
+void xl_disk_lexset_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. */
+
+/* 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(xenXLDiskParserContext *dpc,
+ const char *what_respecified,
+ char **update,
+ const char *value)
+{
+ if (*update) {
+ if (**update) {
+ xenXLDiskParserError(dpc, value, what_respecified);
+ return;
+ }
+
+ VIR_FREE(*update); /* do not complain about overwriting empty strings */
+ }
+
+ ignore_value(VIR_STRDUP(*update, value));
+}
+
+#define DPC dpc /* our convention in lexer helper functions */
+
+/* Sets ->readwrite from the string. */
+static void
+setaccess(xenXLDiskParserContext *dpc, const char *str)
+{
+ if (STREQ(str, "rw") || STREQ(str, "w")) {
+ dpc->disk->src->readonly = 0;
+ } else if (STREQ(str, "r") || STREQ(str, "ro")) {
+ dpc->disk->src->readonly = 1;
+ } else if (STREQ(str, "w!") || STREQ(str, "!")) {
+ dpc->disk->src->readonly = 0;
+ dpc->disk->src->shared = 1;
+ } else {
+ xenXLDiskParserError(dpc, str, "unknown value for access");
+ }
+ dpc->access_set = 1;
+}
+
+/* Sets ->format from the string. IDL should provide something for this. */
+static void
+setformat(xenXLDiskParserContext *dpc, const char *str)
+{
+ if (STREQ(str, "") || STREQ(str, "raw"))
+ virDomainDiskSetFormat(dpc->disk, VIR_STORAGE_FILE_RAW);
+ else if (STREQ(str, "qcow"))
+ virDomainDiskSetFormat(dpc->disk, VIR_STORAGE_FILE_QCOW);
+ else if (STREQ(str, "qcow2"))
+ virDomainDiskSetFormat(dpc->disk, VIR_STORAGE_FILE_QCOW2);
+ else if (STREQ(str, "vhd"))
+ virDomainDiskSetFormat(dpc->disk, VIR_STORAGE_FILE_VHD);
+ else
+ xenXLDiskParserError(dpc, str, "unknown value for format");
+}
+
+
+/* Sets ->backend from the string. IDL should provide something for this. */
+static void
+setdrivertype(xenXLDiskParserContext *dpc, const char *str)
+{
+ if (STREQ(str, "phy"))
+ ignore_value(virDomainDiskSetDriver(dpc->disk, "phy"));
+ else if (STREQ(str, "tap"))
+ ignore_value(virDomainDiskSetDriver(dpc->disk, "tap"));
+ else if (STREQ(str, "file") || STREQ(str, ""))
+ ignore_value(virDomainDiskSetDriver(dpc->disk, "qemu"));
+ else
+ xenXLDiskParserError(dpc, str, "unknown value for backendtype");
+}
+
+
+/* Handles a vdev positional parameter which includes a devtype. */
+static int
+vdev_and_devtype(xenXLDiskParserContext *dpc, char *str)
+{
+ /* returns 1 if it was <vdev>:<devtype>, 0 (doing nothing) otherwise */
+ char *colon = strrchr(str, ':');
+ if (!colon)
+ return 0;
+
+ *colon++ = 0;
+ SAVESTRING("vdev", dst, str);
+
+ if (STREQ(colon,"cdrom")) {
+ DPC->disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
+ } else if (STREQ(colon, "disk")) {
+ DPC->disk->device = VIR_DOMAIN_DISK_DEVICE_DISK;
+ } else {
+ xenXLDiskParserError(DPC, colon, "unknown deprecated type");
+ }
+ return 1;
+}
+
+#undef DPC /* needs to be defined differently the actual lexer */
+#define DPC ((xenXLDiskParserContext*)yyextra)
+
+%}
+
+%option warn
+%option nodefault
+%option batch
+%option 8bit
+%option noyywrap
+%option reentrant
+%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->device = VIR_DOMAIN_DISK_DEVICE_CDROM; }
+devtype=cdrom,? { DPC->disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM; }
+devtype=disk,? { DPC->disk->device = VIR_DOMAIN_DISK_DEVICE_DISK; }
+devtype=[^,]*,? { xenXLDiskParserError(DPC, yytext,"unknown value for type"); }
+
+access=[^,]*,? { STRIP(','); setaccess(DPC, FROMEQUALS); }
+backendtype=[^,]*,? { STRIP(','); setdrivertype(DPC, FROMEQUALS); }
+
+vdev=[^,]*,? { STRIP(','); SAVESTRING("vdev", dst, FROMEQUALS); }
+
+ /* the target magic parameter, eats the rest of the string */
+
+target=.* { STRIP(','); SAVESTRING("target", src->path, FROMEQUALS); }
+
+ /* unknown parameters */
+
+[a-z][-a-z0-9]*=[^,],? { xenXLDiskParserError(DPC, yytext, "unknown parameter"); }
+
+ /* 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;
+ setformat(DPC, yytext);
+ }
+
+tapdisk:/.* { DPC->had_depr_prefix=1; }
+tap2?:/.* { DPC->had_depr_prefix=1; }
+aio:/.* { DPC->had_depr_prefix=1; }
+ioemu:/.* { DPC->had_depr_prefix=1; }
+file:/.* { DPC->had_depr_prefix=1; }
+phy:/.* { DPC->had_depr_prefix=1; }
+[a-z][a-z0-9]*:/([^a-z0-9].*)? {
+ xenXLDiskParserError(DPC, yytext, "unknown deprecated disk prefix");
+ return 0;
+ }
+
+ /* positional parameters */
+
+[^=,]*,|[^=,]+,? {
+ STRIP(',');
+
+ if (DPC->err) {
+ /* previous errors may just lead to subsequent ones */
+ } else if (!DPC->disk->src->path) {
+ SAVESTRING("target", src->path, yytext);
+ } else if (DPC->disk->src->format == VIR_STORAGE_FILE_LAST){
+ setformat(DPC, yytext);
+ }
+ else if (!DPC->disk->dst) {
+ if (!vdev_and_devtype(DPC, yytext))
+ SAVESTRING("vdev", dst, yytext);
+ } else if (!DPC->access_set) {
+ DPC->access_set = 1;
+ setaccess(DPC, yytext);
+ } else {
+ xenXLDiskParserError(DPC, yytext, "too many positional parameters");
+ return 0; /* don't print any more errors */
+ }
+}
+
+. {
+ BEGIN(LEXERR);
+ yymore();
+}
+<LEXERR>.* {
+ xenXLDiskParserError(DPC, yytext, "bad disk syntax");
+ return 0;
+}
--- /dev/null
+/*
+ * xen_xl_disk_i.h - common header for disk spec parser
+ *
+ * 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.
+ */
+
+#ifndef __VIR_XEN_XL_DISK_I_H__
+# define __VIR_XEN_XL_DISK_I_H__
+
+# include "virconf.h"
+# include "domain_conf.h"
+
+
+typedef struct {
+ int err;
+ void *scanner;
+ YY_BUFFER_STATE buf;
+ virDomainDiskDefPtr disk;
+ int access_set;
+ int had_depr_prefix;
+ const char *spec;
+} xenXLDiskParserContext;
+
+void xenXLDiskParserError(xenXLDiskParserContext *dpc,
+ const char *erroneous,
+ const char *message);
+
+#endif /* __VIR_XEN_XL_DISK_I_H__ */