diff options
Diffstat (limited to 'build/parseSpec.c')
-rw-r--r-- | build/parseSpec.c | 312 |
1 files changed, 266 insertions, 46 deletions
diff --git a/build/parseSpec.c b/build/parseSpec.c index fb137047a..d0c42a43e 100644 --- a/build/parseSpec.c +++ b/build/parseSpec.c @@ -6,6 +6,9 @@ #include "system.h" #include <errno.h> +#ifdef HAVE_ICONV +#include <iconv.h> +#endif #include <rpm/rpmtypes.h> #include <rpm/rpmlib.h> /* RPM_MACHTABLE & related */ @@ -28,7 +31,8 @@ typedef struct OpenFileInfo { char * fileName; FILE *fp; int lineNum; - char readBuf[BUFSIZ]; + char *readBuf; + size_t readBufLen; const char * readPtr; struct OpenFileInfo * next; } OFI_t; @@ -60,6 +64,16 @@ static const struct PartRec { { PART_TRIGGERIN, LEN_AND_STR("%trigger")}, { PART_VERIFYSCRIPT, LEN_AND_STR("%verifyscript")}, { PART_POLICIES, LEN_AND_STR("%sepolicy")}, + { PART_FILETRIGGERIN, LEN_AND_STR("%filetriggerin")}, + { PART_FILETRIGGERIN, LEN_AND_STR("%filetrigger")}, + { PART_FILETRIGGERUN, LEN_AND_STR("%filetriggerun")}, + { PART_FILETRIGGERPOSTUN, LEN_AND_STR("%filetriggerpostun")}, + { PART_TRANSFILETRIGGERIN, LEN_AND_STR("%transfiletriggerin")}, + { PART_TRANSFILETRIGGERIN, LEN_AND_STR("%transfiletrigger")}, + { PART_TRANSFILETRIGGERUN, LEN_AND_STR("%transfiletriggerun")}, + { PART_TRANSFILETRIGGERUN, LEN_AND_STR("%transfiletriggerun")}, + { PART_TRANSFILETRIGGERPOSTUN, LEN_AND_STR("%transfiletriggerpostun")}, + { PART_EMPTY, LEN_AND_STR("%end")}, {0, 0, 0} }; @@ -102,11 +116,14 @@ static int matchTok(const char *token, const char *line) return rc; } -void handleComments(char *s) +int handleComments(char *s) { SKIPSPACE(s); - if (*s == '#') + if (*s == '#') { *s = '\0'; + return 1; + } + return 0; } /* Push a file to spec's file stack, return the newly pushed entry */ @@ -117,6 +134,8 @@ static OFI_t * pushOFI(rpmSpec spec, const char *fn) ofi->fp = NULL; ofi->fileName = xstrdup(fn); ofi->lineNum = 0; + ofi->readBufLen = BUFSIZ; + ofi->readBuf = xmalloc(ofi->readBufLen); ofi->readBuf[0] = '\0'; ofi->readPtr = NULL; ofi->next = spec->fileStack; @@ -135,6 +154,7 @@ static OFI_t * popOFI(rpmSpec spec) if (ofi->fp) fclose(ofi->fp); free(ofi->fileName); + free(ofi->readBuf); free(ofi); } return spec->fileStack; @@ -151,8 +171,57 @@ static int restoreFirstChar(rpmSpec spec) return 0; } +static int expandMacrosInSpecBuf(rpmSpec spec, int strip) +{ + char *lbuf = NULL; + int isComment = 0; + + /* Don't expand macros (eg. %define) in false branch of %if clause */ + if (!spec->readStack->reading) + return 0; + + lbuf = spec->lbuf; + SKIPSPACE(lbuf); + if (lbuf[0] == '#') + isComment = 1; + + + if (rpmExpandMacros(spec->macros, spec->lbuf, &lbuf, 0) < 0) { + rpmlog(RPMLOG_ERR, _("line %d: %s\n"), + spec->lineNum, spec->lbuf); + return 1; + } + + if (strip & STRIP_COMMENTS && isComment) { + char *bufA = spec->lbuf; + char *bufB = lbuf; + + while (*bufA != '\0' && *bufB != '\0') { + if (*bufA == '%' && *(bufA + 1) == '%') + bufA++; + + if (*bufA != *bufB) + break; + + bufA++; + bufB++; + } + + if (*bufA != '\0' || *bufB != '\0') + rpmlog(RPMLOG_WARNING, + _("Macro expanded in comment on line %d: %s\n"), + spec->lineNum, bufA); + } + + free(spec->lbuf); + spec->lbuf = lbuf; + spec->lbufSize = strlen(spec->lbuf) + 1; + + return 0; +} + /* Return zero on success, 1 if we need to read more and -1 on errors. */ -static int copyNextLineFromOFI(rpmSpec spec, OFI_t *ofi) +static int copyNextLineFromOFI(rpmSpec spec, OFI_t *ofi, int strip) { /* Expand next line from file into line buffer */ if (!(spec->nextline && *spec->nextline)) { @@ -203,13 +272,9 @@ static int copyNextLineFromOFI(rpmSpec spec, OFI_t *ofi) } spec->lbufOff = 0; - /* Don't expand macros (eg. %define) in false branch of %if clause */ - if (spec->readStack->reading && - expandMacros(spec, spec->macros, spec->lbuf, spec->lbufSize)) { - rpmlog(RPMLOG_ERR, _("line %d: %s\n"), - spec->lineNum, spec->lbuf); - return -1; - } + if (expandMacrosInSpecBuf(spec, strip)) + return -1; + spec->nextline = spec->lbuf; } return 0; @@ -258,7 +323,7 @@ retry: /* Make sure we have something in the read buffer */ if (!(ofi->readPtr && *(ofi->readPtr))) { - if (!fgets(ofi->readBuf, BUFSIZ, ofi->fp)) { + if (getline(&ofi->readBuf, &ofi->readBufLen, ofi->fp) <= 0) { /* EOF, remove this file from the stack */ ofi = popOFI(spec); @@ -280,8 +345,8 @@ retry: do { \ char *os = s; \ char *exp = rpmExpand(token, NULL); \ - while(*s && !risblank(*s)) s++; \ - while(*s && risblank(*s)) s++; \ + while (*s && !risblank(*s)) s++; \ + while (*s && risblank(*s)) s++; \ if (!*s) { \ rpmlog(RPMLOG_ERR, _("%s:%d: Argument expected for %s\n"), ofi->fileName, ofi->lineNum, os); \ free(exp); \ @@ -319,7 +384,7 @@ int readLine(rpmSpec spec, int strip) ofi = spec->fileStack; /* Copy next file line into the spec line buffer */ - rc = copyNextLineFromOFI(spec, ofi); + rc = copyNextLineFromOFI(spec, ofi, strip); if (rc > 0) { if (startLine == 0) startLine = spec->lineNum; @@ -349,12 +414,12 @@ int readLine(rpmSpec spec, int strip) match = !match; } else if (ISMACROWITHARG(s, "%if")) { s += 3; - match = parseExpressionBoolean(spec, s); + match = parseExpressionBoolean(s); if (match < 0) { rpmlog(RPMLOG_ERR, - _("%s:%d: bad %%if condition, continuing nevertheless\n"), + _("%s:%d: bad %%if condition\n"), ofi->fileName, ofi->lineNum); - match = 0; + return PART_ERROR; } } else if (ISMACRO(s, "%else")) { if (! spec->readStack->next) { @@ -385,10 +450,13 @@ int readLine(rpmSpec spec, int strip) fileName = s+8; SKIPSPACE(fileName); endFileName = fileName; - SKIPNONSPACE(endFileName); - p = endFileName; - SKIPSPACE(p); - if (*fileName == '\0' || *p != '\0') { + do { + SKIPNONSPACE(endFileName); + p = endFileName; + SKIPSPACE(p); + if (*p != '\0') endFileName = p; + } while (*p != '\0'); + if (*fileName == '\0') { rpmlog(RPMLOG_ERR, _("%s:%d: malformed %%include statement\n"), ofi->fileName, ofi->lineNum); return PART_ERROR; @@ -453,22 +521,26 @@ static const rpmTagVal sourceTags[] = { static void initSourceHeader(rpmSpec spec) { + Package sourcePkg = spec->sourcePackage; struct Source *srcPtr; - if (spec->sourceHeader) + if (headerIsEntry(sourcePkg->header, RPMTAG_NAME)) return; - spec->sourceHeader = headerNew(); /* Only specific tags are added to the source package header */ - headerCopyTags(spec->packages->header, spec->sourceHeader, sourceTags); + headerCopyTags(spec->packages->header, sourcePkg->header, sourceTags); /* Add the build restrictions */ + for (int i=0; i<PACKAGE_NUM_DEPS; i++) { + rpmdsPutToHeader(sourcePkg->dependencies[i], sourcePkg->header); + } + { HeaderIterator hi = headerInitIterator(spec->buildRestrictions); struct rpmtd_s td; while (headerNext(hi, &td)) { if (rpmtdCount(&td) > 0) { - (void) headerPut(spec->sourceHeader, &td, HEADERPUT_DEFAULT); + (void) headerPut(sourcePkg->header, &td, HEADERPUT_DEFAULT); } rpmtdFreeData(&td); } @@ -476,23 +548,23 @@ static void initSourceHeader(rpmSpec spec) } if (spec->BANames && spec->BACount > 0) { - headerPutStringArray(spec->sourceHeader, RPMTAG_BUILDARCHS, + headerPutStringArray(sourcePkg->header, RPMTAG_BUILDARCHS, spec->BANames, spec->BACount); } /* Add tags for sources and patches */ for (srcPtr = spec->sources; srcPtr != NULL; srcPtr = srcPtr->next) { if (srcPtr->flags & RPMBUILD_ISSOURCE) { - headerPutString(spec->sourceHeader, RPMTAG_SOURCE, srcPtr->source); + headerPutString(sourcePkg->header, RPMTAG_SOURCE, srcPtr->source); if (srcPtr->flags & RPMBUILD_ISNO) { - headerPutUint32(spec->sourceHeader, RPMTAG_NOSOURCE, + headerPutUint32(sourcePkg->header, RPMTAG_NOSOURCE, &srcPtr->num, 1); } } if (srcPtr->flags & RPMBUILD_ISPATCH) { - headerPutString(spec->sourceHeader, RPMTAG_PATCH, srcPtr->source); + headerPutString(sourcePkg->header, RPMTAG_PATCH, srcPtr->source); if (srcPtr->flags & RPMBUILD_ISNO) { - headerPutUint32(spec->sourceHeader, RPMTAG_NOPATCH, + headerPutUint32(sourcePkg->header, RPMTAG_NOPATCH, &srcPtr->num, 1); } } @@ -500,19 +572,17 @@ static void initSourceHeader(rpmSpec spec) } /* Add extra provides to package. */ -static void addPackageProvides(Header h) +void addPackageProvides(Package pkg) { const char *arch, *name; char *evr, *isaprov; rpmsenseFlags pflags = RPMSENSE_EQUAL; /* <name> = <evr> provide */ - name = headerGetString(h, RPMTAG_NAME); - arch = headerGetString(h, RPMTAG_ARCH); - evr = headerGetAsString(h, RPMTAG_EVR); - headerPutString(h, RPMTAG_PROVIDENAME, name); - headerPutString(h, RPMTAG_PROVIDEVERSION, evr); - headerPutUint32(h, RPMTAG_PROVIDEFLAGS, &pflags, 1); + name = headerGetString(pkg->header, RPMTAG_NAME); + arch = headerGetString(pkg->header, RPMTAG_ARCH); + evr = headerGetAsString(pkg->header, RPMTAG_EVR); + addReqProv(pkg, RPMTAG_PROVIDENAME, name, evr, pflags, 0); /* * <name>(<isa>) = <evr> provide @@ -521,9 +591,7 @@ static void addPackageProvides(Header h) */ isaprov = rpmExpand(name, "%{?_isa}", NULL); if (!rstreq(arch, "noarch") && !rstreq(name, isaprov)) { - headerPutString(h, RPMTAG_PROVIDENAME, isaprov); - headerPutString(h, RPMTAG_PROVIDEVERSION, evr); - headerPutUint32(h, RPMTAG_PROVIDEFLAGS, &pflags, 1); + addReqProv(pkg, RPMTAG_PROVIDENAME, isaprov, evr, pflags, 0); } free(isaprov); free(evr); @@ -545,8 +613,13 @@ static void addTargets(Package Pkgs) headerPutString(pkg->header, RPMTAG_PLATFORM, platform); headerPutString(pkg->header, RPMTAG_OPTFLAGS, optflags); + /* Add manual dependencies early for rpmspec etc to look at */ + addPackageProvides(pkg); + for (int i=0; i<PACKAGE_NUM_DEPS; i++) { + rpmdsPutToHeader(pkg->dependencies[i], pkg->header); + } + pkg->ds = rpmdsThis(pkg->header, RPMTAG_REQUIRENAME, RPMSENSE_EQUAL); - addPackageProvides(pkg->header); } free(platform); free(arch); @@ -554,10 +627,134 @@ static void addTargets(Package Pkgs) free(optflags); } +rpmRC checkForEncoding(Header h, int addtag) +{ + rpmRC rc = RPMRC_OK; +#if HAVE_ICONV + const char *encoding = "utf-8"; + rpmTagVal tag; + iconv_t ic; + char *dest = NULL; + size_t destlen = 0; + int strict = rpmExpandNumeric("%{_invalid_encoding_terminates_build}"); + HeaderIterator hi = headerInitIterator(h); + + ic = iconv_open(encoding, encoding); + if (ic == (iconv_t) -1) { + rpmlog(RPMLOG_WARNING, + _("encoding %s not supported by system\n"), encoding); + goto exit; + } + + while ((tag = headerNextTag(hi)) != RPMTAG_NOT_FOUND) { + struct rpmtd_s td; + const char *src = NULL; + + if (rpmTagGetClass(tag) != RPM_STRING_CLASS) + continue; + + headerGet(h, tag, &td, (HEADERGET_RAW|HEADERGET_MINMEM)); + while ((src = rpmtdNextString(&td)) != NULL) { + size_t srclen = strlen(src); + size_t outlen, inlen = srclen; + char *out, *in = (char *) src; + + if (destlen < srclen) { + destlen = srclen * 2; + dest = xrealloc(dest, destlen); + } + out = dest; + outlen = destlen; + + /* reset conversion state */ + iconv(ic, NULL, &inlen, &out, &outlen); + + if (iconv(ic, &in, &inlen, &out, &outlen) == (size_t) -1) { + rpmlog(strict ? RPMLOG_ERR : RPMLOG_WARNING, + _("Package %s: invalid %s encoding in %s: %s - %s\n"), + headerGetString(h, RPMTAG_NAME), + encoding, rpmTagGetName(tag), src, strerror(errno)); + rc = RPMRC_FAIL; + } + + } + rpmtdFreeData(&td); + } + + /* Stomp "known good utf" mark in header if requested */ + if (rc == RPMRC_OK && addtag) + headerPutString(h, RPMTAG_ENCODING, encoding); + if (!strict) + rc = RPMRC_OK; + +exit: + if (ic != (iconv_t) -1) + iconv_close(ic); + headerFreeIterator(hi); + free(dest); +#endif /* HAVE_ICONV */ + + return rc; +} + +static int parseEmpty(rpmSpec spec, int prevParsePart) +{ + int res = PART_ERROR; + int nextPart, rc; + char *line; + + line = spec->line + sizeof("%end") - 1; + SKIPSPACE(line); + if (line[0] != '\0') { + rpmlog(RPMLOG_ERR, + _("line %d: %%end doesn't take any arguments: %s\n"), + spec->lineNum, spec->line); + goto exit; + } + + if (prevParsePart == PART_EMPTY) { + rpmlog(RPMLOG_ERR, + _("line %d: %%end not expected here, no section to close: %s\n"), + spec->lineNum, spec->line); + goto exit; + } + + if ((rc = readLine(spec, STRIP_TRAILINGSPACE|STRIP_COMMENTS)) > 0) { + nextPart = PART_NONE; + } else if (rc < 0) { + goto exit; + } else { + while (! (nextPart = isPart(spec->line))) { + line = spec->line; + SKIPSPACE(line); + + if (line[0] != '\0') { + rpmlog(RPMLOG_ERR, + _("line %d doesn't belong to any section: %s\n"), + spec->lineNum, spec->line); + goto exit; + } + if ((rc = readLine(spec, STRIP_TRAILINGSPACE|STRIP_COMMENTS)) > 0) { + nextPart = PART_NONE; + break; + } else if (rc < 0) { + goto exit; + } + } + } + + res = nextPart; + +exit: + return res; +} + static rpmSpec parseSpec(const char *specFile, rpmSpecFlags flags, const char *buildRoot, int recursing) { int parsePart = PART_PREAMBLE; + int prevParsePart = PART_EMPTY; + int storedParsePart; int initialPackage = 1; rpmSpec spec; @@ -572,8 +769,8 @@ static rpmSpec parseSpec(const char *specFile, rpmSpecFlags flags, } else { spec->buildRoot = rpmGetPath("%{?buildroot:%{buildroot}}", NULL); } - addMacro(NULL, "_docdir", NULL, "%{_defaultdocdir}", RMIL_SPEC); - addMacro(NULL, "_licensedir", NULL, "%{_defaultlicensedir}", RMIL_SPEC); + rpmPushMacro(NULL, "_docdir", NULL, "%{_defaultdocdir}", RMIL_SPEC); + rpmPushMacro(NULL, "_licensedir", NULL, "%{_defaultlicensedir}", RMIL_SPEC); spec->recursing = recursing; spec->flags = flags; @@ -583,11 +780,15 @@ static rpmSpec parseSpec(const char *specFile, rpmSpecFlags flags, while (parsePart != PART_NONE) { int goterror = 0; + storedParsePart = parsePart; switch (parsePart) { case PART_ERROR: /* fallthrough */ default: goterror = 1; break; + case PART_EMPTY: + parsePart = parseEmpty(spec, prevParsePart); + break; case PART_PREAMBLE: parsePart = parsePreamble(spec, initialPackage); initialPackage = 0; @@ -619,6 +820,12 @@ static rpmSpec parseSpec(const char *specFile, rpmSpecFlags flags, case PART_TRIGGERIN: case PART_TRIGGERUN: case PART_TRIGGERPOSTUN: + case PART_FILETRIGGERIN: + case PART_FILETRIGGERUN: + case PART_FILETRIGGERPOSTUN: + case PART_TRANSFILETRIGGERIN: + case PART_TRANSFILETRIGGERUN: + case PART_TRANSFILETRIGGERPOSTUN: parsePart = parseScript(spec, parsePart); break; @@ -635,6 +842,7 @@ static rpmSpec parseSpec(const char *specFile, rpmSpecFlags flags, case PART_BUILDARCHITECTURES: break; } + prevParsePart = storedParsePart; if (goterror || parsePart >= PART_LAST) { goto errxit; @@ -654,13 +862,13 @@ static rpmSpec parseSpec(const char *specFile, rpmSpecFlags flags, /* Skip if not arch is not compatible. */ if (!rpmMachineScore(RPM_MACHTABLE_BUILDARCH, spec->BANames[x])) continue; - addMacro(NULL, "_target_cpu", NULL, spec->BANames[x], RMIL_RPMRC); + rpmPushMacro(NULL, "_target_cpu", NULL, spec->BANames[x], RMIL_RPMRC); spec->BASpecs[index] = parseSpec(specFile, flags, buildRoot, 1); if (spec->BASpecs[index] == NULL) { spec->BACount = index; goto errxit; } - delMacro(NULL, "_target_cpu"); + rpmPopMacro(NULL, "_target_cpu"); index++; } @@ -710,6 +918,18 @@ static rpmSpec parseSpec(const char *specFile, rpmSpecFlags flags, /* Add arch, os and platform, self-provides etc for each package */ addTargets(spec->packages); + /* Check for encoding in each package unless disabled */ + if (!(spec->flags & RPMSPEC_NOUTF8)) { + int badenc = 0; + for (Package pkg = spec->packages; pkg != NULL; pkg = pkg->next) { + if (checkForEncoding(pkg->header, 0) != RPMRC_OK) { + badenc = 1; + } + } + if (badenc) + goto errxit; + } + closeSpec(spec); exit: /* Assemble source header from parsed components */ |