diff options
Diffstat (limited to 'build/rpmfc.c')
-rw-r--r-- | build/rpmfc.c | 359 |
1 files changed, 356 insertions, 3 deletions
diff --git a/build/rpmfc.c b/build/rpmfc.c index b347c2ee5..0747e9f87 100644 --- a/build/rpmfc.c +++ b/build/rpmfc.c @@ -1,4 +1,3 @@ -/*@-bounds@*/ #include "system.h" #include <signal.h> /* getOutputFrom() */ @@ -7,6 +6,9 @@ #include <argv.h> #include <rpmfc.h> +#include <rpmds.h> +#include <rpmfi.h> + #if HAVE_GELF_H #include <gelf.h> #endif @@ -18,6 +20,9 @@ /*@unchecked@*/ int _rpmfc_debug; +/** + */ +/*@-bounds@*/ /* LCL: internal error */ static int rpmfcExpandAppend(/*@out@*/ ARGV_t * argvp, const ARGV_t av) /*@globals rpmGlobalMacroContext @*/ /*@modifies *argvp, rpmGlobalMacroContext @*/ @@ -34,7 +39,7 @@ static int rpmfcExpandAppend(/*@out@*/ ARGV_t * argvp, const ARGV_t av) *argvp = argv; return 0; } - +/*@=bounds@*/ /*@-boundswrite@*/ /** \ingroup rpmbuild @@ -268,6 +273,11 @@ static int rpmfcSaveArg(/*@out@*/ ARGV_t * argvp, const char * key) } /** + * Run per-interpreter dependency helper. + * @param fc file classifier + * @param deptype 'P' == Provides:, 'R' == Requires:, helper + * @param nsdep class name for interpreter (e.g. "perl") + * @return 0 on success */ /*@-bounds@*/ static int rpmfcHelper(rpmfc fc, unsigned char deptype, const char * nsdep) @@ -447,6 +457,7 @@ int rpmfcColoring(const char * fmstr) return fcolor; } +/*@-bounds@*/ void rpmfcPrint(const char * msg, rpmfc fc, FILE * fp) { int fcolor; @@ -533,6 +544,7 @@ rpmfc rpmfcFree(rpmfc fc) fc = _free(fc); return NULL; } +/*@=bounds@*/ rpmfc rpmfcNew(void) { @@ -540,6 +552,11 @@ rpmfc rpmfcNew(void) return fc; } +/** + * Extract script dependencies. + * @param fc file classifier + * @return 0 on success + */ static int rpmfcSCRIPT(rpmfc fc) /*@globals rpmGlobalMacroContext, fileSystem, internalState @*/ /*@modifies fc, rpmGlobalMacroContext, fileSystem, internalState @*/ @@ -626,6 +643,11 @@ static int rpmfcSCRIPT(rpmfc fc) return 0; } +/** + * Extract Elf dependencies. + * @param fc file classifier + * @return 0 on success + */ static int rpmfcELF(rpmfc fc) /*@globals fileSystem, internalState @*/ /*@modifies fc, fileSystem, internalState @*/ @@ -853,6 +875,8 @@ typedef struct rpmfcApplyTbl_s { int colormask; } * rpmfcApplyTbl; +/** + */ /*@unchecked@*/ static struct rpmfcApplyTbl_s rpmfcApplyTable[] = { { rpmfcELF, RPMFC_ELF }, @@ -990,9 +1014,338 @@ assert(se != NULL); } fcav = argvFree(fcav); + /* XXX TODO dump fmagic baggage. */ return 0; } -/*@=bounds@*/ +/** + */ +typedef struct DepMsg_s * DepMsg_t; + +/** + */ +struct DepMsg_s { +/*@observer@*/ /*@null@*/ + const char * msg; +/*@observer@*/ + const char * argv[4]; + rpmTag ntag; + rpmTag vtag; + rpmTag ftag; + int mask; + int xor; +}; + +/** + */ +/*@unchecked@*/ +static struct DepMsg_s depMsgs[] = { + { "Provides", { "%{?__find_provides}", NULL, NULL, NULL }, + RPMTAG_PROVIDENAME, RPMTAG_PROVIDEVERSION, RPMTAG_PROVIDEFLAGS, + 0, -1 }, +#ifdef DYING + { "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 }, +#else + { "Requires(interp)", { NULL, "interp", NULL, NULL }, + RPMTAG_REQUIRENAME, RPMTAG_REQUIREVERSION, RPMTAG_REQUIREFLAGS, + _notpre(RPMSENSE_INTERP), 0 }, +#endif + { "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 }, + { "Conflicts", { "%{?__find_conflicts}", NULL, NULL, NULL }, + RPMTAG_CONFLICTNAME, RPMTAG_CONFLICTVERSION, RPMTAG_CONFLICTFLAGS, + 0, -1 }, + { "Obsoletes", { "%{?__find_obsoletes}", NULL, NULL, NULL }, + RPMTAG_OBSOLETENAME, RPMTAG_OBSOLETEVERSION, RPMTAG_OBSOLETEFLAGS, + 0, -1 }, + { NULL, { NULL, NULL, NULL, NULL }, 0, 0, 0, 0, 0 } +}; + +/*@unchecked@*/ +static DepMsg_t DepMsgs = depMsgs; + +/** + */ +static void printDeps(Header h) + /*@modifies h @*/ +{ + DepMsg_t dm; + rpmds ds = NULL; + int scareMem = 0; + const char * DNEVR; + int_32 Flags; + int bingo = 0; + + for (dm = DepMsgs; dm->msg != NULL; dm++) { + if (dm->ntag != -1) { + ds = rpmdsFree(ds); + ds = rpmdsNew(h, dm->ntag, scareMem); + } + if (dm->ftag == 0) + continue; + + ds = rpmdsInit(ds); + if (ds == NULL) + continue; /* XXX can't happen */ + + bingo = 0; + while (rpmdsNext(ds) >= 0) { + + Flags = rpmdsFlags(ds); + + if (!((Flags & dm->mask) ^ dm->xor)) + /*@innercontinue@*/ continue; + if (bingo == 0) { + rpmMessage(RPMMESS_NORMAL, "%s:", (dm->msg ? dm->msg : "")); + bingo = 1; + } + if ((DNEVR = rpmdsDNEVR(ds)) == NULL) + /*@innercontinue@*/ continue; /* XXX can't happen */ + rpmMessage(RPMMESS_NORMAL, " %s", DNEVR+2); + } + if (bingo) + rpmMessage(RPMMESS_NORMAL, "\n"); + } + ds = rpmdsFree(ds); +} + +/** + */ +static int rpmfcGenerateDependsHelper(const Spec spec, Package pkg, rpmfi fi) + /*@globals rpmGlobalMacroContext, fileSystem, internalState @*/ + /*@modifies fi, rpmGlobalMacroContext, fileSystem, internalState @*/ +{ + StringBuf sb_stdin; + StringBuf sb_stdout; + DepMsg_t dm; + int failnonzero = 0; + int rc = 0; + + /* + * Create file manifest buffer to deliver to dependency finder. + */ + sb_stdin = newStringBuf(); + fi = rpmfiInit(fi, 0); + if (fi != NULL) + while (rpmfiNext(fi) >= 0) + appendLineStringBuf(sb_stdin, rpmfiFN(fi)); + + for (dm = DepMsgs; dm->msg != NULL; dm++) { + int tag, tagflags; + char * s; + int xx; + + tag = (dm->ftag > 0) ? dm->ftag : dm->ntag; + tagflags = 0; + s = NULL; + + switch(tag) { + case RPMTAG_PROVIDEFLAGS: + if (!pkg->autoProv) + continue; + failnonzero = 1; + tagflags = RPMSENSE_FIND_PROVIDES; + /*@switchbreak@*/ break; + case RPMTAG_REQUIREFLAGS: + if (!pkg->autoReq) + continue; + failnonzero = 0; + tagflags = RPMSENSE_FIND_REQUIRES; + /*@switchbreak@*/ break; + default: + continue; + /*@notreached@*/ /*@switchbreak@*/ break; + } + + xx = rpmfcExec(dm->argv, sb_stdin, &sb_stdout, failnonzero); + if (xx == -1) + continue; + + s = rpmExpand(dm->argv[0], NULL); + rpmMessage(RPMMESS_NORMAL, _("Finding %s: %s\n"), dm->msg, + (s ? s : "")); + s = _free(s); + + if (sb_stdout == NULL) { + rc = RPMERR_EXEC; + rpmError(rc, _("Failed to find %s:\n"), dm->msg); + break; + } + + /* Parse dependencies into header */ + tagflags &= ~RPMSENSE_MULTILIB; + + rc = parseRCPOT(spec, pkg, getStringBuf(sb_stdout), tag, 0, tagflags); + sb_stdout = freeStringBuf(sb_stdout); + + if (rc) { + rpmError(rc, _("Failed to find %s:\n"), dm->msg); + break; + } + } + + sb_stdin = freeStringBuf(sb_stdin); + + return rc; +} + +int rpmfcGenerateDepends(const Spec spec, Package pkg) +{ + rpmfi fi = pkg->cpioList; + rpmfc fc = NULL; + rpmds ds; + const char * DNEVR; + int scareMem = 0; + ARGV_t av; + int ac = rpmfiFC(fi); + const void ** p; + int c; + int rc = 0; + int xx; + + /* Skip packages with no files. */ + if (ac <= 0) + return 0; + + /* Skip packages that have dependency generation disabled. */ + if (! (pkg->autoReq || pkg->autoProv)) + return 0; + + /* If new-fangled dependency generation is disabled ... */ + if (!rpmExpandNumeric("%{?_classify_file_types}")) { + /* ... then generate dependencies using %{__find_requires} et al. */ + rc = rpmfcGenerateDependsHelper(spec, pkg, fi); +/*@-noeffect@*/ + printDeps(pkg->header); +/*@=noeffect@*/ + return rc; + } + + /* Extract absolute file paths in argv format. */ + av = xcalloc(ac+1, sizeof(*av)); + + fi = rpmfiInit(fi, 0); + if (fi != NULL) + while ((c = rpmfiNext(fi)) >= 0) + av[c] = xstrdup(rpmfiFN(fi)); + av[ac] = NULL; + + /* Build file class dictionary. */ + fc = rpmfcNew(); + xx = rpmfcClassify(fc, av); + + /* Copy (and delete) manually generated dependencies to dictionary. */ + ds = rpmdsNew(pkg->header, RPMTAG_PROVIDENAME, scareMem); + ds = rpmdsInit(ds); + if (ds != NULL) + while (rpmdsNext(ds) >= 0) { + DNEVR = rpmdsDNEVR(ds); + if (DNEVR == NULL) + continue; + xx = rpmfcSaveArg(&fc->provides, DNEVR+2); + } + ds = rpmdsFree(ds); + + ds = rpmdsNew(pkg->header, RPMTAG_REQUIRENAME, scareMem); + ds = rpmdsInit(ds); + if (ds != NULL) + while (rpmdsNext(ds) >= 0) { + DNEVR = rpmdsDNEVR(ds); + if (DNEVR == NULL) + continue; + xx = rpmfcSaveArg(&fc->requires, DNEVR+2); + } + ds = rpmdsFree(ds); + + /* Build file/package dependency dictionary. */ + xx = rpmfcApply(fc); + + /* Add per-file colors(#files) */ + p = (const void **) argiData(fc->fcolor); + c = argiCount(fc->fcolor); +assert(ac == c); + if (p != NULL) + xx = headerAddEntry(pkg->header, RPMTAG_FILECOLOR, RPM_INT32_TYPE, + p, c); + + /* Add classes(#classes) */ + p = (const void **) argvData(fc->cdict); + c = argvCount(fc->cdict); + if (p != NULL) + xx = headerAddEntry(pkg->header, RPMTAG_CLASSDICT, RPM_STRING_ARRAY_TYPE, + p, c); + + /* Add per-file classes(#files) */ + p = (const void **) argiData(fc->fcdictx); + c = argiCount(fc->fcdictx); +assert(ac == c); + if (p != NULL) + xx = headerAddEntry(pkg->header, RPMTAG_FILECLASS, RPM_INT32_TYPE, + p, c); + + /* Add dependency dictionary(#dependencies) */ + p = (const void **) argvData(fc->ddict); + c = argvCount(fc->ddict); + if (p != NULL) + xx = headerAddEntry(pkg->header, RPMTAG_DEPENDSDICT, RPM_STRING_ARRAY_TYPE, + p, c); + + /* Add per-file dependency (start,number) pairs (#files) */ + p = (const void **) argiData(fc->fddictx); + c = argiCount(fc->fddictx); +assert(ac == c); + if (p != NULL) + xx = headerAddEntry(pkg->header, RPMTAG_FILEDEPENDSX, RPM_INT32_TYPE, + p, c); + + p = (const void **) argiData(fc->fddictn); + c = argiCount(fc->fddictn); +assert(ac == c); + if (p != NULL) + xx = headerAddEntry(pkg->header, RPMTAG_FILEDEPENDSN, RPM_INT32_TYPE, + p, c); + +/*@-noeffect@*/ + printDeps(pkg->header); +/*@=noeffect@*/ + +#ifdef NOTYET +if (fc != NULL) { +char buf[BUFSIZ]; +sprintf(buf, "final: files %d cdict[%d] %d%% ddictx[%d]", fc->nfiles, argvCount(fc->cdict), ((100 * fc->fknown)/fc->nfiles), argiCount(fc->ddictx)); +rpmfcPrint(buf, fc, NULL); +} +#endif + + /* Clean up. */ + fc = rpmfcFree(fc); + av = argvFree(av); + + return rc; +} |