Permit file objects in python header constructor
[platform/upstream/rpm.git] / build / rpmfc.c
index f46deae..308d7da 100644 (file)
@@ -1,15 +1,6 @@
 #include "system.h"
 
-#include <signal.h>    /* getOutputFrom() */
-
-#include <rpmbuild.h>
-#include <argv.h>
-#include <rpmfc.h>
-
-#define        _RPMDS_INTERNAL
-#include <rpmds.h>
-#include <rpmfi.h>
-
+#include <signal.h>
 #if HAVE_GELF_H
 #include <gelf.h>
 
 
 #endif
 
+#include <rpm/header.h>
+#include <rpm/rpmbuild.h>
+#include <rpm/argv.h>
+#include <rpm/rpmfc.h>
+#include <rpm/rpmlog.h>
+#include <rpm/rpmfileutil.h>
+
+#include <rpm/rpmds.h>
+#include <rpm/rpmfi.h>
+
 #include "debug.h"
 
 /**
@@ -51,10 +52,16 @@ struct rpmfc_s {
 
 };
 
+/**
+ */
+struct rpmfcTokens_s {
+    const char * token;
+    rpm_color_t colors;
+};  
 
 /**
  */
-static int rpmfcExpandAppend(ARGV_t * argvp, const ARGV_t av)
+static int rpmfcExpandAppend(ARGV_t * argvp, ARGV_const_t av)
 {
     ARGV_t argv = *argvp;
     int argc = argvCount(argv);
@@ -80,7 +87,7 @@ static int rpmfcExpandAppend(ARGV_t * argvp, const ARGV_t av)
  * @return             buffered stdout from script, NULL on error
  */     
 static StringBuf getOutputFrom(const char * dir, ARGV_t argv,
-                        const char * writePtr, int writeBytesLeft,
+                        const char * writePtr, size_t writeBytesLeft,
                         int failNonZero)
 {
     pid_t child, reaped;
@@ -95,9 +102,11 @@ static StringBuf getOutputFrom(const char * dir, ARGV_t argv,
     oldhandler = signal(SIGPIPE, SIG_IGN);
 
     toProg[0] = toProg[1] = 0;
-    (void) pipe(toProg);
     fromProg[0] = fromProg[1] = 0;
-    (void) pipe(fromProg);
+    if (pipe(toProg) < 0 || pipe(fromProg) < 0) {
+       rpmlog(RPMLOG_ERR, _("Couldn't create pipe for %s: %m\n"), argv[0]);
+       return NULL;
+    }
     
     if (!(child = fork())) {
        (void) close(toProg[1]);
@@ -109,22 +118,24 @@ static StringBuf getOutputFrom(const char * dir, ARGV_t argv,
        (void) close(toProg[0]);
        (void) close(fromProg[1]);
 
-       if (dir) {
-           (void) chdir(dir);
+       if (dir && chdir(dir)) {
+           rpmlog(RPMLOG_ERR, _("Couldn't chdir to %s: %s\n"),
+                   dir, strerror(errno));
+           _exit(EXIT_FAILURE);
        }
        
-       rpmlog(RPMLOG_DEBUG, _("\texecv(%s) pid %d\n"),
+       rpmlog(RPMLOG_DEBUG, "\texecv(%s) pid %d\n",
                         argv[0], (unsigned)getpid());
 
        unsetenv("MALLOC_CHECK_");
        (void) execvp(argv[0], (char *const *)argv);
        /* XXX this error message is probably not seen. */
-       rpmlog(RPMERR_EXEC, _("Couldn't exec %s: %s\n"),
+       rpmlog(RPMLOG_ERR, _("Couldn't exec %s: %s\n"),
                argv[0], strerror(errno));
-       _exit(RPMERR_EXEC);
+       _exit(EXIT_FAILURE);
     }
     if (child < 0) {
-       rpmlog(RPMERR_FORK, _("Couldn't fork %s: %s\n"),
+       rpmlog(RPMLOG_ERR, _("Couldn't fork %s: %s\n"),
                argv[0], strerror(errno));
        return NULL;
     }
@@ -206,31 +217,31 @@ top:
 
     /* Collect status from prog */
     reaped = waitpid(child, &status, 0);
-    rpmlog(RPMLOG_DEBUG, _("\twaitpid(%d) rc %d status %x\n"),
+    rpmlog(RPMLOG_DEBUG, "\twaitpid(%d) rc %d status %x\n",
         (unsigned)child, (unsigned)reaped, status);
 
     if (failNonZero && (!WIFEXITED(status) || WEXITSTATUS(status))) {
-       rpmlog(RPMERR_EXEC, _("%s failed\n"), argv[0]);
+       rpmlog(RPMLOG_ERR, _("%s failed\n"), argv[0]);
        return NULL;
     }
     if (writeBytesLeft) {
-       rpmlog(RPMERR_EXEC, _("failed to write all data to %s\n"), argv[0]);
+       rpmlog(RPMLOG_ERR, _("failed to write all data to %s\n"), argv[0]);
        return NULL;
     }
     return readBuff;
 }
 
-int rpmfcExec(ARGV_t av, StringBuf sb_stdin, StringBuf * sb_stdoutp,
+int rpmfcExec(ARGV_const_t av, StringBuf sb_stdin, StringBuf * sb_stdoutp,
                int failnonzero)
 {
-    const char * s = NULL;
+    char * s = NULL;
     ARGV_t xav = NULL;
     ARGV_t pav = NULL;
     int pac = 0;
     int ec = -1;
     StringBuf sb = NULL;
     const char * buf_stdin = NULL;
-    int buf_stdin_len = 0;
+    size_t buf_stdin_len = 0;
     int xx;
 
     if (sb_stdoutp)
@@ -291,26 +302,23 @@ static int rpmfcSaveArg(ARGV_t * argvp, const char * key)
     return rc;
 }
 
-static char * rpmfcFileDep(char * buf, int ix,
-               rpmds ds)
+static void rpmfcAddFileDep(ARGV_t * argvp, int ix, rpmds ds)
 {
-    int_32 tagN = rpmdsTagN(ds);
-    char deptype = 'X';
+    rpmTag tagN = rpmdsTagN(ds);
+    char *key = NULL;
 
-    buf[0] = '\0';
-    switch (tagN) {
-    case RPMTAG_PROVIDENAME:
-       deptype = 'P';
-       break;
-    case RPMTAG_REQUIRENAME:
-       deptype = 'R';
-       break;
+    if (ds == NULL) {
+       return;
     }
-    if (ds != NULL)
-       sprintf(buf, "%08d%c %s %s 0x%08x", ix, deptype,
+
+    assert(tagN == RPMTAG_PROVIDENAME || tagN == RPMTAG_REQUIRENAME);
+
+    rasprintf(&key, "%08d%c %s %s 0x%08x", ix, tagN == RPMTAG_PROVIDENAME ? 'P' : 'R',
                rpmdsN(ds), rpmdsEVR(ds), rpmdsFlags(ds));
-    return buf;
-};
+
+    rpmfcSaveArg(argvp, key);
+    free(key);
+}
 
 /**
  * Run per-interpreter dependency helper.
@@ -322,14 +330,15 @@ static char * rpmfcFileDep(char * buf, int ix,
 static int rpmfcHelper(rpmfc fc, unsigned char deptype, const char * nsdep)
 {
     const char * fn = fc->fn[fc->ix];
-    char buf[BUFSIZ];
+    char *buf = NULL;
     StringBuf sb_stdout = NULL;
     StringBuf sb_stdin;
-    const char *av[2];
+    char *av[2];
     rpmds * depsp, ds;
     const char * N;
     const char * EVR;
-    int_32 Flags, dsContext, tagN;
+    rpmsenseFlags Flags, dsContext;
+    rpmTag tagN;
     ARGV_t pav;
     const char * s;
     int pac;
@@ -343,7 +352,7 @@ static int rpmfcHelper(rpmfc fc, unsigned char deptype, const char * nsdep)
     case 'P':
        if (fc->skipProv)
            return 0;
-       xx = snprintf(buf, sizeof(buf), "%%{?__%s_provides}", nsdep);
+       rasprintf(&buf, "%%{?__%s_provides}", nsdep);
        depsp = &fc->provides;
        dsContext = RPMSENSE_FIND_PROVIDES;
        tagN = RPMTAG_PROVIDENAME;
@@ -351,13 +360,12 @@ static int rpmfcHelper(rpmfc fc, unsigned char deptype, const char * nsdep)
     case 'R':
        if (fc->skipReq)
            return 0;
-       xx = snprintf(buf, sizeof(buf), "%%{?__%s_requires}", nsdep);
+       rasprintf(&buf, "%%{?__%s_requires}", nsdep);
        depsp = &fc->requires;
        dsContext = RPMSENSE_FIND_REQUIRES;
        tagN = RPMTAG_REQUIRENAME;
        break;
     }
-    buf[sizeof(buf)-1] = '\0';
     av[0] = buf;
     av[1] = NULL;
 
@@ -416,7 +424,7 @@ assert(EVR != NULL);
            xx = rpmdsMerge(depsp, ds);
 
            /* Add to file dependencies. */
-           xx = rpmfcSaveArg(&fc->ddict, rpmfcFileDep(buf, fc->ix, ds));
+           rpmfcAddFileDep(&fc->ddict, fc->ix, ds);
 
            ds = rpmdsFree(ds);
        }
@@ -424,13 +432,14 @@ assert(EVR != NULL);
        pav = argvFree(pav);
     }
     sb_stdout = freeStringBuf(sb_stdout);
+    free(buf);
 
     return 0;
 }
 
 /**
  */
-static struct rpmfcTokens_s rpmfcTokens[] = {
+static const struct rpmfcTokens_s const rpmfcTokens[] = {
   { "directory",               RPMFC_DIRECTORY|RPMFC_INCLUDE },
 
   { " shared object",          RPMFC_LIBRARY },
@@ -443,7 +452,6 @@ static struct rpmfcTokens_s rpmfcTokens[] = {
   { "ELF 64-bit",              RPMFC_ELF64|RPMFC_INCLUDE },
 
   { " script",                 RPMFC_SCRIPT },
-  { " text",                   RPMFC_TEXT },
   { " document",               RPMFC_DOCUMENT },
 
   { " compressed",             RPMFC_COMPRESSED },
@@ -465,7 +473,7 @@ static struct rpmfcTokens_s rpmfcTokens[] = {
 
   /* XXX .NET executables and libraries.  file(1) cannot differ from win32 
    * executables unfortunately :( */
-  { "PE executable",            RPMFC_MONO|RPMFC_INCLUDE },
+  { "Mono/.Net assembly",       RPMFC_MONO|RPMFC_INCLUDE },
 
   { "current ar archive",      RPMFC_STATIC|RPMFC_LIBRARY|RPMFC_ARCHIVE|RPMFC_INCLUDE },
 
@@ -476,6 +484,7 @@ static struct rpmfcTokens_s rpmfcTokens[] = {
   { "RPM v4",                  RPMFC_ARCHIVE|RPMFC_INCLUDE },
 
   { " image",                  RPMFC_IMAGE|RPMFC_INCLUDE },
+  { " font metrics",           RPMFC_WHITE|RPMFC_INCLUDE },
   { " font",                   RPMFC_FONT|RPMFC_INCLUDE },
   { " Font",                   RPMFC_FONT|RPMFC_INCLUDE },
 
@@ -488,18 +497,14 @@ static struct rpmfcTokens_s rpmfcTokens[] = {
   { "SGML",                    RPMFC_WHITE|RPMFC_INCLUDE },
   { "XML",                     RPMFC_WHITE|RPMFC_INCLUDE },
 
-  { " program text",           RPMFC_WHITE|RPMFC_INCLUDE },
   { " source",                 RPMFC_WHITE|RPMFC_INCLUDE },
   { "GLS_BINARY_LSB_FIRST",    RPMFC_WHITE|RPMFC_INCLUDE },
   { " DB ",                    RPMFC_WHITE|RPMFC_INCLUDE },
 
-  { "ASCII English text",      RPMFC_WHITE|RPMFC_INCLUDE },
-  { "ASCII text",              RPMFC_WHITE|RPMFC_INCLUDE },
-  { "ISO-8859 text",           RPMFC_WHITE|RPMFC_INCLUDE },
-
   { "symbolic link to",                RPMFC_SYMLINK },
   { "socket",                  RPMFC_DEVICE },
   { "special",                 RPMFC_DEVICE },
+  { " text",                   RPMFC_TEXT|RPMFC_INCLUDE },
 
   { "ASCII",                   RPMFC_WHITE },
   { "ISO-8859",                        RPMFC_WHITE },
@@ -527,7 +532,7 @@ static struct rpmfcTokens_s rpmfcTokens[] = {
 int rpmfcColoring(const char * fmstr)
 {
     rpmfcToken fct;
-    int fcolor = RPMFC_BLACK;
+    rpm_color_t fcolor = RPMFC_BLACK;
 
     for (fct = rpmfcTokens; fct->token != NULL; fct++) {
        if (strstr(fmstr, fct->token) == NULL)
@@ -541,7 +546,7 @@ int rpmfcColoring(const char * fmstr)
 
 void rpmfcPrint(const char * msg, rpmfc fc, FILE * fp)
 {
-    int fcolor;
+    rpm_color_t fcolor;
     int ndx;
     int cx;
     int dx;
@@ -717,16 +722,16 @@ static int rpmfcSCRIPT(rpmfc fc)
            xx = rpmdsMerge(&fc->requires, ds);
 
            /* Add to file requires. */
-           xx = rpmfcSaveArg(&fc->ddict, rpmfcFileDep(se, fc->ix, ds));
+           rpmfcAddFileDep(&fc->ddict, fc->ix, ds);
 
            ds = rpmdsFree(ds);
        }
 
        /* Set color based on interpreter name. */
        bn = basename(s);
-       if (!strcmp(bn, "perl"))
+       if (rstreq(bn, "perl"))
            fc->fcolor->vals[fc->ix] |= RPMFC_PERL;
-       else if (!strncmp(bn, "python", sizeof("python")-1))
+       else if (rstreqn(bn, "python", sizeof("python")-1))
            fc->fcolor->vals[fc->ix] |= RPMFC_PYTHON;
 
        break;
@@ -792,13 +797,13 @@ static int rpmfcELF(rpmfc fc)
     int fdno;
     int cnt2;
     int cnt;
-    char buf[BUFSIZ];
+    char *buf = NULL;
     const char * s;
     struct stat sb, * st = &sb;
-    const char * soname = NULL;
+    char * soname = NULL;
     rpmds * depsp, ds;
-    int_32 tagN, dsContext;
-    char * t;
+    rpmTag tagN;
+    rpmsenseFlags dsContext;
     int xx;
     int isElf64;
     int isDSO;
@@ -874,17 +879,14 @@ static int rpmfcELF(rpmfc fc)
                        } else
                        if (soname != NULL
                         && !(filter_GLIBC_PRIVATE != 0
-                               && !strcmp(s, "GLIBC_PRIVATE")))
+                               && rstreq(s, "GLIBC_PRIVATE")))
                        {
-                           buf[0] = '\0';
-                           t = buf;
-                           t = stpcpy( stpcpy( stpcpy( stpcpy(t, soname), "("), s), ")");
-
+                           rasprintf(&buf, "%s(%s)%s", soname, s,
 #if !defined(__alpha__)
-                           if (isElf64)
-                               t = stpcpy(t, "(64bit)");
+                                                       isElf64 ? "(64bit)" : "");
+#else
+                                                       "");
 #endif
-                           t++;
 
                            /* Add to package provides. */
                            ds = rpmdsSingle(RPMTAG_PROVIDES,
@@ -892,10 +894,10 @@ static int rpmfcELF(rpmfc fc)
                            xx = rpmdsMerge(&fc->provides, ds);
 
                            /* Add to file dependencies. */
-                           xx = rpmfcSaveArg(&fc->ddict,
-                                       rpmfcFileDep(t, fc->ix, ds));
+                           rpmfcAddFileDep(&fc->ddict, fc->ix, ds);
 
                            ds = rpmdsFree(ds);
+                           free(buf);
                        }
                        auxoffset += aux->vda_next;
                    }
@@ -934,17 +936,14 @@ static int rpmfcELF(rpmfc fc)
                        /* Filter dependencies that contain GLIBC_PRIVATE */
                        if (soname != NULL
                         && !(filter_GLIBC_PRIVATE != 0
-                               && !strcmp(s, "GLIBC_PRIVATE")))
+                               && rstreq(s, "GLIBC_PRIVATE")))
                        {
-                           buf[0] = '\0';
-                           t = buf;
-                           t = stpcpy( stpcpy( stpcpy( stpcpy(t, soname), "("), s), ")");
-
+                           rasprintf(&buf, "%s(%s)%s", soname, s,
 #if !defined(__alpha__)
-                           if (isElf64)
-                               t = stpcpy(t, "(64bit)");
+                                                       isElf64 ? "(64bit)" : "");
+#else
+                                                       "");
 #endif
-                           t++;
 
                            /* Add to package dependencies. */
                            ds = rpmdsSingle(RPMTAG_REQUIRENAME,
@@ -952,9 +951,9 @@ static int rpmfcELF(rpmfc fc)
                            xx = rpmdsMerge(&fc->requires, ds);
 
                            /* Add to file dependencies. */
-                           xx = rpmfcSaveArg(&fc->ddict,
-                                       rpmfcFileDep(t, fc->ix, ds));
+                           rpmfcAddFileDep(&fc->ddict, fc->ix, ds);
                            ds = rpmdsFree(ds);
+                           free(buf);
                        }
                        auxoffset += aux->vna_next;
                    }
@@ -1009,25 +1008,22 @@ assert(s != NULL);
                    if (s == NULL)
                        continue;
 
-                   buf[0] = '\0';
-                   t = buf;
-                   t = stpcpy(t, s);
-
+                   rasprintf(&buf, "%s%s", s,
 #if !defined(__alpha__)
-                   if (isElf64)
-                       t = stpcpy(t, "()(64bit)");
+                                           isElf64 ? "()(64bit)" : "");
+#else
+                                           "");
 #endif
-                   t++;
 
                    /* Add to package dependencies. */
                    ds = rpmdsSingle(tagN, buf, "", dsContext);
                    xx = rpmdsMerge(depsp, ds);
 
                    /* Add to file dependencies. */
-                   xx = rpmfcSaveArg(&fc->ddict,
-                                       rpmfcFileDep(t, fc->ix, ds));
+                   rpmfcAddFileDep(&fc->ddict, fc->ix, ds);
 
                    ds = rpmdsFree(ds);
+                   free(buf);
                }
            }
            break;
@@ -1040,9 +1036,7 @@ assert(s != NULL);
         ds = rpmdsSingle(RPMTAG_REQUIRENAME, "rtld(GNU_HASH)", "", 
                          RPMSENSE_FIND_REQUIRES);
         rpmdsMerge(&fc->requires, ds);
-        buf[0] = '\0';
-        t = buf;
-        rpmfcSaveArg(&fc->ddict, rpmfcFileDep(t, fc->ix, ds));
+        rpmfcAddFileDep(&fc->ddict, fc->ix, ds);
         ds = rpmdsFree(ds);
     }
 
@@ -1058,25 +1052,22 @@ assert(s != NULL);
        else
            s = fn;
 
-       buf[0] = '\0';
-       t = buf;
-/* LCL: s is not null. */
-       t = stpcpy(t, s);
-
+       rasprintf(&buf, "%s%s", s,
 #if !defined(__alpha__)
-       if (isElf64)
-           t = stpcpy(t, "()(64bit)");
+                               isElf64 ? "()(64bit)" : "");
+#else
+                               "");
 #endif
-       t++;
 
        /* Add to package dependencies. */
        ds = rpmdsSingle(tagN, buf, "", dsContext);
        xx = rpmdsMerge(depsp, ds);
 
        /* Add to file dependencies. */
-       xx = rpmfcSaveArg(&fc->ddict, rpmfcFileDep(t, fc->ix, ds));
+       rpmfcAddFileDep(&fc->ddict, fc->ix, ds);
 
        ds = rpmdsFree(ds);
+       free(buf);
     }
 
 exit:
@@ -1089,24 +1080,48 @@ exit:
 #endif
 }
 
-typedef struct rpmfcApplyTbl_s {
+static int rpmfcMISC(rpmfc fc)
+{
+    struct stat st;
+    int rc = -1;
+    const char *what = NULL;
+    const char * fn = fc->fn[fc->ix];
+    /* this part is enumerated, compare equality not bit flags */
+    int ftype = fc->fcolor->vals[fc->ix] & 0x000F0000;
+
+    if (ftype == RPMFC_FONT) {
+       what = "fontconfig";
+    } else if (ftype == RPMFC_TEXT && rpmFileHasSuffix(fn, ".desktop")) {
+       what = "desktop";
+    }
+
+    if (what == NULL || stat(fn, &st) < 0 || !S_ISREG(st.st_mode)) {
+       goto exit;
+    }
+
+    (void) rpmfcHelper(fc, 'P', what);
+    rc = 0;
+
+exit:
+    return rc;
+}
+typedef const struct rpmfcApplyTbl_s {
     int (*func) (rpmfc fc);
     int colormask;
 } * rpmfcApplyTbl;
 
 /**
  */
-static struct rpmfcApplyTbl_s rpmfcApplyTable[] = {
+static const struct rpmfcApplyTbl_s const rpmfcApplyTable[] = {
     { rpmfcELF,                RPMFC_ELF },
-    { rpmfcSCRIPT,     (RPMFC_SCRIPT|RPMFC_PERL) },
-    { rpmfcSCRIPT,     (RPMFC_SCRIPT|RPMFC_PYTHON) },
-    { rpmfcSCRIPT,     (RPMFC_SCRIPT|RPMFC_PKGCONFIG) },
-    { rpmfcSCRIPT,     (RPMFC_SCRIPT|RPMFC_LIBTOOL) },
-    { rpmfcSCRIPT,      RPMFC_MONO },
+    { rpmfcSCRIPT,     (RPMFC_SCRIPT|RPMFC_BOURNE|
+                        RPMFC_PERL|RPMFC_PYTHON|RPMFC_MONO|
+                        RPMFC_PKGCONFIG|RPMFC_LIBTOOL) },
+    { rpmfcMISC,       RPMFC_FONT|RPMFC_TEXT },
     { NULL, 0 }
 };
 
-int rpmfcApply(rpmfc fc)
+rpmRC rpmfcApply(rpmfc fc)
 {
     rpmfcApplyTbl fcat;
     const char * s;
@@ -1114,7 +1129,7 @@ int rpmfcApply(rpmfc fc)
     rpmds ds;
     const char * N;
     const char * EVR;
-    int_32 Flags;
+    rpmsenseFlags Flags;
     unsigned char deptype;
     int nddict;
     int previx;
@@ -1134,7 +1149,7 @@ int rpmfcApply(rpmfc fc)
                fn += sizeof("/usr/lib")-1;
                if (fn[0] == '6' && fn[1] == '4')
                    fn += 2;
-               if (!strncmp(fn, "/python", sizeof("/python")-1))
+               if (rstreqn(fn, "/python", sizeof("/python")-1))
                    fc->fcolor->vals[fc->ix] |= RPMFC_PYTHON;
            }
        }
@@ -1155,7 +1170,11 @@ int rpmfcApply(rpmfc fc)
 
        /* Parse out (file#,deptype,N,EVR,Flags) */
        ix = strtol(s, &se, 10);
-assert(se != NULL);
+       if ( se == NULL ) {
+               rpmlog(RPMLOG_ERR, _("Conversion of %s to long integer failed.\n"), s);
+               return RPMRC_FAIL;
+       }
+       
        deptype = *se++;
        se++;
        N = se;
@@ -1203,10 +1222,10 @@ assert(dix >= 0);
            fc->fddictn->vals[ix]++;
     }
 
-    return 0;
+    return RPMRC_OK;
 }
 
-int rpmfcClassify(rpmfc fc, ARGV_t argv, int_16 * fmode)
+rpmRC rpmfcClassify(rpmfc fc, ARGV_t argv, rpm_mode_t * fmode)
 {
     ARGV_t fcav = NULL;
     ARGV_t dav;
@@ -1214,7 +1233,7 @@ int rpmfcClassify(rpmfc fc, ARGV_t argv, int_16 * fmode)
     size_t slen;
     int fcolor;
     int xx;
-    int msflags = MAGIC_CHECK; /* XXX MAGIC_COMPRESS flag? */
+    int msflags = MAGIC_CHECK | MAGIC_COMPRESS | MAGIC_NO_CHECK_TOKENS;
     magic_t ms = NULL;
 
     if (fc == NULL || argv == NULL)
@@ -1232,25 +1251,23 @@ int rpmfcClassify(rpmfc fc, ARGV_t argv, int_16 * fmode)
 
     ms = magic_open(msflags);
     if (ms == NULL) {
-       xx = RPMERR_EXEC;
-       rpmlog(xx, _("magic_open(0x%x) failed: %s\n"),
+       rpmlog(RPMLOG_ERR, _("magic_open(0x%x) failed: %s\n"),
                msflags, strerror(errno));
-assert(ms != NULL);    /* XXX figger a proper return path. */
+       return RPMRC_FAIL;
     }
 
     xx = magic_load(ms, NULL);
     if (xx == -1) {
-       xx = RPMERR_EXEC;
-       rpmlog(xx, _("magic_load failed: %s\n"), magic_error(ms));
-assert(xx != -1);      /* XXX figger a proper return path. */
+       rpmlog(RPMLOG_ERR, _("magic_load failed: %s\n"), magic_error(ms));
+       magic_close(ms);
+       return RPMRC_FAIL;
     }
 
     for (fc->ix = 0; fc->ix < fc->nfiles; fc->ix++) {
        const char * ftype;
-       int_16 mode = (fmode ? fmode[fc->ix] : 0);
+       rpm_mode_t mode = (fmode ? fmode[fc->ix] : 0);
 
        s = argv[fc->ix];
-assert(s != NULL);
        slen = strlen(s);
 
        switch (mode & S_IFMT) {
@@ -1262,32 +1279,30 @@ assert(s != NULL);
        case S_IFLNK:
        case S_IFREG:
        default:
-#define _suffix(_s, _x) \
-    (slen >= sizeof(_x) && !strcmp((_s)+slen-(sizeof(_x)-1), (_x)))
-
            /* XXX all files with extension ".pm" are perl modules for now. */
-           if (_suffix(s, ".pm"))
+           if (rpmFileHasSuffix(s, ".pm"))
                ftype = "Perl5 module source text";
 
            /* XXX all files with extension ".la" are libtool for now. */
-           else if (_suffix(s, ".la"))
+           else if (rpmFileHasSuffix(s, ".la"))
                ftype = "libtool library file";
 
            /* XXX all files with extension ".pc" are pkgconfig for now. */
-           else if (_suffix(s, ".pc"))
+           else if (rpmFileHasSuffix(s, ".pc"))
                ftype = "pkgconfig file";
 
            /* XXX skip all files in /dev/ which are (or should be) %dev dummies. */
-           else if (slen >= fc->brlen+sizeof("/dev/") && !strncmp(s+fc->brlen, "/dev/", sizeof("/dev/")-1))
+           else if (slen >= fc->brlen+sizeof("/dev/") && rstreqn(s+fc->brlen, "/dev/", sizeof("/dev/")-1))
                ftype = "";
            else
                ftype = magic_file(ms, s);
 
            if (ftype == NULL) {
-               xx = RPMERR_EXEC;
-               rpmlog(xx, _("magic_file(ms, \"%s\") failed: mode %06o %s\n"),
-                       s, mode, magic_error(ms));
-assert(ftype != NULL); /* XXX figger a proper return path. */
+               rpmlog(RPMLOG_ERR, 
+                      _("Recognition of file \"%s\" failed: mode %06o %s\n"),
+                      s, mode, magic_error(ms));
+               magic_close(ms);
+               return RPMRC_FAIL;
            }
        }
 
@@ -1312,7 +1327,6 @@ assert(ftype != NULL);    /* XXX figger a proper return path. */
     fc->fknown = 0;
     for (fc->ix = 0; fc->ix < fc->nfiles; fc->ix++) {
        se = fcav[fc->ix];
-assert(se != NULL);
 
        dav = argvSearch(fc->cdict, se, NULL);
        if (dav) {
@@ -1329,7 +1343,7 @@ assert(se != NULL);
     if (ms != NULL)
        magic_close(ms);
 
-    return 0;
+    return RPMRC_OK;
 }
 
 /**
@@ -1340,7 +1354,7 @@ typedef struct DepMsg_s * DepMsg_t;
  */
 struct DepMsg_s {
     const char * msg;
-    const char * argv[4];
+    char * const argv[4];
     rpmTag ntag;
     rpmTag vtag;
     rpmTag ftag;
@@ -1354,39 +1368,30 @@ 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
+       RPMSENSE_INTERP, 0 },
   { "Requires(rpmlib)",        { NULL, "rpmlib", NULL, NULL },
        -1, -1, RPMTAG_REQUIREFLAGS,
-       _notpre(RPMSENSE_RPMLIB), 0 },
+       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 },
+       RPMSENSE_SCRIPT_PRE, 0 },
   { "Requires(post)",  { NULL, "post", NULL, NULL },
        -1, -1, RPMTAG_REQUIREFLAGS,
-       _notpre(RPMSENSE_SCRIPT_POST), 0 },
+       RPMSENSE_SCRIPT_POST, 0 },
   { "Requires(preun)", { NULL, "preun", NULL, NULL },
        -1, -1, RPMTAG_REQUIREFLAGS,
-       _notpre(RPMSENSE_SCRIPT_PREUN), 0 },
+       RPMSENSE_SCRIPT_PREUN, 0 },
   { "Requires(postun)",        { NULL, "postun", NULL, NULL },
        -1, -1, RPMTAG_REQUIREFLAGS,
-       _notpre(RPMSENSE_SCRIPT_POSTUN), 0 },
+       RPMSENSE_SCRIPT_POSTUN, 0 },
   { "Requires",                { "%{?__find_requires}", NULL, NULL, NULL },
        -1, -1, RPMTAG_REQUIREFLAGS,    /* XXX inherit name/version arrays */
-       RPMSENSE_PREREQ, RPMSENSE_PREREQ },
+       RPMSENSE_FIND_REQUIRES|RPMSENSE_TRIGGERIN|RPMSENSE_TRIGGERUN|RPMSENSE_TRIGGERPOSTUN|RPMSENSE_TRIGGERPREIN, 0 },
   { "Conflicts",       { "%{?__find_conflicts}", NULL, NULL, NULL },
        RPMTAG_CONFLICTNAME, RPMTAG_CONFLICTVERSION, RPMTAG_CONFLICTFLAGS,
        0, -1 },
