From 2b64fdd9c7c922b0f516e93f35137a6f18805e0d Mon Sep 17 00:00:00 2001 From: Michael Schroeder Date: Fri, 12 Sep 2014 16:58:18 +0200 Subject: [PATCH] Parse rich dependencies in spec files We use the callback to normalize the rich dependency (i.e. strip spaces, canonicalize op names). --- build/parseReqs.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/build/parseReqs.c b/build/parseReqs.c index af77d4e51..3903d7972 100644 --- a/build/parseReqs.c +++ b/build/parseReqs.c @@ -49,6 +49,61 @@ static rpmRC checkDep(rpmSpec spec, char *N, char *EVR, char **emsg) return RPMRC_OK; } +struct parseRCPOTRichData { + rpmSpec spec; + StringBuf sb; + int no_if; +}; + +/* Callback for the rich dependency parser. We use this to do check for invalid + * characters and to build a normailzed version of the dependency */ +static rpmRC parseRCPOTRichCB(void *cbdata, rpmrichParseType type, + const char *n, int nl, const char *e, int el, rpmsenseFlags sense, + rpmrichOp op, char **emsg) { + struct parseRCPOTRichData *data = cbdata; + StringBuf sb = data->sb; + rpmRC rc = RPMRC_OK; + + if (type == RPMRICH_PARSE_ENTER) { + appendStringBuf(sb, "("); + } else if (type == RPMRICH_PARSE_LEAVE) { + appendStringBuf(sb, ")"); + } else if (type == RPMRICH_PARSE_SIMPLE) { + char *N = xmalloc(nl + 1); + char *EVR = NULL; + rstrlcpy(N, n, nl + 1); + appendStringBuf(sb, N); + if (el) { + char rel[6], *rp = rel; + EVR = xmalloc(el + 1); + rstrlcpy(EVR, e, el + 1); + *rp++ = ' '; + if (sense & RPMSENSE_LESS) + *rp++ = '<'; + if (sense & RPMSENSE_GREATER) + *rp++ = '>'; + if (sense & RPMSENSE_EQUAL) + *rp++ = '='; + *rp++ = ' '; + *rp = 0; + appendStringBuf(sb, rel); + appendStringBuf(sb, EVR); + } + rc = checkDep(data->spec, N, EVR, emsg); + _free(N); + _free(EVR); + } else if (type == RPMRICH_PARSE_OP) { + if (op == RPMRICHOP_IF && data->no_if) { + rasprintf(emsg, _("IF not allowed in conflicts dependencies")); + rc = RPMRC_FAIL; + } + appendStringBuf(sb, " "); + appendStringBuf(sb, rpmrichOpStr(op)); + appendStringBuf(sb, " "); + } + return rc; +} + rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN, int index, rpmsenseFlags tagflags) { @@ -127,6 +182,31 @@ rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN, Flags = (tagflags & ~RPMSENSE_SENSEMASK); + if (r[0] == '(') { + struct parseRCPOTRichData data; + if (nametag != RPMTAG_REQUIRENAME && nametag != RPMTAG_CONFLICTNAME && + nametag != RPMTAG_RECOMMENDNAME && nametag != RPMTAG_SUPPLEMENTNAME && + nametag != RPMTAG_SUGGESTNAME && nametag != RPMTAG_ENHANCENAME) { + rasprintf(&emsg, _("No rich dependencies allowed for this type")); + goto exit; + } + data.spec = spec; + data.sb = newStringBuf(); + data.no_if = (nametag == RPMTAG_CONFLICTNAME); + if (rpmrichParse(&r, &emsg, parseRCPOTRichCB, &data) != RPMRC_OK) { + freeStringBuf(data.sb); + goto exit; + } + if (addReqProv(pkg, nametag, getStringBuf(data.sb), NULL, Flags | RPMSENSE_RICH, index)) { + rasprintf(&emsg, _("invalid dependency")); + freeStringBuf(data.sb); + goto exit; + } + freeStringBuf(data.sb); + re = r; + continue; + } + re = r; SKIPNONWHITE(re); N = xmalloc((re-r) + 1);