summaryrefslogtreecommitdiff
path: root/build/parseSpec.c
diff options
context:
space:
mode:
Diffstat (limited to 'build/parseSpec.c')
-rw-r--r--build/parseSpec.c312
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 */