From patchwork Tue Aug 13 14:48:27 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony PERARD X-Patchwork-Id: 11092379 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 911261395 for ; Tue, 13 Aug 2019 14:49:58 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7FACC22A65 for ; Tue, 13 Aug 2019 14:49:58 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 74032285BD; Tue, 13 Aug 2019 14:49:58 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.0 required=2.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id B883622A65 for ; Tue, 13 Aug 2019 14:49:56 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hxY6E-0003jT-5r; Tue, 13 Aug 2019 14:48:34 +0000 Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hxY6C-0003jH-Rd for xen-devel@lists.xenproject.org; Tue, 13 Aug 2019 14:48:32 +0000 X-Inumbo-ID: 6ae77358-bdd9-11e9-8b5b-27832ad6d868 Received: from esa2.hc3370-68.iphmx.com (unknown [216.71.145.153]) by us1-rack-iad1.inumbo.com (Halon) with ESMTPS id 6ae77358-bdd9-11e9-8b5b-27832ad6d868; Tue, 13 Aug 2019 14:48:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1565707711; h=from:to:cc:subject:date:message-id:mime-version: content-transfer-encoding; bh=dQ25kYn2AJJKofzglLJawR2DVoLC54CAWR0+LQrBizs=; b=Sdeqib6HLjxilYLnEfOQSqfoMF2lka4tBQgMD11uPJc07Wo+Y2CqOJrK 9PJhscjH1LMmwfIpiEYVz2z+al73nyFLHTE82b5vEopKWYYsNs6LYzyzL qcfYuSGHuRRBrvUELWdmiJZOyqzEfkRy8MCTZ1DCLvFOhtgfbeBgSjhAR s=; Authentication-Results: esa2.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none; spf=None smtp.pra=anthony.perard@citrix.com; spf=Pass smtp.mailfrom=anthony.perard@citrix.com; spf=None smtp.helo=postmaster@mail.citrix.com Received-SPF: None (esa2.hc3370-68.iphmx.com: no sender authenticity information available from domain of anthony.perard@citrix.com) identity=pra; client-ip=162.221.158.21; receiver=esa2.hc3370-68.iphmx.com; envelope-from="anthony.perard@citrix.com"; x-sender="anthony.perard@citrix.com"; x-conformance=sidf_compatible Received-SPF: Pass (esa2.hc3370-68.iphmx.com: domain of anthony.perard@citrix.com designates 162.221.158.21 as permitted sender) identity=mailfrom; client-ip=162.221.158.21; receiver=esa2.hc3370-68.iphmx.com; envelope-from="anthony.perard@citrix.com"; x-sender="anthony.perard@citrix.com"; x-conformance=sidf_compatible; x-record-type="v=spf1"; x-record-text="v=spf1 ip4:209.167.231.154 ip4:178.63.86.133 ip4:195.66.111.40/30 ip4:85.115.9.32/28 ip4:199.102.83.4 ip4:192.28.146.160 ip4:192.28.146.107 ip4:216.52.6.88 ip4:216.52.6.188 ip4:162.221.158.21 ip4:162.221.156.83 ~all" Received-SPF: None (esa2.hc3370-68.iphmx.com: no sender authenticity information available from domain of postmaster@mail.citrix.com) identity=helo; client-ip=162.221.158.21; receiver=esa2.hc3370-68.iphmx.com; envelope-from="anthony.perard@citrix.com"; x-sender="postmaster@mail.citrix.com"; x-conformance=sidf_compatible IronPort-SDR: +gs+QiX2Y+8P6h09i4Yz6d5lk8N/mJwjZlvrbv+z6D5LIuD92KToerNbCy0h7P3IfRr/TVgcOH kG3cr0LfQP6fGa+u80xTAjhecdKKIfeva4z8Lcq4JiDacWRbcgSvIrpgxM1AhG/AZMJtqlAee5 hAAiAmsC2CvLEXeBYTPgpZNmdXBKBr1+gY7Qji9zxTEAqn68mgTh1on7ja8EkPQbcAt3wPectr 3sIMRYgL+g9Pdp3KdjtaTs+k9SHr7KPR/oBKtnasdnDaLpMP+YlKFqkX9h64o01660vDhJRgd/ gww= X-SBRS: 2.7 X-MesageID: 4208104 X-Ironport-Server: esa2.hc3370-68.iphmx.com X-Remote-IP: 162.221.158.21 X-Policy: $RELAYED X-IronPort-AV: E=Sophos;i="5.64,381,1559534400"; d="scan'208";a="4208104" From: Anthony PERARD To: Date: Tue, 13 Aug 2019 15:48:27 +0100 Message-ID: <20190813144827.6318-1-anthony.perard@citrix.com> X-Mailer: git-send-email 2.22.0 MIME-Version: 1.0 Subject: [Xen-devel] [PATCH] libxlu: Handle += in config files X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Anthony PERARD , Andrew Cooper , Ian Jackson , Wei Liu Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP Handle += of both strings and lists. If += is used for config options expected to be numbers, then a warning is printed and the config option ignored (because xl ignores config options with errors). This is to be used for development purposes, where modifying config option can be done on the `xl create' command line. One could have a cmdline= in the cfg file, and specify cmdline+= on the `xl create` command line without the need to write the whole cmdline in `xl' command line but simply append to the one in the cfg file. Or add an extra vif or disk by simply having "vif += [ '', ];" in the `xl' cmdline. Signed-off-by: Anthony PERARD Acked-by: Ian Jackson --- Notes: Commiter, the libxlu_cfg_?.[hc] files needs to be regenerated. (with make) This is a different proposal to Andrew's patch: <20190805144910.20223-1-andrew.cooper3@citrix.com> [PATCH] tools/xl: Make extra= usable in combination with cmdline= tools/libxl/libxlu_cfg.c | 100 +++++++++++++++++++++++++++++++++- tools/libxl/libxlu_cfg_i.h | 1 + tools/libxl/libxlu_cfg_l.l | 1 + tools/libxl/libxlu_cfg_y.y | 4 +- tools/libxl/libxlu_internal.h | 1 + tools/libxl/libxlutil.h | 5 ++ 6 files changed, 109 insertions(+), 3 deletions(-) diff --git a/tools/libxl/libxlu_cfg.c b/tools/libxl/libxlu_cfg.c index 5838f6885e..72815d25dd 100644 --- a/tools/libxl/libxlu_cfg.c +++ b/tools/libxl/libxlu_cfg.c @@ -276,6 +276,14 @@ int xlu_cfg_get_long(const XLU_Config *cfg, const char *n, char *ep; e= find_atom(cfg,n,&set,dont_warn); if (e) return e; + if (set->op == XLU_OP_ADDITION) { + if (!dont_warn) + fprintf(cfg->report, + "%s:%d: warning: can't use += with numbers" + " for parameter `%s'\n", + cfg->config_source, set->lineno, n); + return EINVAL; + } errno= 0; l= strtol(set->value->u.string, &ep, 0); e= errno; if (errno) { @@ -450,23 +458,111 @@ void xlu__cfg_list_append(CfgParseContext *ctx, list->u.list.nvalues++; } +static int xlu__cfg_concat_vals(CfgParseContext *ctx, + XLU_ConfigValue *prev, + XLU_ConfigValue *to_add) +{ + int r; + + if (prev->type != to_add->type) { + xlu__cfgl_lexicalerror(ctx, + "can't add [list] to \"string\" or vice versa"); + return EINVAL; + } + + switch (to_add->type) { + case XLU_STRING: { + char *new_string = NULL; + + r = asprintf(&new_string, "%s%s", prev->u.string, + to_add->u.string); + if (r < 0) { + return errno; + } + free(to_add->u.string); + to_add->u.string = new_string; + return 0; + } + case XLU_LIST: { + XLU_ConfigList *const prev_list = &prev->u.list; + XLU_ConfigList *const cur_list = &to_add->u.list; + int nvalues; + + if (prev->u.list.nvalues > INT_MAX - to_add->u.list.nvalues) { + return ERANGE; + } + nvalues = prev->u.list.nvalues + to_add->u.list.nvalues; + + if (nvalues >= cur_list->avalues) { + XLU_ConfigValue **new_vals; + new_vals = realloc(cur_list->values, + nvalues * sizeof(*new_vals)); + if (!new_vals) { + return ENOMEM; + } + cur_list->avalues = nvalues; + cur_list->values = new_vals; + } + + /* make space for `prev' into `to_add' */ + memmove(cur_list->values + prev_list->nvalues, + cur_list->values, + cur_list->nvalues * sizeof(XLU_ConfigValue *)); + /* move values from `prev' to `to_add' as the list in `prev' will + * not be reachable by find(). */ + memcpy(cur_list->values, + prev_list->values, + prev_list->nvalues * sizeof(XLU_ConfigValue *)); + cur_list->nvalues = nvalues; + prev_list->nvalues = 0; + memset(prev_list->values, 0, + prev_list->nvalues * sizeof(XLU_ConfigValue *)); + return 0; + } + default: + abort(); + } + return -1; +} + void xlu__cfg_set_store(CfgParseContext *ctx, char *name, + enum XLU_Operation op, XLU_ConfigValue *val, int lineno) { XLU_ConfigSetting *set; + int r; - if (ctx->err) return; + if (ctx->err) goto out; assert(name); + + if (op == XLU_OP_ADDITION) { + /* If we have += concatenate with previous value with same name */ + XLU_ConfigSetting *prev_set = find(ctx->cfg, name); + if (prev_set) { + r = xlu__cfg_concat_vals(ctx, prev_set->value, val); + if (r) { + ctx->err = r; + goto out; + } + } + } + set = malloc(sizeof(*set)); if (!set) { ctx->err = errno; - return; + goto out; } set->name= name; set->value = val; + set->op = op; set->lineno= lineno; set->next= ctx->cfg->settings; ctx->cfg->settings= set; + return; +out: + assert(ctx->err); + free(name); + xlu__cfg_value_free(val); } char *xlu__cfgl_strdup(CfgParseContext *ctx, const char *src) { diff --git a/tools/libxl/libxlu_cfg_i.h b/tools/libxl/libxlu_cfg_i.h index 1b59b3312f..87b19df311 100644 --- a/tools/libxl/libxlu_cfg_i.h +++ b/tools/libxl/libxlu_cfg_i.h @@ -24,6 +24,7 @@ void xlu__cfg_set_free(XLU_ConfigSetting *set); void xlu__cfg_set_store(CfgParseContext*, char *name, + enum XLU_Operation op, XLU_ConfigValue *val, int lineno); XLU_ConfigValue *xlu__cfg_string_mk(CfgParseContext *ctx, char *atom, YYLTYPE *loc); diff --git a/tools/libxl/libxlu_cfg_l.l b/tools/libxl/libxlu_cfg_l.l index e0ea8cfcb3..390d6e2c2b 100644 --- a/tools/libxl/libxlu_cfg_l.l +++ b/tools/libxl/libxlu_cfg_l.l @@ -66,6 +66,7 @@ void xlu__cfg_yyset_column(int column_no, yyscan_t yyscanner); , { GOT(','); } \[ { GOT('['); } \] { GOT(']'); } +\+\= { GOT(OP_ADD); } \= { GOT('='); } \; { GOT(';'); } diff --git a/tools/libxl/libxlu_cfg_y.y b/tools/libxl/libxlu_cfg_y.y index a923f7672d..020fc63eb3 100644 --- a/tools/libxl/libxlu_cfg_y.y +++ b/tools/libxl/libxlu_cfg_y.y @@ -38,6 +38,7 @@ %token IDENT STRING NUMBER NEWLINE %type atom %destructor { free($$); } atom IDENT STRING NUMBER +%token OP_ADD "+=" %type value valuelist values %destructor { xlu__cfg_value_free($$); } value valuelist values @@ -54,7 +55,8 @@ stmt: assignment endstmt | endstmt | error NEWLINE -assignment: IDENT '=' value { xlu__cfg_set_store(ctx,$1,$3,@3.first_line); } +assignment: IDENT '=' value { xlu__cfg_set_store(ctx,$1,XLU_OP_ASSIGNMENT,$3,@3.first_line); } + | IDENT "+=" value { xlu__cfg_set_store(ctx,$1,XLU_OP_ADDITION,$3,@3.first_line); } endstmt: NEWLINE | ';' diff --git a/tools/libxl/libxlu_internal.h b/tools/libxl/libxlu_internal.h index 0acdde38f4..1f7559ecd9 100644 --- a/tools/libxl/libxlu_internal.h +++ b/tools/libxl/libxlu_internal.h @@ -53,6 +53,7 @@ typedef struct XLU_ConfigSetting { /* transparent */ struct XLU_ConfigSetting *next; char *name; XLU_ConfigValue *value; + enum XLU_Operation op; int lineno; } XLU_ConfigSetting; diff --git a/tools/libxl/libxlutil.h b/tools/libxl/libxlutil.h index e81b644c01..057cc25cb2 100644 --- a/tools/libxl/libxlutil.h +++ b/tools/libxl/libxlutil.h @@ -25,6 +25,11 @@ enum XLU_ConfigValueType { XLU_LIST, }; +enum XLU_Operation { + XLU_OP_ASSIGNMENT = 0, + XLU_OP_ADDITION, +}; + /* Unless otherwise stated, all functions return an errno value. */ typedef struct XLU_Config XLU_Config; typedef struct XLU_ConfigList XLU_ConfigList;