@@ -1404,15 +1409,14 @@ static void printDeps(Header h)
 {
     DepMsg_t dm;
     rpmds ds = NULL;
-    int flags = 0;     /* XXX !scareMem */
     const char * DNEVR;
-    int_32 Flags;
+    rpmsenseFlags Flags;
     int bingo = 0;
 
     for (dm = DepMsgs; dm->msg != NULL; dm++) {
        if (dm->ntag != -1) {
            ds = rpmdsFree(ds);
-           ds = rpmdsNew(h, dm->ntag, flags);
+           ds = rpmdsNew(h, dm->ntag, 0);
        }
        if (dm->ftag == 0)
            continue;
@@ -1450,7 +1454,7 @@ static int rpmfcGenerateDependsHelper(const rpmSpec spec, Package pkg, rpmfi fi)
     StringBuf sb_stdout;
     DepMsg_t dm;
     int failnonzero = 0;
-    int rc = 0;
+    int rc = RPMRC_OK;
 
     /*
      * Create file manifest buffer to deliver to dependency finder.
@@ -1462,13 +1466,9 @@ static int rpmfcGenerateDependsHelper(const rpmSpec spec, Package pkg, rpmfi fi)
        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;
+       rpmTag tag = (dm->ftag > 0) ? dm->ftag : dm->ntag;
+       rpmsenseFlags tagflags;
+       char * s = NULL;
 
        switch(tag) {
        case RPMTAG_PROVIDEFLAGS:
@@ -1488,18 +1488,16 @@ static int rpmfcGenerateDependsHelper(const rpmSpec spec, Package pkg, rpmfi fi)
            break;
        }
 
-       xx = rpmfcExec(dm->argv, sb_stdin, &sb_stdout, failnonzero);
-       if (xx == -1)
+       if (rpmfcExec(dm->argv, sb_stdin, &sb_stdout, failnonzero) == -1)
            continue;
 
        s = rpmExpand(dm->argv[0], NULL);
-       rpmlog(RPMLOG_NOTICE, _("Finding  %s: %s\n"), dm->msg,
-               (s ? s : ""));
-       s = _free(s);
+       rpmlog(RPMLOG_NOTICE, _("Finding  %s: %s\n"), dm->msg, (s ? s : ""));
+       free(s);
 
        if (sb_stdout == NULL) {
-           rc = RPMERR_EXEC;
-           rpmlog(rc, _("Failed to find %s:\n"), dm->msg);
+           rc = RPMRC_FAIL;
+           rpmlog(RPMLOG_ERR, _("Failed to find %s:\n"), dm->msg);
            break;
        }
 
@@ -1508,7 +1506,7 @@ static int rpmfcGenerateDependsHelper(const rpmSpec spec, Package pkg, rpmfi fi)
        sb_stdout = freeStringBuf(sb_stdout);
 
        if (rc) {
-           rpmlog(rc, _("Failed to find %s:\n"), dm->msg);
+           rpmlog(RPMLOG_ERR, _("Failed to find %s:\n"), dm->msg);
            break;
        }
     }
@@ -1518,23 +1516,22 @@ static int rpmfcGenerateDependsHelper(const rpmSpec spec, Package pkg, rpmfi fi)
     return rc;
 }
 
-int rpmfcGenerateDepends(const rpmSpec spec, Package pkg)
+rpmRC rpmfcGenerateDepends(const rpmSpec spec, Package pkg)
 {
     rpmfi fi = pkg->cpioList;
     rpmfc fc = NULL;
     rpmds ds;
-    int flags = 0;     /* XXX !scareMem */
     ARGV_t av;
-    int_16 * fmode;
+    rpm_mode_t * fmode;
     int ac = rpmfiFC(fi);
-    const void ** p;
-    char buf[BUFSIZ];
+    char *buf = NULL;
     const char * N;
     const char * EVR;
     int genConfigDeps;
-    int c;
-    int rc = 0;
+    int rc = RPMRC_OK;
     int xx;
+    int idx;
+    struct rpmtd_s td;
 
     /* Skip packages with no files. */
     if (ac <= 0)
@@ -1559,15 +1556,15 @@ int rpmfcGenerateDepends(const rpmSpec spec, Package pkg)
     genConfigDeps = 0;
     fi = rpmfiInit(fi, 0);
     if (fi != NULL)
-    while ((c = rpmfiNext(fi)) >= 0) {
+    while ((idx = rpmfiNext(fi)) >= 0) {
        rpmfileAttrs fileAttrs;
 
        /* Does package have any %config files? */
        fileAttrs = rpmfiFFlags(fi);
        genConfigDeps |= (fileAttrs & RPMFILE_CONFIG);
 
-       av[c] = xstrdup(rpmfiFN(fi));
-       fmode[c] = rpmfiFMode(fi);
+       av[idx] = xstrdup(rpmfiFN(fi));
+       fmode[idx] = rpmfiFMode(fi);
     }
     av[ac] = NULL;
 
@@ -1575,151 +1572,167 @@ int rpmfcGenerateDepends(const rpmSpec spec, Package pkg)
     fc->skipProv = !pkg->autoProv;
     fc->skipReq = !pkg->autoReq;
     fc->tracked = 0;
-    fc->brlen = (spec->buildRootURL ? strlen(spec->buildRootURL) : 0);
+    fc->brlen = (spec->buildRoot ? strlen(spec->buildRoot) : 0);
 
     /* Copy (and delete) manually generated dependencies to dictionary. */
     if (!fc->skipProv) {
-       ds = rpmdsNew(pkg->header, RPMTAG_PROVIDENAME, flags);
+       ds = rpmdsNew(pkg->header, RPMTAG_PROVIDENAME, 0);
        xx = rpmdsMerge(&fc->provides, ds);
        ds = rpmdsFree(ds);
-       xx = headerRemoveEntry(pkg->header, RPMTAG_PROVIDENAME);
-       xx = headerRemoveEntry(pkg->header, RPMTAG_PROVIDEVERSION);
-       xx = headerRemoveEntry(pkg->header, RPMTAG_PROVIDEFLAGS);
+       xx = headerDel(pkg->header, RPMTAG_PROVIDENAME);
+       xx = headerDel(pkg->header, RPMTAG_PROVIDEVERSION);
+       xx = headerDel(pkg->header, RPMTAG_PROVIDEFLAGS);
 
        /* Add config dependency, Provides: config(N) = EVR */
        if (genConfigDeps) {
            N = rpmdsN(pkg->ds);
-assert(N != NULL);
+           if (N == NULL) {
+               rc = RPMRC_FAIL;
+               rpmlog(RPMLOG_ERR, _("Unable to get current dependency name.\n"));
+               goto exit;
+           }
            EVR = rpmdsEVR(pkg->ds);
-assert(EVR != NULL);
-           sprintf(buf, "config(%s)", N);
+           if (EVR == NULL) {
+               rc = RPMRC_FAIL;
+               rpmlog(RPMLOG_ERR, _("Unable to get current dependency epoch-version-release.\n"));
+               goto exit;
+           }
+           rasprintf(&buf, "config(%s)", N);
            ds = rpmdsSingle(RPMTAG_PROVIDENAME, buf, EVR,
                        (RPMSENSE_EQUAL|RPMSENSE_CONFIG));
+           free(buf);
            xx = rpmdsMerge(&fc->provides, ds);
            ds = rpmdsFree(ds);
        }
     }
 
     if (!fc->skipReq) {
-       ds = rpmdsNew(pkg->header, RPMTAG_REQUIRENAME, flags);
+       ds = rpmdsNew(pkg->header, RPMTAG_REQUIRENAME, 0);
        xx = rpmdsMerge(&fc->requires, ds);
        ds = rpmdsFree(ds);
-       xx = headerRemoveEntry(pkg->header, RPMTAG_REQUIRENAME);
-       xx = headerRemoveEntry(pkg->header, RPMTAG_REQUIREVERSION);
-       xx = headerRemoveEntry(pkg->header, RPMTAG_REQUIREFLAGS);
+       xx = headerDel(pkg->header, RPMTAG_REQUIRENAME);
+       xx = headerDel(pkg->header, RPMTAG_REQUIREVERSION);
+       xx = headerDel(pkg->header, RPMTAG_REQUIREFLAGS);
 
        /* Add config dependency,  Requires: config(N) = EVR */
        if (genConfigDeps) {
            N = rpmdsN(pkg->ds);
-assert(N != NULL);
+           if (N == NULL) {
+               rc = RPMRC_FAIL;
+               rpmlog(RPMLOG_ERR, _("Unable to get current dependency name.\n"));
+               goto exit;
+           }
            EVR = rpmdsEVR(pkg->ds);
-assert(EVR != NULL);
-           sprintf(buf, "config(%s)", N);
+           if (EVR == NULL) {
+               rc = RPMRC_FAIL;
+               rpmlog(RPMLOG_ERR, _("Unable to get current dependency epoch-version-release.\n"));
+               goto exit;
+           }
+           rasprintf(&buf, "config(%s)", N);
            ds = rpmdsSingle(RPMTAG_REQUIRENAME, buf, EVR,
                        (RPMSENSE_EQUAL|RPMSENSE_CONFIG));
+           free(buf);
            xx = rpmdsMerge(&fc->requires, ds);
            ds = rpmdsFree(ds);
        }
     }
 
     /* Build file class dictionary. */
-    xx = rpmfcClassify(fc, av, fmode);
+    rc = rpmfcClassify(fc, av, fmode);
+    if ( rc != RPMRC_OK )
+       goto exit;
 
     /* Build file/package dependency dictionary. */
-    xx = rpmfcApply(fc);
+    rc = rpmfcApply(fc);
+    if ( rc != RPMRC_OK )
+       goto exit;
 
     /* Add per-file colors(#files) */
-    p = (const void **) argiData(fc->fcolor);
-    c = argiCount(fc->fcolor);
-assert(ac == c);
-    if (p != NULL && c > 0) {
-       int_32 * fcolors = (int_32 *)p;
-       int i;
-
+    if (rpmtdFromArgi(&td, RPMTAG_FILECOLORS, fc->fcolor)) {
+       rpm_color_t *fcolor;
+       if (ac != rpmtdCount(&td)) {
+           rc = RPMRC_FAIL;
+           rpmlog(RPMLOG_ERR, _("File count from file info doesn't match file in container.\n"));
+           goto exit;
+       }
+       assert(rpmtdType(&td) == RPM_INT32_TYPE);
        /* XXX Make sure only primary (i.e. Elf32/Elf64) colors are added. */
-       for (i = 0; i < c; i++)
-           fcolors[i] &= 0x0f;
-       xx = headerAddEntry(pkg->header, RPMTAG_FILECOLORS, RPM_INT32_TYPE,
-                       p, c);
+       while ((fcolor = rpmtdNextUint32(&td))) {
+           *fcolor &= 0x0f;
+       }
+       headerPut(pkg->header, &td, HEADERPUT_DEFAULT);
     }
 
     /* Add classes(#classes) */
-    p = (const void **) argvData(fc->cdict);
-    c = argvCount(fc->cdict);
-    if (p != NULL && c > 0)
-       xx = headerAddEntry(pkg->header, RPMTAG_CLASSDICT, RPM_STRING_ARRAY_TYPE,
-                       p, c);
+    if (rpmtdFromArgv(&td, RPMTAG_CLASSDICT, fc->cdict)) {
+       if (rpmtdType(&td) != RPM_STRING_ARRAY_TYPE) {
+           rc = RPMRC_FAIL;
+           rpmlog(RPMLOG_ERR, _("Container not of string array data type.\n"));
+           goto exit;
+       }
+       headerPut(pkg->header, &td, HEADERPUT_DEFAULT);
+    }
 
     /* Add per-file classes(#files) */
-    p = (const void **) argiData(fc->fcdictx);
-    c = argiCount(fc->fcdictx);
-assert(ac == c);
-    if (p != NULL && c > 0)
-       xx = headerAddEntry(pkg->header, RPMTAG_FILECLASS, RPM_INT32_TYPE,
-                       p, c);
+    if (rpmtdFromArgi(&td, RPMTAG_FILECLASS, fc->fcdictx)) {
+       assert(rpmtdType(&td) == RPM_INT32_TYPE);
+       headerPut(pkg->header, &td, HEADERPUT_DEFAULT);
+    }
 
     /* Add Provides: */
-    if (fc->provides != NULL && (c = rpmdsCount(fc->provides)) > 0 && !fc->skipProv) {
-       p = (const void **) fc->provides->N;
-       xx = headerAddEntry(pkg->header, RPMTAG_PROVIDENAME, RPM_STRING_ARRAY_TYPE,
-                       p, c);
-       /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
-       p = (const void **) fc->provides->EVR;
-assert(p != NULL);
-       xx = headerAddEntry(pkg->header, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE,
-                       p, c);
-       p = (const void **) fc->provides->Flags;
-assert(p != NULL);
-       xx = headerAddEntry(pkg->header, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE,
-                       p, c);
+    if (fc->provides != NULL && rpmdsCount(fc->provides) > 0 && !fc->skipProv) {
+       rpmds pi = rpmdsInit(fc->provides);
+       while (rpmdsNext(pi) >= 0) {
+           const char *name = rpmdsN(pi);
+           const char *evr = rpmdsEVR(pi);
+           rpmsenseFlags flags = rpmdsFlags(pi);
+       
+           headerPutString(pkg->header, RPMTAG_PROVIDENAME, name);
+           headerPutString(pkg->header, RPMTAG_PROVIDEVERSION, evr);
+           headerPutUint32(pkg->header, RPMTAG_PROVIDEFLAGS, &flags, 1);
+       }
     }
 
     /* Add Requires: */
-    if (fc->requires != NULL && (c = rpmdsCount(fc->requires)) > 0 && !fc->skipReq) {
-       p = (const void **) fc->requires->N;
-       xx = headerAddEntry(pkg->header, RPMTAG_REQUIRENAME, RPM_STRING_ARRAY_TYPE,
-                       p, c);
-       /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
-       p = (const void **) fc->requires->EVR;
-assert(p != NULL);
-       xx = headerAddEntry(pkg->header, RPMTAG_REQUIREVERSION, RPM_STRING_ARRAY_TYPE,
-                       p, c);
-       p = (const void **) fc->requires->Flags;
-assert(p != NULL);
-       xx = headerAddEntry(pkg->header, RPMTAG_REQUIREFLAGS, RPM_INT32_TYPE,
-                       p, c);
+    if (fc->requires != NULL && rpmdsCount(fc->requires) > 0 && !fc->skipReq) {
+       rpmds pi = rpmdsInit(fc->requires);
+       while (rpmdsNext(pi) >= 0) {
+           const char *name = rpmdsN(pi);
+           const char *evr = rpmdsEVR(pi);
+           rpmsenseFlags flags = rpmdsFlags(pi);
+       
+           headerPutString(pkg->header, RPMTAG_REQUIRENAME, name);
+           headerPutString(pkg->header, RPMTAG_REQUIREVERSION, evr);
+           headerPutUint32(pkg->header, RPMTAG_REQUIREFLAGS, &flags, 1);
+       }
     }
 
     /* Add dependency dictionary(#dependencies) */
-    p = (const void **) argiData(fc->ddictx);
-    c = argiCount(fc->ddictx);
-    if (p != NULL)
-       xx = headerAddEntry(pkg->header, RPMTAG_DEPENDSDICT, RPM_INT32_TYPE,
-                       p, c);
+    if (rpmtdFromArgi(&td, RPMTAG_DEPENDSDICT, fc->ddictx)) {
+       assert(rpmtdType(&td) == RPM_INT32_TYPE);
+       headerPut(pkg->header, &td, HEADERPUT_DEFAULT);
+    }
 
     /* 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);
+    if (rpmtdFromArgi(&td, RPMTAG_FILEDEPENDSX, fc->fddictx)) {
+       assert(rpmtdType(&td) == RPM_INT32_TYPE);
+       headerPut(pkg->header, &td, HEADERPUT_DEFAULT);
+    }
+
+    if (rpmtdFromArgi(&td, RPMTAG_FILEDEPENDSN, fc->fddictn)) {
+       assert(rpmtdType(&td) == RPM_INT32_TYPE);
+       headerPut(pkg->header, &td, HEADERPUT_DEFAULT);
+    }
 
     printDeps(pkg->header);
 
 if (fc != NULL && _rpmfc_debug) {
-char msg[BUFSIZ];
-sprintf(msg, "final: files %d cdict[%d] %d%% ddictx[%d]", fc->nfiles, argvCount(fc->cdict), ((100 * fc->fknown)/fc->nfiles), argiCount(fc->ddictx));
+char *msg = NULL;
+rasprintf(&msg, "final: files %d cdict[%d] %d%% ddictx[%d]", fc->nfiles, argvCount(fc->cdict), ((100 * fc->fknown)/fc->nfiles), argiCount(fc->ddictx));
 rpmfcPrint(msg, fc, NULL);
+free(msg);
 }
-
+exit:
     /* Clean up. */
     fmode = _free(fmode);
     fc = rpmfcFree(fc);