summaryrefslogtreecommitdiff
path: root/build/rpmfc.c
diff options
context:
space:
mode:
Diffstat (limited to 'build/rpmfc.c')
-rw-r--r--build/rpmfc.c775
1 files changed, 410 insertions, 365 deletions
diff --git a/build/rpmfc.c b/build/rpmfc.c
index f8e340288..2fbfc69ab 100644
--- a/build/rpmfc.c
+++ b/build/rpmfc.c
@@ -1,6 +1,7 @@
#include "system.h"
#include <errno.h>
+#include <libgen.h>
#include <sys/select.h>
#include <sys/wait.h>
#include <signal.h>
@@ -16,6 +17,7 @@
#include <rpm/rpmfi.h>
#include <rpm/rpmstrpool.h>
+#include "lib/rpmfi_internal.h" /* rpmfiles stuff for now */
#include "build/rpmbuild_internal.h"
#include "debug.h"
@@ -32,13 +34,24 @@ typedef struct rpmfcAttr_s {
struct matchRule excl;
} * rpmfcAttr;
+typedef struct {
+ int fileIx;
+ rpmds dep;
+} rpmfcFileDep;
+
+typedef struct {
+ rpmfcFileDep *data;
+ int size;
+ int alloced;
+} rpmfcFileDeps;
+
/**
*/
struct rpmfc_s {
+ Package pkg;
int nfiles; /*!< no. of files */
int fknown; /*!< no. of classified files */
int fwhite; /*!< no. of "white" files */
- int ix; /*!< current file index */
int skipProv; /*!< Don't auto-generate Provides:? */
int skipReq; /*!< Don't auto-generate Requires:? */
char *buildRoot; /*!< (Build) root dir */
@@ -54,11 +67,9 @@ struct rpmfc_s {
ARGI_t fddictn; /*!< (no. files) file depends dictionary no. entries */
ARGI_t ddictx; /*!< (no. dependencies) file->dependency mapping */
rpmstrPool cdict; /*!< file class dictionary */
- rpmstrPool ddict; /*!< file depends dictionary */
+ rpmfcFileDeps fileDeps; /*!< file dependency mapping */
- rpmds provides; /*!< (no. provides) package provides */
- rpmds requires; /*!< (no. requires) package requires */
- rpmds supplements; /*!< (no. supplements) package supplements */
+ rpmstrPool pool; /*!< general purpose string storage */
};
struct rpmfcTokens_s {
@@ -87,22 +98,62 @@ static void ruleFree(struct matchRule *rule)
argvFree(rule->flags);
}
-static char *rpmfcAttrMacro(const char *name,
- const char *attr_prefix, const char *attr)
+static char *rpmfcAttrMacroV(const char *arg, va_list args)
{
- char *ret;
- if (attr_prefix && attr_prefix[0] != '\0')
- ret = rpmExpand("%{?__", name, "_", attr_prefix, "_", attr, "}", NULL);
- else
- ret = rpmExpand("%{?__", name, "_", attr, "}", NULL);
- return rstreq(ret, "") ? _free(ret) : ret;
+ const char *s;
+ int blen;
+ char *buf = NULL, *obuf;
+ char *pe;
+ va_list args2;
+
+ if (arg == NULL || rstreq(arg, ""))
+ return NULL;
+
+ va_copy(args2, args);
+ blen = sizeof("%{?_") - 1;
+ for (s = arg; s != NULL; s = va_arg(args, const char *)) {
+ blen += sizeof("_") - 1 + strlen(s);
+ }
+ blen += sizeof("}") - 1;
+
+ buf = xmalloc(blen + 1);
+
+ pe = buf;
+ pe = stpcpy(pe, "%{?_");
+ for (s = arg; s != NULL; s = va_arg(args2, const char *)) {
+ *pe++ = '_';
+ pe = stpcpy(pe, s);
+ }
+ va_end(args2);
+ *pe++ = '}';
+ *pe = '\0';
+
+ obuf = rpmExpand(buf, NULL);
+ free(buf);
+
+ return rstreq(obuf, "") ? _free(obuf) : obuf;
}
-static regex_t *rpmfcAttrReg(const char *name,
- const char *attr_prefix, const char *attr)
+static char *rpmfcAttrMacro(const char *arg, ...)
+{
+ va_list args;
+ char *s;
+
+ va_start(args, arg);
+ s = rpmfcAttrMacroV(arg, args);
+ va_end(args);
+ return s;
+}
+
+static regex_t *rpmfcAttrReg(const char *arg, ...)
{
regex_t *reg = NULL;
- char *pattern = rpmfcAttrMacro(name, attr_prefix, attr);
+ char *pattern;
+ va_list args;
+
+ va_start(args, arg);
+ pattern = rpmfcAttrMacroV(arg, args);
+ va_end(args);
if (pattern) {
reg = xcalloc(1, sizeof(*reg));
if (regcomp(reg, pattern, REG_EXTENDED) != 0) {
@@ -122,10 +173,19 @@ static rpmfcAttr rpmfcAttrNew(const char *name)
attr->name = xstrdup(name);
for (struct matchRule **rule = rules; rule && *rule; rule++) {
const char *prefix = (*rule == &attr->incl) ? NULL : "exclude";
- char *flags = rpmfcAttrMacro(name, prefix, "flags");
+ char *flags;
+
+ if (prefix) {
+ flags = rpmfcAttrMacro(name, prefix, "flags", NULL);
- (*rule)->path = rpmfcAttrReg(name, prefix, "path");
- (*rule)->magic = rpmfcAttrReg(name, prefix, "magic");
+ (*rule)->path = rpmfcAttrReg(name, prefix, "path", NULL);
+ (*rule)->magic = rpmfcAttrReg(name, prefix, "magic", NULL);
+ } else {
+ flags = rpmfcAttrMacro(name, "flags", NULL);
+
+ (*rule)->path = rpmfcAttrReg(name, "path", NULL);
+ (*rule)->magic = rpmfcAttrReg(name, "magic", NULL);
+ }
(*rule)->flags = argvSplitString(flags, ",", ARGV_SKIPEMPTY);
argvSort((*rule)->flags, NULL);
@@ -163,16 +223,17 @@ static int rpmfcExpandAppend(ARGV_t * argvp, ARGV_const_t av)
return 0;
}
-static rpmds rpmdsSingleNS(rpmTagVal tagN, const char *namespace,
+static rpmds rpmdsSingleNS(rpmstrPool pool,
+ rpmTagVal tagN, const char *namespace,
const char * N, const char * EVR, rpmsenseFlags Flags)
{
rpmds ds = NULL;
if (namespace) {
char *NSN = rpmExpand(namespace, "(", N, ")", NULL);
- ds = rpmdsSingle(tagN, NSN, EVR, Flags);
+ ds = rpmdsSinglePool(pool, tagN, NSN, EVR, Flags);
free(NSN);
} else {
- ds = rpmdsSingle(tagN, N, EVR, Flags);
+ ds = rpmdsSinglePool(pool, tagN, N, EVR, Flags);
}
return ds;
}
@@ -208,8 +269,6 @@ static StringBuf getOutputFrom(ARGV_t argv,
child = fork();
if (child == 0) {
- /* NSPR messes with SIGPIPE, reset to default for the kids */
- signal(SIGPIPE, SIG_DFL);
close(toProg[1]);
close(fromProg[0]);
@@ -369,6 +428,12 @@ int rpmfcExec(ARGV_const_t av, StringBuf sb_stdin, StringBuf * sb_stdoutp,
buf_stdin_len = strlen(buf_stdin);
}
+ if (_rpmfc_debug) {
+ char *cmd = argvJoin(xav, " ");
+ rpmlog(RPMLOG_DEBUG, "Executing %s on %s\n", cmd, buf_stdin);
+ free(cmd);
+ }
+
/* Read output from exec'd helper. */
sb = getOutputFrom(xav, buf_stdin, buf_stdin_len, failnonzero, buildRoot);
@@ -397,15 +462,15 @@ static void argvAddUniq(ARGV_t * argvp, const char * key)
#define hasAttr(_a, _n) (argvSearch((_a), (_n), NULL) != NULL)
-static void rpmfcAddFileDep(rpmstrPool ddict, int ix, rpmds ds, char deptype)
+static void rpmfcAddFileDep(rpmfcFileDeps *fileDeps, rpmds ds, int ix)
{
- if (ds) {
- char *key = NULL;
- rasprintf(&key, "%08d%c %s %s 0x%08x", ix, deptype,
- rpmdsN(ds), rpmdsEVR(ds), rpmdsFlags(ds));
- rpmstrPoolId(ddict, key, 1);
- free(key);
+ if (fileDeps->size == fileDeps->alloced) {
+ fileDeps->alloced <<= 2;
+ fileDeps->data = xrealloc(fileDeps->data,
+ fileDeps->alloced * sizeof(fileDeps->data[0]));
}
+ fileDeps->data[fileDeps->size].fileIx = ix;
+ fileDeps->data[fileDeps->size++].dep = ds;
}
static ARGV_t runCmd(const char *nsdep, const char *depname,
@@ -424,7 +489,7 @@ static ARGV_t runCmd(const char *nsdep, const char *depname,
appendLineStringBuf(sb_stdin, fn);
if (rpmfcExec(av, sb_stdin, &sb_stdout, 0, buildRoot) == 0) {
- argvSplit(&output, getStringBuf(sb_stdout), " \t\n\r");
+ argvSplit(&output, getStringBuf(sb_stdout), "\n\r");
}
argvFree(av);
@@ -436,74 +501,77 @@ static ARGV_t runCmd(const char *nsdep, const char *depname,
return output;
}
+struct addReqProvDataFc {
+ rpmfc fc;
+ const char *namespace;
+ regex_t *exclude;
+};
+
+static rpmRC addReqProvFc(void *cbdata, rpmTagVal tagN,
+ const char * N, const char * EVR, rpmsenseFlags Flags,
+ int index)
+{
+ struct addReqProvDataFc *data = cbdata;
+ rpmfc fc = data->fc;
+ const char *namespace = data->namespace;
+ regex_t *exclude = data->exclude;
+
+ rpmds ds = rpmdsSingleNS(fc->pool, tagN, namespace, N, EVR, Flags);
+ /* Add to package and file dependencies unless filtered */
+ if (regMatch(exclude, rpmdsDNEVR(ds)+2) == 0)
+ rpmfcAddFileDep(&fc->fileDeps, ds, index);
+
+ return RPMRC_OK;
+}
+
/**
* Run per-interpreter dependency helper.
* @param fc file classifier
+ * @param ix file index
* @param nsdep class name for interpreter (e.g. "perl")
* @param depname "provides" or "requires"
- * @param depsp fc->provides or fc->requires
* @param dsContext RPMSENSE_FIND_PROVIDES or RPMSENSE_FIND_REQUIRES
* @param tagN RPMTAG_PROVIDENAME or RPMTAG_REQUIRENAME
- * @return 0
+ * @return 0 on success
*/
-static int rpmfcHelper(rpmfc fc, const char *nsdep, const char *depname,
- rpmds *depsp, rpmsenseFlags dsContext, rpmTagVal tagN)
+static int rpmfcHelper(rpmfc fc, int ix,
+ const char *nsdep, const char *depname,
+ rpmsenseFlags dsContext, rpmTagVal tagN)
{
ARGV_t pav = NULL;
- const char * fn = fc->fn[fc->ix];
+ const char * fn = fc->fn[ix];
char *namespace = NULL;
int pac;
+ int rc = 0;
regex_t *exclude = NULL;
regex_t *exclude_from = NULL;
+ regex_t *global_exclude_from = NULL;
/* If the entire path is filtered out, there's nothing more to do */
- exclude_from = rpmfcAttrReg(depname, "exclude", "from");
+ exclude_from = rpmfcAttrReg(depname, "exclude", "from", NULL);
if (regMatch(exclude_from, fn+fc->brlen))
goto exit;
+ global_exclude_from = rpmfcAttrReg("global", depname, "exclude", "from", NULL);
+ if (regMatch(global_exclude_from, fn+fc->brlen))
+ goto exit;
+
pav = runCmd(nsdep, depname, fc->buildRoot, fn);
if (pav == NULL)
goto exit;
pac = argvCount(pav);
- namespace = rpmfcAttrMacro(nsdep, NULL, "namespace");
- exclude = rpmfcAttrReg(depname, NULL, "exclude");
-
- for (int i = 0; i < pac; i++) {
- rpmds ds = NULL;
- const char *N = pav[i];
- const char *EVR = "";
- rpmsenseFlags Flags = dsContext;
- if (pav[i+1] && strchr("=<>", *pav[i+1])) {
- i++;
- for (const char *s = pav[i]; *s; s++) {
- switch(*s) {
- default:
- break;
- case '=':
- Flags |= RPMSENSE_EQUAL;
- break;
- case '<':
- Flags |= RPMSENSE_LESS;
- break;
- case '>':
- Flags |= RPMSENSE_GREATER;
- break;
- }
- }
- i++;
- EVR = pav[i];
- }
-
- ds = rpmdsSingleNS(tagN, namespace, N, EVR, Flags);
+ namespace = rpmfcAttrMacro(nsdep, "namespace", NULL);
+ exclude = rpmfcAttrReg(depname, "exclude", NULL);
- /* Add to package and file dependencies unless filtered */
- if (regMatch(exclude, rpmdsDNEVR(ds)+2) == 0) {
- (void) rpmdsMerge(depsp, ds);
- rpmfcAddFileDep(fc->ddict, fc->ix, ds, tagN == RPMTAG_PROVIDENAME ? 'P' : 'R');
- }
+ struct addReqProvDataFc data;
+ data.fc = fc;
+ data.namespace = namespace;
+ data.exclude = exclude;
- rpmdsFree(ds);
+ for (int i = 0; i < pac; i++) {
+ if (parseRCPOT(NULL, fc->pkg, pav[i], tagN, ix, dsContext, addReqProvFc, &data))
+ rc++;
}
argvFree(pav);
@@ -512,55 +580,8 @@ static int rpmfcHelper(rpmfc fc, const char *nsdep, const char *depname,
exit:
regFree(exclude_from);
- return 0;
-}
-
-/**
- * Run per-interpreter Provides: dependency helper.
- * @param fc file classifier
- * @param nsdep class name for interpreter (e.g. "perl")
- * @return 0
- */
-static int rpmfcHelperProvides(rpmfc fc, const char * nsdep)
-{
- if (fc->skipProv)
- return 0;
-
- rpmfcHelper(fc, nsdep, "provides", &fc->provides, RPMSENSE_FIND_PROVIDES, RPMTAG_PROVIDENAME);
-
- return 0;
-}
-
-/**
- * Run per-interpreter Requires: dependency helper.
- * @param fc file classifier
- * @param nsdep class name for interpreter (e.g. "perl")
- * @return 0
- */
-static int rpmfcHelperRequires(rpmfc fc, const char * nsdep)
-{
- if (fc->skipReq)
- return 0;
-
- rpmfcHelper(fc, nsdep, "requires", &fc->requires, RPMSENSE_FIND_REQUIRES, RPMTAG_REQUIRENAME);
-
- return 0;
-}
-
-/**
- * Run per-interpreter Supplements: dependency helper.
- * @param fc file classifier
- * @param nsdep class name for interpreter (e.g. "perl")
- * @return 0
- */
-static int rpmfcHelperSupplements(rpmfc fc, const char * nsdep)
-{
- if (fc->skipReq)
- return 0;
-
- rpmfcHelper(fc, nsdep, "supplements", &fc->supplements, RPMSENSE_FIND_REQUIRES|RPMSENSE_STRONG|RPMSENSE_MISSINGOK, RPMTAG_ENHANCESNAME);
-
- return 0;
+ regFree(global_exclude_from);
+ return rc;
}
/* Only used for elf coloring and controlling RPMTAG_FILECLASS inclusion now */
@@ -635,7 +656,7 @@ static int matches(const struct matchRule *rule,
}
}
-static void rpmfcAttributes(rpmfc fc, const char *ftype, const char *fullpath)
+static void rpmfcAttributes(rpmfc fc, int ix, const char *ftype, const char *fullpath)
{
const char *path = fullpath + fc->brlen;
int is_executable = 0;
@@ -652,7 +673,7 @@ static void rpmfcAttributes(rpmfc fc, const char *ftype, const char *fullpath)
/* Add attributes on libmagic type & path pattern matches */
if (matches(&(*attr)->incl, ftype, path, is_executable))
- argvAddTokens(&fc->fattrs[fc->ix], (*attr)->name);
+ argvAddTokens(&fc->fattrs[ix], (*attr)->name);
}
}
@@ -676,39 +697,34 @@ static rpm_color_t rpmfcColor(const char * fmstr)
void rpmfcPrint(const char * msg, rpmfc fc, FILE * fp)
{
- rpm_color_t fcolor;
int ndx;
int dx;
int fx;
-int nprovides;
-int nrequires;
-
if (fp == NULL) fp = stderr;
if (msg)
fprintf(fp, "===================================== %s\n", msg);
-nprovides = rpmdsCount(fc->provides);
-nrequires = rpmdsCount(fc->requires);
-
if (fc)
for (fx = 0; fx < fc->nfiles; fx++) {
- rpmsid cx = fc->fcdictx[fx] + 1; /* id's are one off */
- fcolor = fc->fcolor[fx];
- ARGV_t fattrs = fc->fattrs[fx];
-
fprintf(fp, "%3d %s", fx, fc->fn[fx]);
- if (fcolor != RPMFC_BLACK)
+ if (_rpmfc_debug) {
+ rpmsid cx = fc->fcdictx[fx] + 1; /* id's are one off */
+ rpm_color_t fcolor = fc->fcolor[fx];
+ ARGV_t fattrs = fc->fattrs[fx];
+
+ if (fcolor != RPMFC_BLACK)
fprintf(fp, "\t0x%x", fc->fcolor[fx]);
- else
+ else
fprintf(fp, "\t%s", rpmstrPoolStr(fc->cdict, cx));
- if (fattrs) {
- char *attrs = argvJoin(fattrs, ",");
- fprintf(fp, " [%s]", attrs);
- free(attrs);
- } else {
- fprintf(fp, " [none]");
+ if (fattrs) {
+ char *attrs = argvJoin(fattrs, ",");
+ fprintf(fp, " [%s]", attrs);
+ free(attrs);
+ } else {
+ fprintf(fp, " [none]");
+ }
}
fprintf(fp, "\n");
@@ -724,32 +740,16 @@ assert(fx < fc->fddictn->nvals);
const char * depval;
unsigned char deptype;
unsigned ix;
+ rpmds ds;
ix = fc->ddictx->vals[dx++];
deptype = ((ix >> 24) & 0xff);
ix &= 0x00ffffff;
depval = NULL;
- switch (deptype) {
- default:
-assert(depval != NULL);
- break;
- case 'P':
- if (nprovides > 0) {
-assert(ix < nprovides);
- (void) rpmdsSetIx(fc->provides, ix-1);
- if (rpmdsNext(fc->provides) >= 0)
- depval = rpmdsDNEVR(fc->provides);
- }
- break;
- case 'R':
- if (nrequires > 0) {
-assert(ix < nrequires);
- (void) rpmdsSetIx(fc->requires, ix-1);
- if (rpmdsNext(fc->requires) >= 0)
- depval = rpmdsDNEVR(fc->requires);
- }
- break;
- }
+ ds = rpmfcDependencies(fc, rpmdsDToTagN(deptype));
+ (void) rpmdsSetIx(ds, ix-1);
+ if (rpmdsNext(ds) >= 0)
+ depval = rpmdsDNEVR(ds);
if (depval)
fprintf(fp, "\t%s\n", depval);
}
@@ -771,16 +771,19 @@ rpmfc rpmfcFree(rpmfc fc)
free(fc->fattrs);
free(fc->fcolor);
free(fc->fcdictx);
+ free(fc->pkg);
argiFree(fc->fddictx);
argiFree(fc->fddictn);
argiFree(fc->ddictx);
- rpmstrPoolFree(fc->ddict);
+ for (int i = 0; i < fc->fileDeps.size; i++) {
+ rpmdsFree(fc->fileDeps.data[i].dep);
+ }
+ free(fc->fileDeps.data);
+
rpmstrPoolFree(fc->cdict);
- rpmdsFree(fc->provides);
- rpmdsFree(fc->requires);
- rpmdsFree(fc->supplements);
+ rpmstrPoolFree(fc->pool);
memset(fc, 0, sizeof(*fc)); /* trash and burn */
free(fc);
}
@@ -794,6 +797,11 @@ rpmfc rpmfcCreate(const char *buildRoot, rpmFlags flags)
fc->buildRoot = xstrdup(buildRoot);
fc->brlen = strlen(buildRoot);
}
+ fc->pool = rpmstrPoolCreate();
+ fc->pkg = xcalloc(1, sizeof(*fc->pkg));
+ fc->fileDeps.alloced = 10;
+ fc->fileDeps.data = xmalloc(fc->fileDeps.alloced *
+ sizeof(fc->fileDeps.data[0]));
return fc;
}
@@ -802,97 +810,183 @@ rpmfc rpmfcNew(void)
return rpmfcCreate(NULL, 0);
}
+rpmds rpmfcDependencies(rpmfc fc, rpmTagVal tag)
+{
+ if (fc) {
+ return *packageDependencies(fc->pkg, tag);
+ }
+ return NULL;
+}
+
rpmds rpmfcProvides(rpmfc fc)
{
- return (fc != NULL ? fc->provides : NULL);
+ return rpmfcDependencies(fc, RPMTAG_PROVIDENAME);
}
rpmds rpmfcRequires(rpmfc fc)
{
- return (fc != NULL ? fc->requires : NULL);
+ return rpmfcDependencies(fc, RPMTAG_REQUIRENAME);
+}
+
+rpmds rpmfcRecommends(rpmfc fc)
+{
+ return rpmfcDependencies(fc, RPMTAG_RECOMMENDNAME);
+}
+
+rpmds rpmfcSuggests(rpmfc fc)
+{
+ return rpmfcDependencies(fc, RPMTAG_SUGGESTNAME);
}
rpmds rpmfcSupplements(rpmfc fc)
{
- return (fc != NULL ? fc->supplements : NULL);
+ return rpmfcDependencies(fc, RPMTAG_SUPPLEMENTNAME);
}
-rpmRC rpmfcApply(rpmfc fc)
+rpmds rpmfcEnhances(rpmfc fc)
{
- const char * s;
- char * se;
- rpmds ds;
- const char * N;
- const char * EVR;
- rpmsenseFlags Flags;
- unsigned char deptype;
- int nddict;
+ return rpmfcDependencies(fc, RPMTAG_ENHANCENAME);
+}
+
+rpmds rpmfcConflicts(rpmfc fc)
+{
+ return rpmfcDependencies(fc, RPMTAG_CONFLICTNAME);
+}
+
+rpmds rpmfcObsoletes(rpmfc fc)
+{
+ return rpmfcDependencies(fc, RPMTAG_OBSOLETENAME);
+}
+
+
+/* Versioned deps are less than unversioned deps */
+static int cmpVerDeps(const void *a, const void *b)
+{
+ rpmfcFileDep *fDepA = (rpmfcFileDep *) a;
+ rpmfcFileDep *fDepB = (rpmfcFileDep *) b;
+
+ int aIsVersioned = rpmdsFlags(fDepA->dep) & RPMSENSE_SENSEMASK ? 1 : 0;
+ int bIsVersioned = rpmdsFlags(fDepB->dep) & RPMSENSE_SENSEMASK ? 1 : 0;
+
+ return bIsVersioned - aIsVersioned;
+}
+
+/* Sort by index */
+static int cmpIndexDeps(const void *a, const void *b)
+{
+ rpmfcFileDep *fDepA = (rpmfcFileDep *) a;
+ rpmfcFileDep *fDepB = (rpmfcFileDep *) b;
+
+ return fDepA->fileIx - fDepB->fileIx;
+}
+
+/*
+ * Remove unversioned deps if corresponding versioned deps exist but only
+ * if the versioned dependency has the same type and the same color as the versioned.
+ */
+static void rpmfcNormalizeFDeps(rpmfc fc)
+{
+ rpmstrPool versionedDeps = rpmstrPoolCreate();
+ rpmfcFileDep *normalizedFDeps = xmalloc(fc->fileDeps.size *
+ sizeof(normalizedFDeps[0]));
+ int ix = 0;
+ char *depStr;
+
+ /* Sort. Versioned dependencies first */
+ qsort(fc->fileDeps.data, fc->fileDeps.size, sizeof(fc->fileDeps.data[0]),
+ cmpVerDeps);
+
+ for (int i = 0; i < fc->fileDeps.size; i++) {
+ switch (rpmdsTagN(fc->fileDeps.data[i].dep)) {
+ case RPMTAG_REQUIRENAME:
+ case RPMTAG_RECOMMENDNAME:
+ case RPMTAG_SUGGESTNAME:
+ rasprintf(&depStr, "%08x_%c_%s",
+ fc->fcolor[fc->fileDeps.data[i].fileIx],
+ rpmdsD(fc->fileDeps.data[i].dep),
+ rpmdsN(fc->fileDeps.data[i].dep));
+
+ if (rpmdsFlags(fc->fileDeps.data[i].dep) & RPMSENSE_SENSEMASK) {
+ /* preserve versioned require dependency */
+ normalizedFDeps[ix++] = fc->fileDeps.data[i];
+ rpmstrPoolId(versionedDeps, depStr, 1);
+ } else if (!rpmstrPoolId(versionedDeps, depStr, 0)) {
+ /* preserve unversioned require dep only if versioned dep doesn't exist */
+ normalizedFDeps[ix++] =fc-> fileDeps.data[i];
+ } else {
+ rpmdsFree(fc->fileDeps.data[i].dep);
+ }
+ free(depStr);
+ break;
+ default:
+ /* Preserve all non-require dependencies */
+ normalizedFDeps[ix++] = fc->fileDeps.data[i];
+ break;
+ }
+ }
+ rpmstrPoolFree(versionedDeps);
+
+ free(fc->fileDeps.data);
+ fc->fileDeps.data = normalizedFDeps;
+ fc->fileDeps.size = ix;
+}
+
+static rpmRC rpmfcApplyInternal(rpmfc fc)
+{
+ rpmds ds, * dsp;
int previx;
unsigned int val;
int dix;
int ix;
/* Generate package and per-file dependencies. */
- for (fc->ix = 0; fc->ix < fc->nfiles && fc->fn[fc->ix] != NULL; fc->ix++) {
- for (ARGV_t fattr = fc->fattrs[fc->ix]; fattr && *fattr; fattr++) {
- rpmfcHelperProvides(fc, *fattr);
- rpmfcHelperRequires(fc, *fattr);
- rpmfcHelperSupplements(fc, *fattr);
+ for (ix = 0; ix < fc->nfiles && fc->fn[ix] != NULL; ix++) {
+ for (ARGV_t fattr = fc->fattrs[ix]; fattr && *fattr; fattr++) {
+ if (!fc->skipProv) {
+ rpmfcHelper(fc, ix, *fattr, "provides",
+ RPMSENSE_FIND_PROVIDES, RPMTAG_PROVIDENAME);
+ }
+ if (!fc->skipReq) {
+ rpmfcHelper(fc, ix, *fattr, "requires",
+ RPMSENSE_FIND_REQUIRES, RPMTAG_REQUIRENAME);
+ rpmfcHelper(fc, ix, *fattr, "recommends",
+ RPMSENSE_FIND_REQUIRES, RPMTAG_RECOMMENDNAME);
+ rpmfcHelper(fc, ix, *fattr, "suggests",
+ RPMSENSE_FIND_REQUIRES, RPMTAG_SUGGESTNAME);
+ rpmfcHelper(fc, ix, *fattr, "supplements",
+ RPMSENSE_FIND_REQUIRES, RPMTAG_SUPPLEMENTNAME);
+ rpmfcHelper(fc, ix, *fattr, "enhances",
+ RPMSENSE_FIND_REQUIRES, RPMTAG_ENHANCENAME);
+ rpmfcHelper(fc, ix, *fattr, "conflicts",
+ RPMSENSE_FIND_REQUIRES, RPMTAG_CONFLICTNAME);
+ rpmfcHelper(fc, ix, *fattr, "obsoletes",
+ RPMSENSE_FIND_REQUIRES, RPMTAG_OBSOLETENAME);
+ }
}
}
/* No more additions after this, freeze pool to minimize memory use */
- rpmstrPoolFreeze(fc->ddict, 0);
+
+ rpmfcNormalizeFDeps(fc);
+ for (int i = 0; i < fc->fileDeps.size; i++) {
+ ds = fc->fileDeps.data[i].dep;
+ rpmdsMerge(packageDependencies(fc->pkg, rpmdsTagN(ds)), ds);
+ }
+
+ /* Sort by index */
+ qsort(fc->fileDeps.data, fc->fileDeps.size,
+ sizeof(fc->fileDeps.data[0]), cmpIndexDeps);
/* Generate per-file indices into package dependencies. */
- nddict = rpmstrPoolNumStr(fc->ddict);
previx = -1;
- for (rpmsid id = 1; id <= nddict; id++) {
- s = rpmstrPoolStr(fc->ddict, id);
-
- /* Parse out (file#,deptype,N,EVR,Flags) */
- ix = strtol(s, &se, 10);
- if ( se == NULL ) {
- rpmlog(RPMLOG_ERR, _("Conversion of %s to long integer failed.\n"), s);
- return RPMRC_FAIL;
- }
-
- deptype = *se++;
- se++;
- N = se;
- while (*se && *se != ' ')
- se++;
- *se++ = '\0';
- EVR = se;
- while (*se && *se != ' ')
- se++;
- *se++ = '\0';
- Flags = strtol(se, NULL, 16);
-
- dix = -1;
- switch (deptype) {
- default:
- break;
- case 'P':
- ds = rpmdsSingle(RPMTAG_PROVIDENAME, N, EVR, Flags);
- dix = rpmdsFind(fc->provides, ds);
- rpmdsFree(ds);
- break;
- case 'R':
- ds = rpmdsSingle(RPMTAG_REQUIRENAME, N, EVR, Flags);
- dix = rpmdsFind(fc->requires, ds);
- rpmdsFree(ds);
- break;
- case 'S':
- ds = rpmdsSingle(RPMTAG_ENHANCESNAME, N, EVR, Flags);
- dix = rpmdsFind(fc->supplements, ds);
- ds = rpmdsFree(ds);
- break;
- }
-
+ for (int i = 0; i < fc->fileDeps.size; i++) {
+ ds = fc->fileDeps.data[i].dep;
+ ix = fc->fileDeps.data[i].fileIx;
+ dsp = packageDependencies(fc->pkg, rpmdsTagN(ds));
+ dix = rpmdsFind(*dsp, ds);
if (dix < 0)
continue;
- val = (deptype << 24) | (dix & 0x00ffffff);
+ val = (rpmdsD(ds) << 24) | (dix & 0x00ffffff);
argiAdd(&fc->ddictx, -1, val);
if (previx != ix) {
@@ -901,8 +995,8 @@ rpmRC rpmfcApply(rpmfc fc)
}
if (fc->fddictn && fc->fddictn->vals)
fc->fddictn->vals[ix]++;
- }
+ }
return RPMRC_OK;
}
@@ -960,7 +1054,6 @@ rpmRC rpmfcClassify(rpmfc fc, ARGV_t argv, rpm_mode_t * fmode)
/* Build (sorted) file class dictionary. */
fc->cdict = rpmstrPoolCreate();
- fc->ddict = rpmstrPoolCreate();
ms = magic_open(msflags);
if (ms == NULL) {
@@ -974,13 +1067,13 @@ rpmRC rpmfcClassify(rpmfc fc, ARGV_t argv, rpm_mode_t * fmode)
goto exit;
}
- for (fc->ix = 0; fc->ix < fc->nfiles; fc->ix++) {
+ for (int ix = 0; ix < fc->nfiles; ix++) {
rpmsid ftypeId;
const char * ftype;
- const char * s = argv[fc->ix];
+ const char * s = argv[ix];
size_t slen = strlen(s);
int fcolor = RPMFC_BLACK;
- rpm_mode_t mode = (fmode ? fmode[fc->ix] : 0);
+ rpm_mode_t mode = (fmode ? fmode[ix] : 0);
int is_executable = (mode & (S_IXUSR|S_IXGRP|S_IXOTH));
switch (mode & S_IFMT) {
@@ -1026,15 +1119,15 @@ rpmRC rpmfcClassify(rpmfc fc, ARGV_t argv, rpm_mode_t * fmode)
rpmlog(RPMLOG_DEBUG, "%s: %s\n", s, ftype);
/* Save the path. */
- fc->fn[fc->ix] = xstrdup(s);
+ fc->fn[ix] = xstrdup(s);
/* Add (filtered) file coloring */
fcolor |= rpmfcColor(ftype);
/* Add attributes based on file type and/or path */
- rpmfcAttributes(fc, ftype, s);
+ rpmfcAttributes(fc, ix, ftype, s);
- fc->fcolor[fc->ix] = fcolor;
+ fc->fcolor[ix] = fcolor;
/* Add to file class dictionary and index array */
if (fcolor != RPMFC_WHITE && (fcolor & RPMFC_INCLUDE)) {
@@ -1045,7 +1138,7 @@ rpmRC rpmfcClassify(rpmfc fc, ARGV_t argv, rpm_mode_t * fmode)
fc->fwhite++;
}
/* Pool id's start from 1, for headers we want it from 0 */
- fc->fcdictx[fc->ix] = ftypeId - 1;
+ fc->fcdictx[ix] = ftypeId - 1;
}
rc = RPMRC_OK;
@@ -1101,6 +1194,12 @@ static struct DepMsg_s depMsgs[] = {
{ "Requires(postun)", { NULL, "postun", NULL, NULL },
-1, -1, RPMTAG_REQUIREFLAGS,
RPMSENSE_SCRIPT_POSTUN, 0 },
+ { "Requires(pretrans)", { NULL, "pretrans", NULL, NULL },
+ -1, -1, RPMTAG_REQUIREFLAGS,
+ RPMSENSE_PRETRANS, 0 },
+ { "Requires(posttrans)", { NULL, "posttrans", NULL, NULL },
+ -1, -1, RPMTAG_REQUIREFLAGS,
+ RPMSENSE_POSTTRANS, 0 },
{ "Requires", { "%{?__find_requires}", NULL, NULL, NULL },
-1, -1, RPMTAG_REQUIREFLAGS, /* XXX inherit name/version arrays */
RPMSENSE_FIND_REQUIRES|RPMSENSE_TRIGGERIN|RPMSENSE_TRIGGERUN|RPMSENSE_TRIGGERPOSTUN|RPMSENSE_TRIGGERPREIN, 0 },
@@ -1110,12 +1209,18 @@ static struct DepMsg_s depMsgs[] = {
{ "Obsoletes", { "%{?__find_obsoletes}", NULL, NULL, NULL },
RPMTAG_OBSOLETENAME, RPMTAG_OBSOLETEVERSION, RPMTAG_OBSOLETEFLAGS,
0, -1 },
- { "Enhances", { "%{?__find_enhances}", NULL, NULL, NULL },
- RPMTAG_ENHANCESNAME, RPMTAG_ENHANCESVERSION, RPMTAG_ENHANCESFLAGS,
- RPMSENSE_STRONG, RPMSENSE_STRONG },
+ { "Recommends", { "%{?__find_recommends}", NULL, NULL, NULL },
+ RPMTAG_RECOMMENDNAME, RPMTAG_RECOMMENDVERSION, RPMTAG_RECOMMENDFLAGS,
+ 0, -1 },
+ { "Suggests", { "%{?__find_suggests}", NULL, NULL, NULL },
+ RPMTAG_SUGGESTNAME, RPMTAG_SUGGESTVERSION, RPMTAG_SUGGESTFLAGS,
+ 0, -1 },
{ "Supplements", { "%{?__find_supplements}", NULL, NULL, NULL },
- RPMTAG_ENHANCESNAME, RPMTAG_ENHANCESVERSION, RPMTAG_ENHANCESFLAGS,
- RPMSENSE_STRONG, 0 },
+ RPMTAG_SUPPLEMENTNAME, RPMTAG_SUPPLEMENTVERSION, RPMTAG_SUPPLEMENTFLAGS,
+ 0, -1 },
+ { "Enhances", { "%{?__find_enhances}", NULL, NULL, NULL },
+ RPMTAG_ENHANCENAME, RPMTAG_ENHANCEVERSION, RPMTAG_ENHANCEFLAGS,
+ 0, -1 },
{ NULL, { NULL, NULL, NULL, NULL }, 0, 0, 0, 0, 0 }
};
@@ -1123,7 +1228,7 @@ static DepMsg_t DepMsgs = depMsgs;
/**
*/
-static void printDeps(Header h)
+static void printDeps(rpmfc fc)
{
DepMsg_t dm;
rpmds ds = NULL;
@@ -1133,8 +1238,7 @@ static void printDeps(Header h)
for (dm = DepMsgs; dm->msg != NULL; dm++) {
if (dm->ntag != -1) {
- rpmdsFree(ds);
- ds = rpmdsNew(h, dm->ntag, 0);
+ ds = rpmfcDependencies(fc, dm->ntag);
}
if (dm->ftag == 0)
continue;
@@ -1161,18 +1265,16 @@ static void printDeps(Header h)
if (bingo)
rpmlog(RPMLOG_NOTICE, "\n");
}
- rpmdsFree(ds);
}
-static rpmRC rpmfcGenerateDependsHelper(const rpmSpec spec, Package pkg, rpmfi fi)
+static rpmRC rpmfcApplyExternal(rpmfc fc)
{
StringBuf sb_stdin = newStringBuf();
rpmRC rc = RPMRC_OK;
/* Create file manifest buffer to deliver to dependency finder. */
- fi = rpmfiInit(fi, 0);
- while (rpmfiNext(fi) >= 0)
- appendLineStringBuf(sb_stdin, rpmfiFN(fi));
+ for (int i = 0; i < fc->nfiles; i++)
+ appendLineStringBuf(sb_stdin, fc->fn[i]);
for (DepMsg_t dm = DepMsgs; dm->msg != NULL; dm++) {
rpmTagVal tag = (dm->ftag > 0) ? dm->ftag : dm->ntag;
@@ -1181,25 +1283,23 @@ static rpmRC rpmfcGenerateDependsHelper(const rpmSpec spec, Package pkg, rpmfi f
StringBuf sb_stdout = NULL;
int failnonzero = (tag == RPMTAG_PROVIDEFLAGS);
- switch(tag) {
+ switch (tag) {
case RPMTAG_PROVIDEFLAGS:
- if (!pkg->autoProv)
+ if (fc->skipProv)
continue;
tagflags = RPMSENSE_FIND_PROVIDES;
break;
case RPMTAG_REQUIREFLAGS:
- if (!pkg->autoReq)
+ case RPMTAG_RECOMMENDFLAGS:
+ case RPMTAG_SUGGESTFLAGS:
+ case RPMTAG_SUPPLEMENTFLAGS:
+ case RPMTAG_ENHANCEFLAGS:
+ case RPMTAG_CONFLICTFLAGS:
+ case RPMTAG_OBSOLETEFLAGS:
+ if (fc->skipReq)
continue;
tagflags = RPMSENSE_FIND_REQUIRES;
break;
- case RPMTAG_ENHANCESFLAGS:
- if (!pkg->autoProv)
- continue;
- failnonzero = 0;
- tagflags = RPMSENSE_FIND_REQUIRES | RPMSENSE_MISSINGOK;
- if (strcmp(dm->msg, "Supplements") == 0)
- tagflags |= RPMSENSE_STRONG;
- break;
default:
continue;
break;
@@ -1210,7 +1310,7 @@ static rpmRC rpmfcGenerateDependsHelper(const rpmSpec spec, Package pkg, rpmfi f
free(s);
if (rpmfcExec(dm->argv, sb_stdin, &sb_stdout,
- failnonzero, spec->buildRoot) == -1)
+ failnonzero, fc->buildRoot) == -1)
continue;
if (sb_stdout == NULL) {
@@ -1220,7 +1320,7 @@ static rpmRC rpmfcGenerateDependsHelper(const rpmSpec spec, Package pkg, rpmfi f
}
/* Parse dependencies into header */
- rc = parseRCPOT(spec, pkg, getStringBuf(sb_stdout), tag, 0, tagflags);
+ rc = parseRCPOT(NULL, fc->pkg, getStringBuf(sb_stdout), dm->ntag != -1 ? dm->ntag : RPMTAG_REQUIRENAME, 0, tagflags, addReqProvPkg, NULL);
freeStringBuf(sb_stdout);
if (rc) {
@@ -1234,11 +1334,26 @@ static rpmRC rpmfcGenerateDependsHelper(const rpmSpec spec, Package pkg, rpmfi f
return rc;
}
+rpmRC rpmfcApply(rpmfc fc)
+{
+ rpmRC rc;
+ /* If new-fangled dependency generation is disabled ... */
+ if (!rpmExpandNumeric("%{?_use_internal_dependency_generator}")) {
+ /* ... then generate dependencies using %{__find_requires} et al. */
+ rpmlog(RPMLOG_WARNING,
+ _("Deprecated external dependency generator is used!\n"));
+ rc = rpmfcApplyExternal(fc);
+ } else {
+ /* ... otherwise generate per-file dependencies */
+ rc = rpmfcApplyInternal(fc);
+ }
+ return rc;
+}
+
rpmRC rpmfcGenerateDepends(const rpmSpec spec, Package pkg)
{
- rpmfi fi = pkg->cpioList;
+ rpmfi fi = rpmfilesIter(pkg->cpioList, RPMFI_ITER_FWD);
rpmfc fc = NULL;
- ARGV_t av = NULL;
rpm_mode_t * fmode = NULL;
int ac = rpmfiFC(fi);
int genConfigDeps = 0;
@@ -1250,82 +1365,46 @@ rpmRC rpmfcGenerateDepends(const rpmSpec spec, Package pkg)
if (ac <= 0)
goto exit;
- /* Skip packages that have dependency generation disabled. */
- if (! (pkg->autoReq || pkg->autoProv))
- goto exit;
-
- /* If new-fangled dependency generation is disabled ... */
- if (!rpmExpandNumeric("%{?_use_internal_dependency_generator}")) {
- /* ... then generate dependencies using %{__find_requires} et al. */
- rc = rpmfcGenerateDependsHelper(spec, pkg, fi);
- goto exit;
- }
-
/* Extract absolute file paths in argv format. */
- av = xcalloc(ac+1, sizeof(*av));
fmode = xcalloc(ac+1, sizeof(*fmode));
fi = rpmfiInit(fi, 0);
while ((idx = rpmfiNext(fi)) >= 0) {
/* Does package have any %config files? */
genConfigDeps |= (rpmfiFFlags(fi) & RPMFILE_CONFIG);
-
- av[idx] = xstrdup(rpmfiFN(fi));
fmode[idx] = rpmfiFMode(fi);
}
- av[ac] = NULL;
fc = rpmfcCreate(spec->buildRoot, 0);
+ free(fc->pkg);
+ fc->pkg = pkg;
fc->skipProv = !pkg->autoProv;
fc->skipReq = !pkg->autoReq;
- /* Copy (and delete) manually generated dependencies to dictionary. */
- if (!fc->skipProv) {
- rpmds ds = rpmdsNew(pkg->header, RPMTAG_PROVIDENAME, 0);
- rpmdsMerge(&fc->provides, ds);
- rpmdsFree(ds);
-
- headerDel(pkg->header, RPMTAG_PROVIDENAME);
- headerDel(pkg->header, RPMTAG_PROVIDEVERSION);
- headerDel(pkg->header, RPMTAG_PROVIDEFLAGS);
-
+ if (!fc->skipProv && genConfigDeps) {
/* Add config dependency, Provides: config(N) = EVR */
- if (genConfigDeps) {
- ds = rpmdsSingleNS(RPMTAG_PROVIDENAME, "config",
- rpmdsN(pkg->ds), rpmdsEVR(pkg->ds),
- (RPMSENSE_EQUAL|RPMSENSE_CONFIG));
- rpmdsMerge(&fc->provides, ds);
- rpmdsFree(ds);
- }
+ rpmds ds = rpmdsSingleNS(fc->pool, RPMTAG_PROVIDENAME, "config",
+ rpmdsN(pkg->ds), rpmdsEVR(pkg->ds),
+ (RPMSENSE_EQUAL|RPMSENSE_CONFIG));
+ rpmdsMerge(packageDependencies(pkg, RPMTAG_PROVIDENAME), ds);
+ rpmdsFree(ds);
}
-
- if (!fc->skipReq) {
- rpmds ds = rpmdsNew(pkg->header, RPMTAG_REQUIRENAME, 0);
- rpmdsMerge(&fc->requires, ds);
+ if (!fc->skipReq && genConfigDeps) {
+ rpmds ds = rpmdsSingleNS(fc->pool, RPMTAG_REQUIRENAME, "config",
+ rpmdsN(pkg->ds), rpmdsEVR(pkg->ds),
+ (RPMSENSE_EQUAL|RPMSENSE_CONFIG));
+ rpmdsMerge(packageDependencies(pkg, RPMTAG_REQUIRENAME), ds);
rpmdsFree(ds);
-
- headerDel(pkg->header, RPMTAG_REQUIRENAME);
- headerDel(pkg->header, RPMTAG_REQUIREVERSION);
- headerDel(pkg->header, RPMTAG_REQUIREFLAGS);
-
- /* Add config dependency, Requires: config(N) = EVR */
- if (genConfigDeps) {
- ds = rpmdsSingleNS(RPMTAG_REQUIRENAME, "config",
- rpmdsN(pkg->ds), rpmdsEVR(pkg->ds),
- (RPMSENSE_EQUAL|RPMSENSE_CONFIG));
- rpmdsMerge(&fc->requires, ds);
- rpmdsFree(ds);
- }
}
/* Build file class dictionary. */
- rc = rpmfcClassify(fc, av, fmode);
+ rc = rpmfcClassify(fc, pkg->dpaths, fmode);
if ( rc != RPMRC_OK )
goto exit;
/* Build file/package dependency dictionary. */
rc = rpmfcApply(fc);
- if ( rc != RPMRC_OK )
+ if (rc != RPMRC_OK)
goto exit;
/* Add per-file colors(#files) */
@@ -1343,54 +1422,18 @@ rpmRC rpmfcGenerateDepends(const rpmSpec spec, Package pkg)
/* Add per-file classes(#files) */
headerPutUint32(pkg->header, RPMTAG_FILECLASS, fc->fcdictx, fc->nfiles);
- /* Add Provides: */
- if (!fc->skipProv) {
- rpmds pi = rpmdsInit(fc->provides);
- while (rpmdsNext(pi) >= 0) {
- rpmsenseFlags flags = rpmdsFlags(pi);
-
- headerPutString(pkg->header, RPMTAG_PROVIDENAME, rpmdsN(pi));
- headerPutString(pkg->header, RPMTAG_PROVIDEVERSION, rpmdsEVR(pi));
- headerPutUint32(pkg->header, RPMTAG_PROVIDEFLAGS, &flags, 1);
- }
- }
-
- /* Add Requires: */
- if (!fc->skipReq) {
- rpmds pi = rpmdsInit(fc->requires);
- while (rpmdsNext(pi) >= 0) {
- rpmsenseFlags flags = rpmdsFlags(pi);
-
- headerPutString(pkg->header, RPMTAG_REQUIRENAME, rpmdsN(pi));
- headerPutString(pkg->header, RPMTAG_REQUIREVERSION, rpmdsEVR(pi));
- headerPutUint32(pkg->header, RPMTAG_REQUIREFLAGS, &flags, 1);
- }
- }
-
- /* Add Supplements: */
- if (!fc->skipReq) {
- rpmds pi = rpmdsInit(fc->supplements);
- while (rpmdsNext(pi) >= 0) {
- rpmsenseFlags flags = rpmdsFlags(pi);
-
- headerPutString(pkg->header, RPMTAG_ENHANCESNAME, rpmdsN(pi));
- headerPutString(pkg->header, RPMTAG_ENHANCESVERSION, rpmdsEVR(pi));
- headerPutUint32(pkg->header, RPMTAG_ENHANCESFLAGS, &flags, 1);
- }
- }
-
/* Add dependency dictionary(#dependencies) */
if (rpmtdFromArgi(&td, RPMTAG_DEPENDSDICT, fc->ddictx)) {
headerPut(pkg->header, &td, HEADERPUT_DEFAULT);
- }
- /* Add per-file dependency (start,number) pairs (#files) */
- if (rpmtdFromArgi(&td, RPMTAG_FILEDEPENDSX, fc->fddictx)) {
- headerPut(pkg->header, &td, HEADERPUT_DEFAULT);
- }
+ /* Add per-file dependency (start,number) pairs (#files) */
+ if (rpmtdFromArgi(&td, RPMTAG_FILEDEPENDSX, fc->fddictx)) {
+ headerPut(pkg->header, &td, HEADERPUT_DEFAULT);
+ }
- if (rpmtdFromArgi(&td, RPMTAG_FILEDEPENDSN, fc->fddictn)) {
- headerPut(pkg->header, &td, HEADERPUT_DEFAULT);
+ if (rpmtdFromArgi(&td, RPMTAG_FILEDEPENDSN, fc->fddictn)) {
+ headerPut(pkg->header, &td, HEADERPUT_DEFAULT);
+ }
}
@@ -1403,12 +1446,14 @@ rpmRC rpmfcGenerateDepends(const rpmSpec spec, Package pkg)
free(msg);
}
exit:
- printDeps(pkg->header);
+ printDeps(fc);
/* Clean up. */
+ if (fc)
+ fc->pkg = NULL;
free(fmode);
rpmfcFree(fc);
- argvFree(av);
+ rpmfiFree(fi);
return rc;
}