From 44e5913dae80f1040748441af35fb02b840c397a Mon Sep 17 00:00:00 2001 From: jbj Date: Sun, 12 Nov 2000 11:11:49 +0000 Subject: [PATCH] - fine-grained Requires, remove install PreReq's from Requires db. CVS patchset: 4258 CVS date: 2000/11/12 11:11:49 --- CHANGES | 1 + build/files.c | 42 ++++++++++-- build/parsePreamble.c | 178 ++++++++++++++++++++++++++++++++++---------------- build/parseReqs.c | 2 +- build/parseScript.c | 84 ++++++++++++------------ build/parseSpec.c | 22 +++---- build/reqprov.c | 6 +- lib/depends.c | 160 ++++++++++++++++++++++++++++++++++----------- lib/rpmdb.c | 21 +++++- lib/rpmlib.h | 50 ++++++++++++-- lib/rpmlibprov.c | 15 +++-- tools/rpmsort.c | 6 +- 12 files changed, 415 insertions(+), 172 deletions(-) diff --git a/CHANGES b/CHANGES index 5aeb713..edcae51 100644 --- a/CHANGES +++ b/CHANGES @@ -29,6 +29,7 @@ - load headers as single contiguous region. - add region marker as RPM_BIN_TYPE in packages and database. - fix: don't headerCopy() relocateable packages if not relocating. + - fine-grained Requires, remove install PreReq's from Requires db. 3.0.6 -> 4.0 - use DIRNAMES/BASENAMES/DIRINDICES not FILENAMES in packages and db. diff --git a/build/files.c b/build/files.c index 424f5c2..d34332c 100644 --- a/build/files.c +++ b/build/files.c @@ -1747,9 +1747,30 @@ DepMsg_t depMsgs[] = { { "Provides", { "%{__find_provides}", NULL, NULL, NULL }, RPMTAG_PROVIDENAME, RPMTAG_PROVIDEVERSION, RPMTAG_PROVIDEFLAGS, 0, -1 }, - { "PreReq", { "%{__find_prereq}", NULL, NULL, NULL }, + { "PreReq", { NULL, NULL, NULL, NULL }, RPMTAG_REQUIRENAME, RPMTAG_REQUIREVERSION, RPMTAG_REQUIREFLAGS, RPMSENSE_PREREQ, 0 }, + { "Requires(interp)", { NULL, "interp", NULL, NULL }, + -1, -1, RPMTAG_REQUIREFLAGS, + _notpre(RPMSENSE_INTERP), 0 }, + { "Requires(rpmlib)", { NULL, "rpmlib", NULL, NULL }, + -1, -1, RPMTAG_REQUIREFLAGS, + _notpre(RPMSENSE_RPMLIB), 0 }, + { "Requires(verify)", { NULL, "verify", NULL, NULL }, + -1, -1, RPMTAG_REQUIREFLAGS, + RPMSENSE_SCRIPT_VERIFY, 0 }, + { "Requires(pre)", { NULL, "pre", NULL, NULL }, + -1, -1, RPMTAG_REQUIREFLAGS, + _notpre(RPMSENSE_SCRIPT_PRE), 0 }, + { "Requires(post)", { NULL, "post", NULL, NULL }, + -1, -1, RPMTAG_REQUIREFLAGS, + _notpre(RPMSENSE_SCRIPT_POST), 0 }, + { "Requires(preun)", { NULL, "preun", NULL, NULL }, + -1, -1, RPMTAG_REQUIREFLAGS, + _notpre(RPMSENSE_SCRIPT_PREUN), 0 }, + { "Requires(postun)", { NULL, "postun", NULL, NULL }, + -1, -1, RPMTAG_REQUIREFLAGS, + _notpre(RPMSENSE_SCRIPT_POSTUN), 0 }, { "Requires", { "%{__find_requires}", NULL, NULL, NULL }, -1, -1, RPMTAG_REQUIREFLAGS, /* XXX inherit name/version arrays */ RPMSENSE_PREREQ, RPMSENSE_PREREQ }, @@ -1794,20 +1815,23 @@ static int generateDepends(Spec spec, Package pkg, } for (dm = depMsgs; dm->msg != NULL; dm++) { - int i, tag; + int i, tag, tagflags; tag = (dm->ftag > 0) ? dm->ftag : dm->ntag; + tagflags = 0; switch(tag) { case RPMTAG_PROVIDEFLAGS: if (!pkg->autoProv) continue; failnonzero = 1; + tagflags = RPMSENSE_FIND_PROVIDES; break; case RPMTAG_REQUIREFLAGS: if (!pkg->autoReq) continue; failnonzero = 0; + tagflags = RPMSENSE_FIND_REQUIRES; break; default: continue; @@ -1815,7 +1839,7 @@ static int generateDepends(Spec spec, Package pkg, } /* Get the script name to run */ - myargv[0] = rpmExpand(dm->argv[0], NULL); + myargv[0] = (dm->argv[0] ? rpmExpand(dm->argv[0], NULL) : NULL); if (!(myargv[0] && *myargv[0] != '%')) { free(myargv[0]); @@ -1855,8 +1879,12 @@ static int generateDepends(Spec spec, Package pkg, } /* Parse dependencies into header */ - rc = parseRCPOT(spec, pkg, getStringBuf(readBuf), tag, 0, - multiLib > 1 ? RPMSENSE_MULTILIB : 0); + tagflags &= ~RPMSENSE_MULTILIB; + if (multiLib > 1) + tagflags |= RPMSENSE_MULTILIB; + else + tagflags &= ~RPMSENSE_MULTILIB; + rc = parseRCPOT(spec, pkg, getStringBuf(readBuf), tag, 0, tagflags); freeStringBuf(readBuf); if (rc) { @@ -1874,9 +1902,9 @@ static void printDepMsg(DepMsg_t *dm, int count, const char **names, { int hasVersions = (versions != NULL); int hasFlags = (flags != NULL); - int i, bingo; + int bingo = 0; + int i; - bingo = 0; for (i = 0; i < count; i++, names++, versions++, flags++) { if (hasFlags && !((*flags & dm->mask) ^ dm->xor)) continue; diff --git a/build/parsePreamble.c b/build/parsePreamble.c index c35b32c..7cd2e20 100644 --- a/build/parsePreamble.c +++ b/build/parsePreamble.c @@ -67,9 +67,8 @@ static int parseSimplePart(char *line, /*@out@*/char **name, /*@out@*/int *flag) } if (!strcmp(tok, "-n")) { - if (!(tok = strtok(NULL, " \t\n"))) { + if (!(tok = strtok(NULL, " \t\n"))) return 1; - } *flag = PART_NAME; } else { *flag = PART_SUBNAME; @@ -92,14 +91,69 @@ static int parseYesNo(char *s) return 1; } +struct tokenBits { + const char * name; + int bits; +}; + +static struct tokenBits installScriptBits[] = { + { "interp", RPMSENSE_INTERP }, + { "prereq", RPMSENSE_PREREQ }, + { "preun", RPMSENSE_SCRIPT_PREUN }, + { "pre", RPMSENSE_SCRIPT_PRE }, + { "postun", RPMSENSE_SCRIPT_POSTUN }, + { "post", RPMSENSE_SCRIPT_POST }, + { "rpmlib", RPMSENSE_RPMLIB }, + { "verify", RPMSENSE_SCRIPT_VERIFY }, + { NULL, 0 } +}; + +static struct tokenBits buildScriptBits[] = { + { "prep", RPMSENSE_SCRIPT_PREP }, + { "build", RPMSENSE_SCRIPT_BUILD }, + { "install", RPMSENSE_SCRIPT_INSTALL }, + { "clean", RPMSENSE_SCRIPT_CLEAN }, + { NULL, 0 } +}; + +static int parseBits(const char * s, struct tokenBits * tokbits, int * bp) +{ + struct tokenBits *tb; + const char *se; + int bits = 0; + int c = 0; + + if (s) { + while (*s) { + while ((c = *s) && isspace(c)) s++; + se = s; + while ((c = *se) && isalpha(c)) se++; + if (s == se) + break; + for (tb = tokbits; tb->name; tb++) { + if (strlen(tb->name) == (se-s) && !strncmp(tb->name, s, (se-s))) + break; + } + if (tb->name == NULL) + break; + bits |= tb->bits; + while ((c = *se) && isspace(c)) se++; + if (c != ',') + break; + s = ++se; + } + } + if (c == 0 && *bp) *bp = bits; + return (c ? RPMERR_BADSPEC : 0); +} + static inline char * findLastChar(char * s) { char *res = s; while (*s) { - if (! isspace(*s)) { + if (! isspace(*s)) res = s; - } s++; } @@ -336,7 +390,10 @@ static int handlePreambleTag(Spec spec, Package pkg, int tag, const char *macro, char *end; char **array; int multiToken = 0; - int num, rc, len; + int tagflags; + int len; + int num; + int rc; /* Find the start of the "field" and strip trailing space */ while ((*field) && (*field != ':')) @@ -509,15 +566,34 @@ static int handlePreambleTag(Spec spec, Package pkg, int tag, const char *macro, if ((rc = parseNoSource(spec, field, tag))) return rc; break; - case RPMTAG_OBSOLETEFLAGS: - case RPMTAG_PROVIDEFLAGS: - case RPMTAG_BUILDREQUIRES: - case RPMTAG_BUILDCONFLICTS: case RPMTAG_BUILDPREREQ: + case RPMTAG_BUILDREQUIRES: + if ((rc = parseBits(lang, buildScriptBits, &tagflags))) { + rpmError(RPMERR_BADSPEC, + _("line %d: Bad %s: qualifiers: %s"), + spec->lineNum, tagName(tag), spec->line); + return rc; + } + if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags))) + return rc; + break; case RPMTAG_REQUIREFLAGS: - case RPMTAG_CONFLICTFLAGS: case RPMTAG_PREREQ: - if ((rc = parseRCPOT(spec, pkg, field, tag, 0, 0))) + if ((rc = parseBits(lang, installScriptBits, &tagflags))) { + rpmError(RPMERR_BADSPEC, + _("line %d: Bad %s: qualifiers: %s"), + spec->lineNum, tagName(tag), spec->line); + return rc; + } + if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags))) + return rc; + break; + case RPMTAG_BUILDCONFLICTS: + case RPMTAG_CONFLICTFLAGS: + case RPMTAG_OBSOLETEFLAGS: + case RPMTAG_PROVIDEFLAGS: + tagflags = 0; + if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags))) return rc; break; case RPMTAG_EXCLUDEARCH: @@ -583,8 +659,8 @@ static struct PreambleRec { {RPMTAG_EXCLUSIVEOS, 0, 0, "exclusiveos"}, {RPMTAG_ICON, 0, 0, "icon"}, {RPMTAG_PROVIDEFLAGS, 0, 0, "provides"}, - {RPMTAG_REQUIREFLAGS, 0, 0, "requires"}, - {RPMTAG_PREREQ, 0, 0, "prereq"}, + {RPMTAG_REQUIREFLAGS, 0, 1, "requires"}, + {RPMTAG_PREREQ, 0, 1, "prereq"}, {RPMTAG_CONFLICTFLAGS, 0, 0, "conflicts"}, {RPMTAG_OBSOLETEFLAGS, 0, 0, "obsoletes"}, {RPMTAG_PREFIXES, 0, 0, "prefixes"}, @@ -593,8 +669,8 @@ static struct PreambleRec { {RPMTAG_BUILDARCHS, 0, 0, "buildarchitectures"}, {RPMTAG_BUILDARCHS, 0, 0, "buildarch"}, {RPMTAG_BUILDCONFLICTS, 0, 0, "buildconflicts"}, - {RPMTAG_BUILDPREREQ, 0, 0, "buildprereq"}, - {RPMTAG_BUILDREQUIRES, 0, 0, "buildrequires"}, + {RPMTAG_BUILDPREREQ, 0, 1, "buildprereq"}, + {RPMTAG_BUILDREQUIRES, 0, 1, "buildrequires"}, {RPMTAG_AUTOREQPROV, 0, 0, "autoreqprov"}, {RPMTAG_AUTOREQ, 0, 0, "autoreq"}, {RPMTAG_AUTOPROV, 0, 0, "autoprov"}, @@ -621,38 +697,38 @@ static int findPreambleTag(Spec spec, /*@out@*/int *tag, /*@out@*/char **macro, if (!strncasecmp(spec->line, p->token, p->len)) break; } - if (p->token == NULL) return 1; s = spec->line + p->len; SKIPSPACE(s); - if (! p->multiLang) { + switch (p->multiLang) { + default: + case 0: /* Unless this is a source or a patch, a ':' better be next */ if (p->tag != RPMTAG_SOURCE && p->tag != RPMTAG_PATCH) { - if (*s != ':') { - return 1; - } + if (*s != ':') return 1; } *lang = '\0'; - } else { - if (*s != ':') { - if (*s != '(') return 1; - s++; - SKIPSPACE(s); - while (! isspace(*s) && *s != ')') { - *lang++ = *s++; - } - *lang = '\0'; - SKIPSPACE(s); - if (*s != ')') return 1; - s++; - SKIPSPACE(s); - if (*s != ':') return 1; - } else { + break; + case 1: /* Parse optional ( ). */ + if (*s == ':') { strcpy(lang, RPMBUILD_DEFAULT_LANG); + break; } + if (*s != '(') return 1; + s++; + SKIPSPACE(s); + while (!isspace(*s) && *s != ')') + *lang++ = *s++; + *lang = '\0'; + SKIPSPACE(s); + if (*s != ')') return 1; + s++; + SKIPSPACE(s); + if (*s != ':') return 1; + break; } *tag = p->tag; @@ -693,18 +769,16 @@ int parsePreamble(Spec spec, int initialPackage) const char * mainName; headerNVR(spec->packages->header, &mainName, NULL, NULL); sprintf(fullName, "%s-%s", mainName, name); - } else { + } else strcpy(fullName, name); - } headerAddEntry(pkg->header, RPMTAG_NAME, RPM_STRING_TYPE, fullName, 1); } if ((rc = readLine(spec, STRIP_TRAILINGSPACE | STRIP_COMMENTS)) > 0) { nextPart = PART_NONE; } else { - if (rc) { + if (rc) return rc; - } while (! (nextPart = isPart(spec->line))) { /* Skip blank lines */ linep = spec->line; @@ -715,21 +789,18 @@ int parsePreamble(Spec spec, int initialPackage) spec->lineNum, spec->line); return RPMERR_BADSPEC; } - if (handlePreambleTag(spec, pkg, tag, macro, lang)) { + if (handlePreambleTag(spec, pkg, tag, macro, lang)) return RPMERR_BADSPEC; - } - if (spec->buildArchitectures && !spec->inBuildArchitectures) { + if (spec->buildArchitectures && !spec->inBuildArchitectures) return PART_BUILDARCHITECTURES; - } } if ((rc = readLine(spec, STRIP_TRAILINGSPACE | STRIP_COMMENTS)) > 0) { nextPart = PART_NONE; break; } - if (rc) { + if (rc) return rc; - } } } @@ -741,25 +812,20 @@ int parsePreamble(Spec spec, int initialPackage) } /* XXX Skip valid arch check if not building binary package */ - if (!spec->anyarch && checkForValidArchitectures(spec)) { - return RPMERR_BADSPEC; - } + if (!spec->anyarch && checkForValidArchitectures(spec)) + return RPMERR_BADSPEC; - if (pkg == spec->packages) { + if (pkg == spec->packages) fillOutMainPackage(pkg->header); - } - if (checkForDuplicates(pkg->header, fullName)) { + if (checkForDuplicates(pkg->header, fullName)) return RPMERR_BADSPEC; - } - if (pkg != spec->packages) { + if (pkg != spec->packages) headerCopyTags(spec->packages->header, pkg->header, copyTagsDuringParse); - } - if (checkForRequired(pkg->header, fullName)) { + if (checkForRequired(pkg->header, fullName)) return RPMERR_BADSPEC; - } return nextPart; } diff --git a/build/parseReqs.c b/build/parseReqs.c index 3f5c5df..4c27df5 100644 --- a/build/parseReqs.c +++ b/build/parseReqs.c @@ -90,7 +90,7 @@ int parseRCPOT(Spec spec, Package pkg, const char *field, int tag, if (*r == '\0') break; - flags = tagflags; + flags = (tagflags & ~RPMSENSE_SENSEMASK); /* Tokens must begin with alphanumeric, _, or / */ if (!(isalnum(r[0]) || r[0] == '_' || r[0] == '/')) { diff --git a/build/parseScript.c b/build/parseScript.c index aede861..b0c9bed 100644 --- a/build/parseScript.c +++ b/build/parseScript.c @@ -71,10 +71,11 @@ int parseScript(Spec spec, int parsePart) char *partname = NULL; int reqtag = 0; int tag = 0; + int tagflags = 0; int progtag = 0; int flag = PART_SUBNAME; Package pkg; - StringBuf sb; + StringBuf sb = NULL; int nextPart; int index; char reqargs[BUFSIZ]; @@ -91,43 +92,51 @@ int parseScript(Spec spec, int parsePart) switch (parsePart) { case PART_PRE: tag = RPMTAG_PREIN; + tagflags = RPMSENSE_SCRIPT_PRE; progtag = RPMTAG_PREINPROG; partname = "%pre"; break; case PART_POST: tag = RPMTAG_POSTIN; + tagflags = RPMSENSE_SCRIPT_POST; progtag = RPMTAG_POSTINPROG; partname = "%post"; break; case PART_PREUN: tag = RPMTAG_PREUN; + tagflags = RPMSENSE_SCRIPT_PREUN; progtag = RPMTAG_PREUNPROG; partname = "%preun"; break; case PART_POSTUN: tag = RPMTAG_POSTUN; + tagflags = RPMSENSE_SCRIPT_POSTUN; progtag = RPMTAG_POSTUNPROG; partname = "%postun"; break; case PART_VERIFYSCRIPT: tag = RPMTAG_VERIFYSCRIPT; + tagflags = RPMSENSE_SCRIPT_VERIFY; progtag = RPMTAG_VERIFYSCRIPTPROG; partname = "%verifyscript"; break; case PART_TRIGGERIN: tag = RPMTAG_TRIGGERSCRIPTS; + tagflags = 0; reqtag = RPMTAG_TRIGGERIN; progtag = RPMTAG_TRIGGERSCRIPTPROG; partname = "%triggerin"; break; case PART_TRIGGERUN: tag = RPMTAG_TRIGGERSCRIPTS; + tagflags = 0; reqtag = RPMTAG_TRIGGERUN; progtag = RPMTAG_TRIGGERSCRIPTPROG; partname = "%triggerun"; break; case PART_TRIGGERPOSTUN: tag = RPMTAG_TRIGGERSCRIPTS; + tagflags = 0; reqtag = RPMTAG_TRIGGERPOSTUN; progtag = RPMTAG_TRIGGERSCRIPTPROG; partname = "%triggerpostun"; @@ -160,9 +169,8 @@ int parseScript(Spec spec, int parsePart) rpmError(RPMERR_BADSPEC, _("line %d: script program must begin " "with \'/\': %s"), spec->lineNum, prog); - FREE(argv); - poptFreeContext(optCon); - return RPMERR_BADSPEC; + rc = RPMERR_BADSPEC; + goto exit; } } else if (arg == 'n') { flag = PART_NAME; @@ -174,9 +182,8 @@ int parseScript(Spec spec, int parsePart) spec->lineNum, poptBadOption(optCon, POPT_BADOPTION_NOALIAS), spec->line); - FREE(argv); - poptFreeContext(optCon); - return RPMERR_BADSPEC; + rc = RPMERR_BADSPEC; + goto exit; } if (poptPeekArg(optCon)) { @@ -186,60 +193,54 @@ int parseScript(Spec spec, int parsePart) rpmError(RPMERR_BADSPEC, _("line %d: Too many names: %s"), spec->lineNum, spec->line); - FREE(argv); - poptFreeContext(optCon); - return RPMERR_BADSPEC; + rc = RPMERR_BADSPEC; + goto exit; } } if (lookupPackage(spec, name, flag, &pkg)) { rpmError(RPMERR_BADSPEC, _("line %d: Package does not exist: %s"), spec->lineNum, spec->line); - FREE(argv); - poptFreeContext(optCon); - return RPMERR_BADSPEC; + rc = RPMERR_BADSPEC; + goto exit; } if (tag != RPMTAG_TRIGGERSCRIPTS) { if (headerIsEntry(pkg->header, progtag)) { rpmError(RPMERR_BADSPEC, _("line %d: Second %s"), spec->lineNum, partname); - FREE(argv); - poptFreeContext(optCon); - return RPMERR_BADSPEC; + rc = RPMERR_BADSPEC; + goto exit; } } if ((rc = poptParseArgvString(prog, &progArgc, &progArgv))) { rpmError(RPMERR_BADSPEC, _("line %d: Error parsing %s: %s"), spec->lineNum, partname, poptStrerror(rc)); - FREE(argv); - poptFreeContext(optCon); - return RPMERR_BADSPEC; + rc = RPMERR_BADSPEC; + goto exit; } sb = newStringBuf(); if ((rc = readLine(spec, STRIP_NOTHING)) > 0) { nextPart = PART_NONE; } else { - if (rc) { - return rc; - } + if (rc) + goto exit; while (! (nextPart = isPart(spec->line))) { appendStringBuf(sb, spec->line); if ((rc = readLine(spec, STRIP_NOTHING)) > 0) { nextPart = PART_NONE; break; } - if (rc) { - return rc; - } + if (rc) + goto exit; } } stripTrailingBlanksStringBuf(sb); p = getStringBuf(sb); - addReqProv(spec, pkg->header, RPMSENSE_PREREQ, prog, NULL, 0); + addReqProv(spec, pkg->header, (tagflags | RPMSENSE_INTERP), prog, NULL, 0); /* Trigger script insertion is always delayed in order to */ /* get the index right. */ @@ -248,18 +249,13 @@ int parseScript(Spec spec, int parsePart) index = addTriggerIndex(pkg, file, p, prog); /* Generate the trigger tags */ - if ((rc = parseRCPOT(spec, pkg, reqargs, reqtag, index, 0))) { - freeStringBuf(sb); - FREE(progArgv); - FREE(argv); - poptFreeContext(optCon); - return rc; - } + if ((rc = parseRCPOT(spec, pkg, reqargs, reqtag, index, tagflags))) + goto exit; } else { headerAddEntry(pkg->header, progtag, RPM_STRING_TYPE, prog, 1); - if (*p) { + if (*p) headerAddEntry(pkg->header, tag, RPM_STRING_TYPE, p, 1); - } + if (file) { switch (parsePart) { case PART_PRE: @@ -280,11 +276,19 @@ int parseScript(Spec spec, int parsePart) } } } + rc = nextPart; - freeStringBuf(sb); - FREE(progArgv); - FREE(argv); - poptFreeContext(optCon); +exit: + if (sb) + freeStringBuf(sb); + if (progArgv) { + FREE(progArgv); + } + if (argv) { + FREE(argv); + } + if (optCon) + poptFreeContext(optCon); - return nextPart; + return rc; } diff --git a/build/parseSpec.c b/build/parseSpec.c index d0a1da4..292c2c6 100644 --- a/build/parseSpec.c +++ b/build/parseSpec.c @@ -45,26 +45,21 @@ static inline void initParts(struct PartRec *p) rpmParseState isPart(const char *line) { - char c; struct PartRec *p; if (partList[0].len == 0) initParts(partList); for (p = partList; p->token != NULL; p++) { - if (! strncasecmp(line, p->token, p->len)) { - c = *(line + p->len); - if (c == '\0' || isspace(c)) { - break; - } - } + char c; + if (strncasecmp(line, p->token, p->len)) + continue; + c = *(line + p->len); + if (c == '\0' || isspace(c)) + break; } - if (p->token) { - return p->part; - } else { - return PART_NONE; - } + return (p->token ? p->part : PART_NONE); } static int matchTok(const char *token, const char *line) @@ -96,9 +91,8 @@ static int matchTok(const char *token, const char *line) void handleComments(char *s) { SKIPSPACE(s); - if (*s == '#') { + if (*s == '#') *s = '\0'; - } } static void forceIncludeFile(Spec spec, const char * fileName) diff --git a/build/reqprov.c b/build/reqprov.c index 7a4ec38..f96158e 100644 --- a/build/reqprov.c +++ b/build/reqprov.c @@ -23,6 +23,7 @@ int addReqProv(/*@unused@*/ Spec spec, Header h, nametag = RPMTAG_PROVIDENAME; versiontag = RPMTAG_PROVIDEVERSION; flagtag = RPMTAG_PROVIDEFLAGS; + extra = flag & RPMSENSE_FIND_PROVIDES; } else if (flag & RPMSENSE_OBSOLETES) { nametag = RPMTAG_OBSOLETENAME; versiontag = RPMTAG_OBSOLETEVERSION; @@ -35,7 +36,7 @@ int addReqProv(/*@unused@*/ Spec spec, Header h, nametag = RPMTAG_REQUIRENAME; versiontag = RPMTAG_REQUIREVERSION; flagtag = RPMTAG_REQUIREFLAGS; - extra = RPMSENSE_PREREQ; + extra = flag & _ALL_REQUIRES_MASK; } else if (flag & RPMSENSE_TRIGGER) { nametag = RPMTAG_TRIGGERNAME; versiontag = RPMTAG_TRIGGERVERSION; @@ -46,6 +47,7 @@ int addReqProv(/*@unused@*/ Spec spec, Header h, nametag = RPMTAG_REQUIRENAME; versiontag = RPMTAG_REQUIREVERSION; flagtag = RPMTAG_REQUIREFLAGS; + extra = flag & _ALL_REQUIRES_MASK; } flag = (flag & (RPMSENSE_SENSEMASK | RPMSENSE_MULTILIB)) | extra; @@ -114,6 +116,6 @@ int rpmlibNeedsFeature(Header h, const char * feature, const char * featureEVR) (void) stpcpy( stpcpy( stpcpy(reqname, "rpmlib("), feature), ")"); /* XXX 1st arg is unused */ - return addReqProv(NULL, h, RPMSENSE_PREREQ|(RPMSENSE_LESS|RPMSENSE_EQUAL), + return addReqProv(NULL, h, RPMSENSE_RPMLIB|(RPMSENSE_LESS|RPMSENSE_EQUAL), reqname, featureEVR, 0); } diff --git a/lib/depends.c b/lib/depends.c index 62f8b86..78f39f6 100644 --- a/lib/depends.c +++ b/lib/depends.c @@ -1364,18 +1364,36 @@ static int checkDependentConflicts(rpmTransactionSet rpmdep, return rc; } -#if 0 +/* + * XXX Hack to remove known Red Hat dependency loops, will be removed + * Real Soon Now. + */ +#define DEPENDENCY_WHITEOUT + +#if defined(DEPENDENCY_WHITEOUT) static struct badDeps_s { const char * pname; const char * qname; } badDeps[] = { -#if 0 { "libtermcap", "bash" }, { "modutils", "vixie-cron" }, - { "XFree86", "Mesa" }, { "ypbind", "yp-tools" }, - { "pango-gtkbeta", "pango-gtkbeta-devel" }, { "ghostscript-fonts", "ghostscript" }, + /* 7.0 only */ + { "pango-gtkbeta-devel", "pango-gtkbeta" }, + { "XFree86", "Mesa" }, + { "compat-glibc", "db2" }, + { "compat-glibc", "db1" }, + { "pam", "initscripts" }, + { "kernel", "initscripts" }, + { "initscripts", "sysklogd" }, + /* 6.2 */ + { "egcs-c++", "libstdc++" }, + /* 6.1 */ + { "pilot-link-devel", "pilot-link" }, + /* 5.2 */ + { "pam", "pamconfig" }, +#if 0 /* ================= */ { "usermode", "util-linux" }, { "chkfontpath", "SysVinit" }, @@ -1392,7 +1410,9 @@ static int ignoreDep(struct availablePackage * p, struct availablePackage * q) for (bdp = badDeps; bdp->pname != NULL; bdp++) { if (!strcmp(p->name, bdp->pname) && !strcmp(q->name, bdp->qname)) { +#if 0 fprintf(stderr, "*** avoiding %s Requires: %s\n", p->name, q->name); +#endif return 1; } } @@ -1419,13 +1439,34 @@ static void markLoop(struct tsortInfo * tsi, struct availablePackage * q) } } +static inline const char * identifyDepend(int_32 f) { + if (isLegacyPreReq(f)) + return "PreReq:"; + f = _notpre(f); + if (f & RPMSENSE_SCRIPT_PRE) + return "Requires(pre):"; + if (f & RPMSENSE_SCRIPT_POST) + return "Requires(post):"; + if (f & RPMSENSE_SCRIPT_PREUN) + return "Requires(preun):"; + if (f & RPMSENSE_SCRIPT_POSTUN) + return "Requires(postun):"; + if (f & RPMSENSE_SCRIPT_VERIFY) + return "Requires(verify):"; + if (f & RPMSENSE_FIND_REQUIRES) + return "Requires(auto):"; + return "Requires:"; +} + /** - * Find (and eliminate PreReq's) "q <- p" relation in dependency loop. + * Find (and eliminate co-requisites) "q <- p" relation in dependency loop. * Search all successors of q for instance of p. Format the specific relation, - * (e.g. p contains "Requires: q"). Unlink and free PreReq: successor node(s). + * (e.g. p contains "Requires: q"). Unlink and free co-requisite (i.e. + * pure Requires: dependencies) successor node(s). * @param q sucessor (i.e. package required by p) * @param p predecessor (i.e. package that "Requires: q") - * @param zap eliminate PreReq's ? + * @param zap max. no. of co-requisites to remove (-1 is all)? + * @retval nzaps address of no. of relations removed * @return (possibly NULL) formatted "q <- p" releation (malloc'ed) */ static /*@owned@*/ /*@null@*/ const char * @@ -1447,8 +1488,7 @@ zapRelation(struct availablePackage * q, struct availablePackage * p, if (tsi->tsi_suc != p) continue; j = tsi->tsi_reqx; - dp = printDepend( ((p->requireFlags[j] & RPMSENSE_PREREQ) - ? "PreReq:" : "Requires:"), + dp = printDepend( identifyDepend(p->requireFlags[j]), p->requires[j], p->requiresEVR[j], p->requireFlags[j]); /* @@ -1459,7 +1499,7 @@ zapRelation(struct availablePackage * q, struct availablePackage * p, * PreReq: /bin/sh * to fail. */ - if (zap && (p->requireFlags[j] & RPMSENSE_PREREQ)) { + if (zap && !(p->requireFlags[j] & RPMSENSE_PREREQ)) { rpmMessage(RPMMESS_WARNING, _("removing %s-%s-%s \"%s\" from tsort relations.\n"), p->name, p->version, p->release, dp); @@ -1470,6 +1510,8 @@ zapRelation(struct availablePackage * q, struct availablePackage * p, free(tsi); if (nzaps) (*nzaps)++; + if (zap) + zap--; } break; } @@ -1477,6 +1519,55 @@ zapRelation(struct availablePackage * q, struct availablePackage * p, } /** + * Record next "q <- p" relation (i.e. "p" requires "q"). + * @param rpmdep rpm transaction set + * @param p predecessor (i.e. package that "Requires: q") + * @param selected boolean package selected array + * @param j relation index + * @return 0 always + */ +static inline int addRelation( const rpmTransactionSet rpmdep, + struct availablePackage * p, unsigned char * selected, int j) +{ + struct availablePackage * q; + struct tsortInfo * tsi; + int matchNum; + + q = alSatisfiesDepend(&rpmdep->addedPackages, NULL, NULL, + p->requires[j], p->requiresEVR[j], p->requireFlags[j]); + + /* Ordering depends only on added package relations. */ + if (q == NULL) + return 0; + + /* Avoid rpmlib feature dependencies. */ + if (!strncmp(p->requires[j], "rpmlib(", sizeof("rpmlib(")-1)) + return 0; + +#if defined(DEPENDENCY_WHITEOUT) + /* Avoid certain dependency relations. */ + if (ignoreDep(p, q)) + return 0; +#endif + + /* Avoid redundant relations. */ + /* XXX FIXME: add control bit. */ + matchNum = q - rpmdep->addedPackages.list; + if (selected[matchNum]) + return 0; + selected[matchNum] = 1; + + /* T3. Record next "q <- p" relation (i.e. "p" requires "q"). */ + p->tsi.tsi_count++; + tsi = xmalloc(sizeof(*tsi)); + tsi->tsi_suc = p; + tsi->tsi_reqx = j; + tsi->tsi_next = q->tsi.tsi_next; + q->tsi.tsi_next = tsi; + return 0; +} + +/** * Compare ordered list entries by index (qsort/bsearch). * @param a 1st ordered list entry * @param b 2nd ordered list entry @@ -1531,42 +1622,35 @@ int rpmdepOrder(rpmTransactionSet rpmdep) selected[matchNum] = 1; /* T2. Next "q <- p" relation. */ + + /* First, do pre-requisites. */ for (j = 0; j < p->requiresCount; j++) { - /* Avoid rpmlib feature dependencies. */ - if (!strncmp(p->requires[j], "rpmlib(", sizeof("rpmlib(")-1)) - continue; + /* Skip if not %pre/%post requires or legacy prereq. */ -#if 0 - /* XXX FIXME: add control bit. */ - /* Only PreReq:'s determine order (for now). */ - if (!_depends_debug && !(p->requireFlags[j] & RPMSENSE_PREREQ)) + if (isErasePreReq(p->requireFlags[j]) || + !( isInstallPreReq(p->requireFlags[j]) || + isLegacyPreReq(p->requireFlags[j]) )) continue; -#endif - /* Ordering depends only on added package relations. */ - q = alSatisfiesDepend(&rpmdep->addedPackages, NULL, NULL, - p->requires[j], p->requiresEVR[j], p->requireFlags[j]); - if (q == NULL) continue; + /* T3. Record next "q <- p" relation (i.e. "p" requires "q"). */ + (void) addRelation(rpmdep, p, selected, j); -#if 0 - /* Avoid certain dependency relations. */ - if (ignoreDep(p, q)) continue; -#endif + } + + /* Then do co-requisites. */ + for (j = 0; j < p->requiresCount; j++) { + + /* Skip if %pre/%post requires or legacy prereq. */ - /* Avoid redundant relations. */ - /* XXX FIXME: add control bit. */ - matchNum = q - rpmdep->addedPackages.list; - if (selected[matchNum]) continue; - selected[matchNum] = 1; + if (isErasePreReq(p->requireFlags[j]) || + ( isInstallPreReq(p->requireFlags[j]) || + isLegacyPreReq(p->requireFlags[j]) )) + continue; /* T3. Record next "q <- p" relation (i.e. "p" requires "q"). */ - p->tsi.tsi_count++; - tsi = xmalloc(sizeof(*tsi)); - tsi->tsi_suc = p; - tsi->tsi_reqx = j; - tsi->tsi_next = q->tsi.tsi_next; - q->tsi.tsi_next = tsi; + (void) addRelation(rpmdep, p, selected, j); + } } @@ -1678,7 +1762,7 @@ rescan: printed = 1; } - /* Find (and destroy if PreReq:) "q <- p" relation. */ + /* Find (and destroy if co-requisite) "q <- p" relation. */ dp = zapRelation(q, p, 1, &nzaps); /* Print next member of loop. */ diff --git a/lib/rpmdb.c b/lib/rpmdb.c index 2971172..ef0e897 100644 --- a/lib/rpmdb.c +++ b/lib/rpmdb.c @@ -1902,9 +1902,11 @@ int rpmdbAdd(rpmdb rpmdb, Header h) int rpmtype = 0; int rpmcnt = 0; int rpmtag; + int_32 * requireFlags; int i, j; dbi = NULL; + requireFlags = NULL; rpmtag = dbiTags[dbix]; switch (rpmtag) { @@ -1935,9 +1937,13 @@ int rpmdbAdd(rpmdb rpmdb, Header h) rpmvals = baseNames; rpmcnt = count; break; + case RPMTAG_REQUIRENAME: + headerGetEntry(h, rpmtag, &rpmtype, (void **)&rpmvals, &rpmcnt); + headerGetEntry(h, RPMTAG_REQUIREFLAGS, NULL, + (void **)&requireFlags, NULL); + break; default: - headerGetEntry(h, rpmtag, &rpmtype, - (void **) &rpmvals, &rpmcnt); + headerGetEntry(h, rpmtag, &rpmtype, (void **)&rpmvals, &rpmcnt); break; } @@ -1984,6 +1990,14 @@ int rpmdbAdd(rpmdb rpmdb, Header h) * included the tagNum only for files. */ switch (dbi->dbi_rpmtag) { + case RPMTAG_REQUIRENAME: + /* Filter out install prerequisites. */ + if (requireFlags && isInstallPreReq(requireFlags[i])) { + rpmMessage(RPMMESS_DEBUG, ("%6d %s\n"), i, rpmvals[i]); + continue; + } + rec->tagNum = i; + break; case RPMTAG_TRIGGERNAME: if (i) { /* don't add duplicates */ for (j = 0; j < i; j++) { @@ -1993,7 +2007,8 @@ int rpmdbAdd(rpmdb rpmdb, Header h) if (j < i) continue; } - /*@fallthrough@*/ + rec->tagNum = i; + break; default: rec->tagNum = i; break; diff --git a/lib/rpmlib.h b/lib/rpmlib.h index 29b06c2..e416aba 100644 --- a/lib/rpmlib.h +++ b/lib/rpmlib.h @@ -320,18 +320,34 @@ typedef enum rpmfileAttrs_e { */ typedef enum rpmsenseFlags_e { RPMSENSE_ANY = 0, - RPMSENSE_SERIAL = (1 << 0), /*!< @todo Legacy. */ + RPMSENSE_SERIAL = (1 << 0), /*!< @todo Legacy. */ RPMSENSE_LESS = (1 << 1), RPMSENSE_GREATER = (1 << 2), RPMSENSE_EQUAL = (1 << 3), RPMSENSE_PROVIDES = (1 << 4), /* only used internally by builds */ RPMSENSE_CONFLICTS = (1 << 5), /* only used internally by builds */ - RPMSENSE_PREREQ = (1 << 6), + RPMSENSE_PREREQ = (1 << 6), /*!< @todo Legacy. */ RPMSENSE_OBSOLETES = (1 << 7), /* only used internally by builds */ - RPMSENSE_TRIGGERIN = (1 << 16), - RPMSENSE_TRIGGERUN = (1 << 17), - RPMSENSE_TRIGGERPOSTUN= (1 << 18), + RPMSENSE_INTERP = (1 << 8), /*!< Interpreter used by scriptlet. */ + RPMSENSE_SCRIPT_PRE = ((1 << 9)|RPMSENSE_PREREQ), /*!< %pre dependency. */ + RPMSENSE_SCRIPT_POST = ((1 << 10)|RPMSENSE_PREREQ), /*!< %post dependency. */ + RPMSENSE_SCRIPT_PREUN = ((1 << 11)|RPMSENSE_PREREQ), /*!< %preun dependency. */ + RPMSENSE_SCRIPT_POSTUN = ((1 << 12)|RPMSENSE_PREREQ), /*!< %postun dependency. */ + RPMSENSE_SCRIPT_VERIFY = (1 << 13), /*!< %verify dependency. */ + RPMSENSE_FIND_REQUIRES = (1 << 14), /*!< find-requires generated dependency. */ + RPMSENSE_FIND_PROVIDES = (1 << 15), /*!< find-provides generated dependency. */ + + RPMSENSE_TRIGGERIN = (1 << 16), /*!< %triggerin dependency. */ + RPMSENSE_TRIGGERUN = (1 << 17), /*!< %triggerun dependency. */ + RPMSENSE_TRIGGERPOSTUN = (1 << 18), /*!< %triggerpostun dependency. */ RPMSENSE_MULTILIB = (1 << 19), + RPMSENSE_SCRIPT_PREP = (1 << 20), /*!< %prep build dependency. */ + RPMSENSE_SCRIPT_BUILD = (1 << 21), /*!< %build build dependency. */ + RPMSENSE_SCRIPT_INSTALL = (1 << 22),/*!< %install build dependency. */ + RPMSENSE_SCRIPT_CLEAN = (1 << 23), /*!< %clean build dependency. */ + RPMSENSE_RPMLIB = ((1 << 24) | RPMSENSE_PREREQ), /*!< rpmlib(feature) dependency. */ + RPMSENSE_TRIGGERPREIN = (1 << 25) /*!< @todo Implement %triggerprein. */ + } rpmsenseFlags; #define RPMSENSE_SENSEMASK 15 /* Mask to get senses, ie serial, */ @@ -342,6 +358,30 @@ typedef enum rpmsenseFlags_e { #define isDependsMULTILIB(_dflags) ((_dflags) & RPMSENSE_MULTILIB) +#define _ALL_REQUIRES_MASK (\ + RPMSENSE_INTERP | \ + RPMSENSE_SCRIPT_PRE | \ + RPMSENSE_SCRIPT_POST | \ + RPMSENSE_SCRIPT_PREUN | \ + RPMSENSE_SCRIPT_POSTUN | \ + RPMSENSE_SCRIPT_VERIFY | \ + RPMSENSE_FIND_REQUIRES | \ + RPMSENSE_SCRIPT_PREP | \ + RPMSENSE_SCRIPT_BUILD | \ + RPMSENSE_SCRIPT_INSTALL | \ + RPMSENSE_SCRIPT_CLEAN | \ + RPMSENSE_RPMLIB ) + +#define _notpre(_x) ((_x) & ~RPMSENSE_PREREQ) +#define _INSTALL_ONLY_MASK \ + _notpre(RPMSENSE_SCRIPT_PRE|RPMSENSE_SCRIPT_POST|RPMSENSE_RPMLIB) +#define _ERASE_ONLY_MASK \ + _notpre(RPMSENSE_SCRIPT_PREUN|RPMSENSE_SCRIPT_POSTUN) + +#define isLegacyPreReq(_x) (((_x) & _ALL_REQUIRES_MASK) == RPMSENSE_PREREQ) +#define isInstallPreReq(_x) ((_x) & _INSTALL_ONLY_MASK) +#define isErasePreReq(_x) ((_x) & _ERASE_ONLY_MASK) + #define xfree(_p) free((void *)_p) /* ==================================================================== */ diff --git a/lib/rpmlibprov.c b/lib/rpmlibprov.c index ca5a718..e115098 100644 --- a/lib/rpmlibprov.c +++ b/lib/rpmlibprov.c @@ -12,15 +12,20 @@ static struct rpmlibProvides { int featureFlags; const char * featureDescription; } rpmlibProvides[] = { - { "rpmlib(VersionedDependencies)", "3.0.3-1", RPMSENSE_EQUAL, + { "rpmlib(VersionedDependencies)", "3.0.3-1", + (RPMSENSE_RPMLIB|RPMSENSE_EQUAL), "PreReq:, Provides:, and Obsoletes: dependencies support versions." }, - { "rpmlib(CompressedFileNames)", "3.0.4-1", RPMSENSE_EQUAL, + { "rpmlib(CompressedFileNames)", "3.0.4-1", + (RPMSENSE_RPMLIB|RPMSENSE_EQUAL), "file names stored as (dirName,BaseName,dirIndex) tuple, not as path."}, - { "rpmlib(PayloadIsBzip2)", "3.0.5-1", RPMSENSE_EQUAL, + { "rpmlib(PayloadIsBzip2)", "3.0.5-1", + (RPMSENSE_RPMLIB|RPMSENSE_EQUAL), "package payload compressed using bzip2." }, - { "rpmlib(PayloadFilesHavePrefix)", "4.0-1", RPMSENSE_EQUAL, + { "rpmlib(PayloadFilesHavePrefix)", "4.0-1", + (RPMSENSE_RPMLIB|RPMSENSE_EQUAL), "package payload files have \"./\" prefix." }, - { "rpmlib(ExplicitPackageProvide)", "4.0-1", RPMSENSE_EQUAL, + { "rpmlib(ExplicitPackageProvide)", "4.0-1", + (RPMSENSE_RPMLIB|RPMSENSE_EQUAL), "package name-version-release not implicitly provided." }, { NULL, NULL, 0 } }; diff --git a/tools/rpmsort.c b/tools/rpmsort.c index 3b2bdcb..f45c25c 100644 --- a/tools/rpmsort.c +++ b/tools/rpmsort.c @@ -8,6 +8,8 @@ extern int _depends_debug; +static int noDeps = 0; + static int do_tsort(const char *fileArgv[]) { @@ -57,7 +59,8 @@ do_tsort(const char *fileArgv[]) } - { struct rpmDependencyConflict * conflicts = NULL; + if (!noDeps) { + struct rpmDependencyConflict * conflicts = NULL; int numConflicts = 0; rc = rpmdepCheck(ts, &conflicts, &numConflicts); @@ -126,6 +129,7 @@ exit: } static struct poptOption optionsTable[] = { + { "nodeps", '\0', 0, &noDeps, 0, NULL, NULL}, { "verbose", 'v', 0, 0, 'v', NULL, NULL}, { NULL, 0, 0, 0, 0, NULL, NULL} }; -- 2.7.4