summaryrefslogtreecommitdiff
path: root/build
diff options
context:
space:
mode:
authorjbj <devnull@localhost>2002-10-19 22:48:25 +0000
committerjbj <devnull@localhost>2002-10-19 22:48:25 +0000
commite9e68be03a2965f0379e4eef1d60ff70eb2ef4a6 (patch)
tree390bfdb472f2b1c0b00791827e6d4db6b79905ad /build
parent4a77efce46d82f91c0539c3c012381ff20d0d2f5 (diff)
downloadrpm-e9e68be03a2965f0379e4eef1d60ff70eb2ef4a6.tar.gz
rpm-e9e68be03a2965f0379e4eef1d60ff70eb2ef4a6.tar.bz2
rpm-e9e68be03a2965f0379e4eef1d60ff70eb2ef4a6.zip
Functional ELF/SCRIPT dependency generation.
CVS patchset: 5790 CVS date: 2002/10/19 22:48:25
Diffstat (limited to 'build')
-rw-r--r--build/argv.c20
-rw-r--r--build/argv.h11
-rw-r--r--build/rpmfc.c527
-rw-r--r--build/rpmfc.h40
-rw-r--r--build/tfr.c169
5 files changed, 550 insertions, 217 deletions
diff --git a/build/argv.c b/build/argv.c
index 01af214ab..2f92fe0cd 100644
--- a/build/argv.c
+++ b/build/argv.c
@@ -21,15 +21,15 @@ void * _free(/*@only@*/ /*@null@*/ /*@out@*/ const void * p)
void argvPrint(const char * msg, ARGV_t argv, FILE * fp)
{
ARGV_t av;
- int ac;
if (fp == NULL) fp = stderr;
if (msg)
fprintf(fp, "===================================== %s\n", msg);
- for (ac = 0, av = argv; *av; av++, ac++)
- fprintf(fp, "%5d: %s\n", ac, *av);
+ if (argv)
+ for (av = argv; *av; av++)
+ fprintf(fp, "%s\n", *av);
}
@@ -56,7 +56,15 @@ ARGV_t argvFree(/*@only@*/ /*@null@*/ ARGV_t argv)
return NULL;
}
-int argvCount(/*@null@*/ const ARGV_t argv)
+int argiCount(ARGI_t argi)
+{
+ int nvals = 0;
+ if (argi)
+ nvals = argi->nvals;
+ return nvals;
+}
+
+int argvCount(const ARGV_t argv)
{
int argc = 0;
if (argv)
@@ -92,7 +100,7 @@ ARGV_t argvSearch(ARGV_t argv, ARGstr_t val,
return bsearch(&val, argv, argvCount(argv), sizeof(*argv), compar);
}
-int argiAdd(/*@out@*/ ARGI_t * argip, unsigned ix, int val)
+int argiAdd(/*@out@*/ ARGI_t * argip, int ix, int val)
{
ARGI_t argi;
@@ -101,6 +109,8 @@ int argiAdd(/*@out@*/ ARGI_t * argip, unsigned ix, int val)
if (*argip == NULL)
*argip = xcalloc(1, sizeof(**argip));
argi = *argip;
+ if (ix < 0)
+ ix = argi->nvals;
if (ix >= argi->nvals) {
argi->vals = xrealloc(argi->vals, (ix + 1) * sizeof(*argi->vals));
memset(argi->vals + argi->nvals, 0,
diff --git a/build/argv.h b/build/argv.h
index 607be34fc..f54f0ab61 100644
--- a/build/argv.h
+++ b/build/argv.h
@@ -48,6 +48,13 @@ ARGV_t argvFree(/*@only@*/ /*@null@*/ ARGV_t argv)
/*@modifies argv @*/;
/**
+ * Return no. of elements in argi array.
+ * @param argi argi array
+ */
+int argiCount(/*@null@*/ const ARGI_t argi)
+ /*@*/;
+
+/**
* Return no. of elements in argv array.
* @param argv argv array
*/
@@ -82,11 +89,11 @@ ARGV_t argvSearch(ARGV_t argv, ARGstr_t val,
/**
* Add an int to an argi array.
* @retval *argip argi array
- * @parm ix argi array index
+ * @parm ix argi array index (or -1 to append)
* @param val int arg to add
* @return 0 always
*/
-int argiAdd(/*@out@*/ ARGI_t * argip, unsigned ix, int val)
+int argiAdd(/*@out@*/ ARGI_t * argip, int ix, int val)
/*@modifies *argip @*/;
/**
diff --git a/build/rpmfc.c b/build/rpmfc.c
index c9d02c53a..b70c0a277 100644
--- a/build/rpmfc.c
+++ b/build/rpmfc.c
@@ -5,8 +5,15 @@
#include <argv.h>
#include <rpmfc.h>
+#if HAVE_GELF_H
+#include <gelf.h>
+#endif
+
#include "debug.h"
+/*@notchecked@*/
+int _rpmfc_debug;
+
/**
*/
/*@unchecked@*/ /*@observer@*/
@@ -88,10 +95,6 @@ static struct rpmfcTokens_s rpmfcTokens[] = {
{ NULL, RPMFC_BLACK }
};
-/*@unchecked@*/
-static int fcolorIgnore =
- (RPMFC_ELF32|RPMFC_ELF64|RPMFC_DIRECTORY|RPMFC_LIBRARY|RPMFC_ARCHIVE|RPMFC_FONT|RPMFC_SCRIPT|RPMFC_IMAGE|RPMFC_WHITE);
-
int rpmfcColoring(const char * fmstr)
{
rpmfcToken fct;
@@ -109,36 +112,70 @@ int rpmfcColoring(const char * fmstr)
void rpmfcPrint(const char * msg, rpmfc fc, FILE * fp)
{
- int ac = 0;
int fcolor;
- int ix;
+ int ndx;
+ int cx;
+ int dx;
+ int fx;
+
+int nprovides;
+int nrequires;
if (fp == NULL) fp = stderr;
if (msg)
fprintf(fp, "===================================== %s\n", msg);
+nprovides = argvCount(fc->provides);
+nrequires = argvCount(fc->requires);
+
if (fc)
- while (1) {
- if (fc->fn[ac] == NULL)
- break;
- if (ac >= fc->fdictx->nvals)
- break;
- ix = fc->fdictx->vals[ac];
- if (ix < 0)
- break;
+ for (fx = 0; fx < fc->nfiles; fx++) {
+assert(fx < fc->fcdictx->nvals);
+ cx = fc->fcdictx->vals[fx];
+assert(fx < fc->fcolor->nvals);
+ fcolor = fc->fcolor->vals[fx];
+
+ fprintf(fp, "%3d %s", fx, fc->fn[fx]);
+ if (fcolor != RPMFC_BLACK)
+ fprintf(fp, "\t0x%x", fc->fcolor->vals[fx]);
+ else
+ fprintf(fp, "\t%s", fc->cdict[cx]);
+ fprintf(fp, "\n");
+
+ if (fc->fddictx == NULL || fc->fddictn == NULL)
+ continue;
- fcolor = fc->fcolor->vals[ac];
- if (ix > 0 && !(fcolor & fcolorIgnore)) {
- fprintf(fp, "%3d %s", ix, fc->fn[ac]);
- if (fcolor != RPMFC_BLACK)
- fprintf(fp, "\t0x%x", fc->fcolor->vals[ac]);
- else
- fprintf(fp, "\t%s", fc->dict[ix]);
- fprintf(fp, "\n");
+assert(fx < fc->fddictx->nvals);
+ dx = fc->fddictx->vals[fx];
+assert(fx < fc->fddictn->nvals);
+ ndx = fc->fddictn->vals[fx];
+
+ while (ndx-- > 0) {
+ const char * depval;
+ char deptype;
+ int ix;
+
+ ix = fc->ddictx->vals[dx++];
+ deptype = ((ix >> 24) & 0xff);
+ ix &= 0x00ffffff;
+ depval = NULL;
+ switch (deptype) {
+ default:
+assert(depval);
+ break;
+ case 'P':
+assert(ix < nprovides);
+ depval = fc->provides[ix];
+ break;
+ case 'R':
+assert(ix < nrequires);
+ depval = fc->requires[ix];
+ break;
+ }
+ if (depval)
+ fprintf(fp, "\t%c %s\n", deptype, depval);
}
-
- ac++;
}
}
@@ -146,9 +183,15 @@ rpmfc rpmfcFree(rpmfc fc)
{
if (fc) {
fc->fn = argvFree(fc->fn);
- fc->fdictx = argiFree(fc->fdictx);
+ fc->fcdictx = argiFree(fc->fcdictx);
fc->fcolor = argiFree(fc->fcolor);
- fc->dict = argvFree(fc->dict);
+ fc->cdict = argvFree(fc->cdict);
+ fc->fddictx = argiFree(fc->fddictx);
+ fc->fddictn = argiFree(fc->fddictn);
+ fc->ddict = argvFree(fc->ddict);
+ fc->ddictx = argiFree(fc->ddictx);
+ fc->provides = argvFree(fc->provides);
+ fc->requires = argvFree(fc->requires);
}
fc = _free(fc);
return NULL;
@@ -160,43 +203,338 @@ rpmfc rpmfcNew(void)
return fc;
}
-static int rpmfcELF(rpmfc fc)
+static int rpmfcSCRIPT(rpmfc fc)
{
+ const char * fn = fc->fn[fc->ix];;
+ char deptype;
+ char buf[BUFSIZ];
+ FILE * fp;
+ char * s, * se;
+ size_t ns;
+ char * t;
+ int i;
+ struct stat sb, * st = &sb;;
+ int xx;
+
+ /* Only executable scripts are searched. */
+ if (stat(fn, st) < 0)
+ return -1;
+ if (!(st->st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))
+ return 0;
+
+ fp = fopen(fn, "r");
+ if (fp == NULL || ferror(fp)) {
+ if (fp) fclose(fp);
+ return -1;
+ }
+
+ /* Look for #! interpreter in first 10 lines. */
+ deptype = 'R';
+ for (i = 0; i < 10; i++) {
+
+ s = fgets(buf, sizeof(buf) - 1, fp);
+ if (s == NULL || ferror(fp) || feof(fp))
+ break;
+ s[sizeof(buf)-1] = '\0';
+ ns = strlen(s);
+ if (!(s[0] == '#' && s[1] == '!'))
+ continue;
+ s += 2;
+ while (*s && strchr(" \t\n\r", *s) != NULL)
+ s++;
+ if (*s == '\0')
+ continue;
+ if (*s != '/')
+ continue;
+
+ for (se = s+1; *se; se++) {
+ if (strchr(" \t\n\r", *se) != NULL)
+ break;
+ }
+ *se = '\0';
+
+ /* Add to package requires. */
+ if (argvSearch(fc->requires, s, NULL) == NULL) {
+ xx = argvAdd(&fc->requires, s);
+ xx = argvSort(fc->requires, NULL);
+ }
+
+ /* Add to file dependencies. */
+ if (ns < (sizeof(buf) - ns - 64)) {
+ t = se + 1;
+ *t = '\0';
+ sprintf(t, "%08d%c %s", fc->ix, deptype, s);
+ if (argvSearch(fc->ddict, t, NULL) == NULL) {
+ xx = argvAdd(&fc->ddict, t);
+ xx = argvSort(fc->ddict, NULL);
+ }
+ }
+ break;
+ }
+
+ (void) fclose(fp);
return 0;
}
-static int rpmfcSCRIPT(rpmfc fc)
+#define _permitstr(_a, _b) (!strncmp((_a), (_b), sizeof(_b)-1))
+static int rpmfcELFpermit(const char *s)
+{
+ if (_permitstr(s, "GLIBCPP_")) return 1;
+ if (_permitstr(s, "GLIBC_")) return 1;
+ if (_permitstr(s, "GCC_")) return 1;
+ if (_permitstr(s, "REDHAT_")) return 1;
+ return 0;
+}
+#undef _permitstr
+
+static int rpmfcELF(rpmfc fc)
{
+#if HAVE_GELF_H && HAVE_LIBELF
+ const char * fn = fc->fn[fc->ix];;
+ Elf * elf;
+ Elf_Scn * scn;
+ Elf_Data * data;
+ GElf_Ehdr ehdr_mem, * ehdr;
+ GElf_Shdr shdr_mem, * shdr;
+ GElf_Verdef def_mem, * def;
+ GElf_Verneed need_mem, * need;
+ GElf_Dyn dyn_mem, * dyn;
+ unsigned int auxoffset;
+ unsigned int offset;
+ int fdno;
+ int cnt2;
+ int cnt;
+ char buf[BUFSIZ];
+ const char * s;
+ char deptype;
+ const char * soname = NULL;
+ const char * depval;
+ size_t ns;
+ char * t;
+ int xx;
+
+ fdno = open(fn, O_RDONLY);
+ if (fdno < 0)
+ return fdno;
+
+ (void) elf_version(EV_CURRENT);
+
+ elf = NULL;
+ if ((elf = elf_begin (fdno, ELF_C_READ, NULL)) == NULL
+ || elf_kind(elf) != ELF_K_ELF
+ || (ehdr = gelf_getehdr(elf, &ehdr_mem)) == NULL
+ || !(ehdr->e_type == ET_DYN || ehdr->e_type == ET_EXEC))
+ goto exit;
+
+ /*@-branchstate -uniondef @*/
+ scn = NULL;
+ while ((scn = elf_nextscn(elf, scn)) != NULL) {
+ shdr = gelf_getshdr(scn, &shdr_mem);
+ if (shdr == NULL)
+ break;
+
+ soname = _free(soname);
+ switch (shdr->sh_type) {
+ default:
+ continue;
+ /*@switchbreak@*/ break;
+ case SHT_GNU_verdef:
+ deptype = 'P';
+ data = NULL;
+ while ((data = elf_getdata (scn, data)) != NULL) {
+ offset = 0;
+ for (cnt = shdr->sh_info; --cnt >= 0; ) {
+
+ def = gelf_getverdef (data, offset, &def_mem);
+ if (def == NULL)
+ break;
+ auxoffset = offset + def->vd_aux;
+ for (cnt2 = def->vd_cnt; --cnt2 >= 0; ) {
+ GElf_Verdaux aux_mem, * aux;
+
+ aux = gelf_getverdaux (data, auxoffset, &aux_mem);
+ if (aux == NULL)
+ break;
+
+ s = elf_strptr(elf, shdr->sh_link, aux->vda_name);
+ if (!rpmfcELFpermit(s)) {
+ soname = _free(soname);
+ soname = xstrdup(s);
+ auxoffset += aux->vda_next;
+ continue;
+ }
+ ns = strlen(s);
+
+ t = buf;
+ *t = '\0';
+ sprintf(t, "%08d%c ", fc->ix, deptype);
+ t += strlen(t);
+ depval = t;
+ t = stpcpy( stpcpy( stpcpy( stpcpy(t, soname), "("), s), ")");
+
+ /* Add to package provides. */
+ if (argvSearch(fc->provides, depval, NULL) == NULL) {
+ xx = argvAdd(&fc->provides, depval);
+ xx = argvSort(fc->provides, NULL);
+ }
+
+ /* Add to file dependencies. */
+ if (ns < (sizeof(buf)-64)) {
+ if (argvSearch(fc->ddict, buf, NULL) == NULL) {
+ xx = argvAdd(&fc->ddict, buf);
+ xx = argvSort(fc->ddict, NULL);
+ }
+ }
+
+ auxoffset += aux->vda_next;
+ }
+ offset += def->vd_next;
+ }
+ }
+ /*@switchbreak@*/ break;
+ case SHT_GNU_verneed:
+ deptype = 'R';
+ data = NULL;
+ while ((data = elf_getdata (scn, data)) != NULL) {
+ offset = 0;
+ for (cnt = shdr->sh_info; --cnt >= 0; ) {
+ need = gelf_getverneed (data, offset, &need_mem);
+ if (need == NULL)
+ break;
+
+ s = elf_strptr(elf, shdr->sh_link, need->vn_file);
+ soname = _free(soname);
+ soname = xstrdup(s);
+ auxoffset = offset + need->vn_aux;
+ for (cnt2 = need->vn_cnt; --cnt2 >= 0; ) {
+ GElf_Vernaux aux_mem, * aux;
+
+ aux = gelf_getvernaux (data, auxoffset, &aux_mem);
+ if (aux == NULL)
+ break;
+
+ s = elf_strptr(elf, shdr->sh_link, aux->vna_name);
+ if (!rpmfcELFpermit(s)) {
+ auxoffset += aux->vna_next;
+ continue;
+ }
+ ns = strlen(s);
+
+ if (soname == NULL)
+ soname = xstrdup("libc.so.6");
+
+ t = buf;
+ *t = '\0';
+ sprintf(t, "%08d%c ", fc->ix, deptype);
+ t += strlen(t);
+ depval = t;
+ t = stpcpy( stpcpy( stpcpy( stpcpy(t, soname), "("), s), ")");
+
+ /* Add to package requires. */
+ if (argvSearch(fc->requires, depval, NULL) == NULL) {
+ xx = argvAdd(&fc->requires, depval);
+ xx = argvSort(fc->requires, NULL);
+ }
+
+ /* Add to file dependencies. */
+ if (ns < (sizeof(buf)-64)) {
+ if (argvSearch(fc->ddict, buf, NULL) == NULL) {
+ xx = argvAdd(&fc->ddict, buf);
+ xx = argvSort(fc->ddict, NULL);
+ }
+ }
+
+ auxoffset += aux->vna_next;
+ }
+ offset += need->vn_next;
+ }
+ }
+ /*@switchbreak@*/ break;
+ case SHT_DYNAMIC:
+ data = NULL;
+ while ((data = elf_getdata (scn, data)) != NULL) {
+ for (cnt = 0; cnt < (shdr->sh_size / shdr->sh_entsize); ++cnt) {
+ dyn = gelf_getdyn (data, cnt, &dyn_mem);
+ t = buf;
+ *t = '\0';
+ s = NULL;
+ switch (dyn->d_tag) {
+ default:
+ /*@innercontinue@*/ continue;
+ /*@notreached@*/ break;
+ case DT_NEEDED:
+ /* Add to package requires. */
+ deptype = 'R';
+ s = elf_strptr(elf, shdr->sh_link, dyn->d_un.d_val);
+ if (argvSearch(fc->requires, s, NULL) == NULL) {
+ xx = argvAdd(&fc->requires, s);
+ xx = argvSort(fc->requires, NULL);
+ }
+ /*@switchbreak@*/ break;
+ case DT_SONAME:
+ /* Add to package provides. */
+ deptype = 'P';
+ s = elf_strptr(elf, shdr->sh_link, dyn->d_un.d_val);
+ if (argvSearch(fc->provides, s, NULL) == NULL) {
+ xx = argvAdd(&fc->provides, s);
+ xx = argvSort(fc->provides, NULL);
+ }
+ /*@switchbreak@*/ break;
+ }
+ if (s == NULL)
+ continue;
+ ns = strlen(s);
+ /* Add to file dependencies. */
+ if (ns < (sizeof(buf)-64)) {
+ sprintf(t, "%08d%c ", fc->ix, deptype);
+ t += strlen(t);
+ t = stpcpy(t, s);
+ if (argvSearch(fc->ddict, buf, NULL) == NULL) {
+ xx = argvAdd(&fc->ddict, buf);
+ xx = argvSort(fc->ddict, NULL);
+ }
+ }
+ }
+ }
+ /*@switchbreak@*/ break;
+ }
+ }
+ /*@=branchstate =uniondef @*/
+
+exit:
+ soname = _free(soname);
+ if (elf) (void) elf_end(elf);
+ xx = close(fdno);
return 0;
+#else
+ return -1;
+#endif
}
-int rpmfcClassify(rpmfc *fcp, ARGV_t argv)
+int rpmfcClassify(rpmfc fc, ARGV_t argv)
{
- rpmfc fc;
char buf[BUFSIZ];
ARGV_t dav;
+ ARGV_t av;
const char * s, * se;
char * t;
int fcolor;
int xx;
- int fknown, fwhite;
-
- if (fcp == NULL || argv == NULL)
+ if (fc == NULL || argv == NULL)
return 0;
- if (*fcp == NULL)
- *fcp = rpmfcNew();
- fc = *fcp;
+ fc->nfiles = argvCount(argv);
+
+ xx = argiAdd(&fc->fddictx, fc->nfiles-1, 0);
+ xx = argiAdd(&fc->fddictn, fc->nfiles-1, 0);
/* Set up the file class dictionary. */
- xx = argvAdd(&fc->dict, "");
- xx = argvAdd(&fc->dict, "directory");
+ xx = argvAdd(&fc->cdict, "");
+ xx = argvAdd(&fc->cdict, "directory");
-/*@-temptrans@*/
- fc->av = argv;
-/*@=temptrans@*/
- while ((s = *fc->av++) != NULL) {
+ av = argv;
+ while ((s = *av++) != NULL) {
se = s;
while (*se && !(se[0] == ':' && se[1] == ' '))
se++;
@@ -213,20 +551,18 @@ int rpmfcClassify(rpmfc *fcp, ARGV_t argv)
if (fcolor == RPMFC_WHITE || !(fcolor & RPMFC_INCLUDE))
continue;
- dav = argvSearch(fc->dict, se, NULL);
+ dav = argvSearch(fc->cdict, se, NULL);
if (dav == NULL) {
- xx = argvAdd(&fc->dict, se);
- xx = argvSort(fc->dict, NULL);
+ xx = argvAdd(&fc->cdict, se);
+ xx = argvSort(fc->cdict, NULL);
}
}
/* Classify files. */
-/*@-kepttrans@*/
- fc->av = argv;
-/*@=kepttrans@*/
fc->ix = 0;
- fknown = 0;
- while ((s = *fc->av++) != NULL) {
+ fc->fknown = 0;
+ av = argv;
+ while ((s = *av++) != NULL) {
se = s;
while (*se && !(se[0] == ':' && se[1] == ' '))
se++;
@@ -244,32 +580,103 @@ int rpmfcClassify(rpmfc *fcp, ARGV_t argv)
if (*se == '\0')
return -1;
- dav = argvSearch(fc->dict, se, NULL);
+ dav = argvSearch(fc->cdict, se, NULL);
if (dav) {
- xx = argiAdd(&fc->fdictx, fc->ix, (dav - fc->dict));
- fknown++;
+ xx = argiAdd(&fc->fcdictx, fc->ix, (dav - fc->cdict));
+ fc->fknown++;
} else {
- xx = argiAdd(&fc->fdictx, fc->ix, 0);
- fwhite++;
+ xx = argiAdd(&fc->fcdictx, fc->ix, 0);
+ fc->fwhite++;
}
fcolor = rpmfcColoring(se);
xx = argiAdd(&fc->fcolor, fc->ix, fcolor);
+#ifdef DYING
if (fcolor & RPMFC_ELF) {
xx = rpmfcELF(fc);
} else if (fcolor & RPMFC_SCRIPT) {
xx = rpmfcSCRIPT(fc);
}
+#endif
fc->ix++;
}
- fc->av = NULL;
-/*@-modfilesys@*/
-sprintf(buf, "final: files %d dict[%d] %d%%", argvCount(fc->fn), argvCount(fc->dict), ((100 * fknown)/fc->ix));
-rpmfcPrint(buf, fc, NULL);
-/*@=modfilesys@*/
+ return 0;
+}
+
+typedef struct rpmfcApplyTbl_s {
+ int (*func) (rpmfc fc);
+ int colormask;
+} * rpmfcApplyTbl;
+
+static struct rpmfcApplyTbl_s rpmfcApplyTable[] = {
+ { rpmfcELF, RPMFC_ELF },
+ { rpmfcSCRIPT, RPMFC_SCRIPT },
+ { NULL, 0 }
+};
+
+int rpmfcApply(rpmfc fc)
+{
+ const char * s;
+ char * se;
+ ARGV_t dav, davbase;
+ rpmfcApplyTbl fcat;
+ char deptype;
+ int fcolor;
+ int nddict;
+ int previx;
+ unsigned int val;
+ int ix;
+ int i;
+ int xx;
+
+ /* Generate package and per-file dependencies. */
+ for (fc->ix = 0; fc->fn[fc->ix] != NULL; fc->ix++) {
+ fcolor = fc->fcolor->vals[fc->ix];
+ for (fcat = rpmfcApplyTable; fcat->func != NULL; fcat++) {
+ if (!(fcolor & fcat->colormask))
+ continue;
+ xx = (*fcat->func) (fc);
+ }
+ }
+
+ /* Generate per-file indices into package dependencies. */
+ nddict = argvCount(fc->ddict);
+ previx = -1;
+ for (i = 0; i < nddict; i++) {
+ s = fc->ddict[i];
+ ix = strtol(s, &se, 10);
+assert(se);
+ deptype = *se++;
+ se++;
+
+ davbase = NULL;
+ switch (deptype) {
+ default:
+assert(davbase);
+ break;
+ case 'P':
+ davbase = fc->provides;
+ break;
+ case 'R':
+ davbase = fc->requires;
+ break;
+ }
+
+ dav = argvSearch(davbase, se, NULL);
+assert(dav);
+ val = (deptype << 24) | ((dav - davbase) & 0x00ffffff);
+ xx = argiAdd(&fc->ddictx, -1, val);
+
+ if (previx != ix) {
+ previx = ix;
+ xx = argiAdd(&fc->fddictx, ix, argiCount(fc->ddictx)-1);
+ }
+ if (fc->fddictn && fc->fddictn->vals)
+ fc->fddictn->vals[ix]++;
+ }
return 0;
}
diff --git a/build/rpmfc.h b/build/rpmfc.h
index 3f68cc7dc..dfd4352fa 100644
--- a/build/rpmfc.h
+++ b/build/rpmfc.h
@@ -1,19 +1,28 @@
#ifndef _H_RPMFC_
#define _H_RPMFC_
+/*@notchecked@*/
+extern int _rpmfc_debug;
+
typedef struct rpmfc_s * rpmfc;
struct rpmfc_s {
- ARGV_t av; /*!< file(1) output lines */
- int ac; /*!< no. of lines */
- int ix; /*!< current lineno */
- ARGV_t fn; /*!< file names */
- ARGI_t fcolor; /*!< file colors */
- ARGI_t fdictx; /*!< file class dictionary indices */
- ARGV_t dict; /*!< file class dictionary */
+ int nfiles; /*!< no. of files */
+ int fknown; /*!< no. of classified files */
+ int fwhite; /*!< no. of "white" files */
+ int ix; /*!< current file index */
+ ARGV_t fn; /*!< (#files) file names */
+ ARGI_t fcolor; /*!< (#files) file colors */
+ ARGI_t fcdictx; /*!< (#files) file class dictionary indices */
+ ARGI_t fddictx; /*!< (#files) file depends dictionary start */
+ ARGI_t fddictn; /*!< (#files) file depends dictionary no. entries */
+ ARGV_t cdict; /*!< (#classes) file class dictionary */
+ ARGV_t ddict; /*!< (#dependencies) file depends dictionary */
+ ARGI_t ddictx; /*!< (#dependencies) file->dependency mapping */
+ ARGV_t provides; /*!< (#provides) package provides */
+ ARGV_t requires; /*!< (#requires) package requires */
};
-
enum FCOLOR_e {
RPMFC_BLACK = 0,
RPMFC_ELF32 = (1 << 0),
@@ -38,6 +47,12 @@ enum FCOLOR_e {
RPMFC_IMAGE = (1 << 22),
RPMFC_MANPAGE = (1 << 23),
+ RPMFC_PERL = (1 << 24),
+ RPMFC_JAVA = (1 << 25),
+ RPMFC_PYTHON = (1 << 26),
+ RPMFC_PHP = (1 << 27),
+ RPMFC_TCL = (1 << 28),
+
RPMFC_WHITE = (1 << 29),
RPMFC_INCLUDE = (1 << 30),
RPMFC_ERROR = (1 << 31)
@@ -78,10 +93,17 @@ rpmfc rpmfcNew(void)
/*@*/;
/**
+ * Build file class dictionary and mappings.
*/
-int rpmfcClassify(/*@out@*/ rpmfc *fcp, ARGV_t argv)
+int rpmfcClassify(rpmfc fc, ARGV_t argv)
/*@modifies *fcp @*/;
+/**
+ * BUild file/package dependency dictionary and mappings.
+ */
+int rpmfcApply(rpmfc fc)
+ /*@modifies fc @*/;
+
#ifdef __cplusplus
}
#endif
diff --git a/build/tfr.c b/build/tfr.c
index 0600c383a..1b1172a68 100644
--- a/build/tfr.c
+++ b/build/tfr.c
@@ -4,138 +4,10 @@
#include <argv.h>
#include <rpmfc.h>
-
-#if HAVE_GELF_H
-
-#include <gelf.h>
-
-#endif
-
#include "debug.h"
-static int rpmfcELF(rpmfc fc)
-{
-#if HAVE_GELF_H && HAVE_LIBELF
- const char * fn = fc->fn[fc->ix];;
- Elf * elf;
- Elf_Scn * scn;
- Elf_Data * data;
- GElf_Ehdr ehdr_mem, * ehdr;
- GElf_Shdr shdr_mem, * shdr;
- GElf_Verdef def_mem, * def;
- GElf_Verneed need_mem, * need;
- GElf_Dyn dyn_mem, * dyn;
- unsigned int auxoffset;
- unsigned int offset;
- int fdno;
- int cnt2;
- int cnt;
-
-fprintf(stderr, "*** %s\n", fn);
- fdno = open(fn, O_RDONLY);
- if (fdno < 0)
- return fdno;
-
- (void) elf_version(EV_CURRENT);
-
- elf = NULL;
- if ((elf = elf_begin (fdno, ELF_C_READ, NULL)) == NULL
- || elf_kind(elf) != ELF_K_ELF
- || (ehdr = gelf_getehdr(elf, &ehdr_mem)) == NULL
- || !(ehdr->e_type == ET_DYN || ehdr->e_type == ET_EXEC))
- goto exit;
-
- /*@-branchstate -uniondef @*/
- scn = NULL;
- while ((scn = elf_nextscn(elf, scn)) != NULL) {
- shdr = gelf_getshdr(scn, &shdr_mem);
- if (shdr == NULL)
- break;
-
- switch (shdr->sh_type) {
- default:
- continue;
- /*@switchbreak@*/ break;
- case SHT_GNU_verdef:
-fprintf(stderr, "\tsection %s\n", elf_strptr(elf, ehdr->e_shstrndx, shdr->sh_name));
- data = NULL;
- while ((data = elf_getdata (scn, data)) != NULL) {
- offset = 0;
- for (cnt = shdr->sh_info; --cnt >= 0; ) {
-
- def = gelf_getverdef (data, offset, &def_mem);
- if (def == NULL)
- break;
- auxoffset = offset + def->vd_aux;
- for (cnt2 = def->vd_cnt; --cnt2 >= 0; ) {
- GElf_Verdaux aux_mem, * aux;
-
- aux = gelf_getverdaux (data, auxoffset, &aux_mem);
- if (aux == NULL)
- break;
-fprintf(stderr, "\t\tverdef: %s\n", elf_strptr(elf, shdr->sh_link, aux->vda_name));
-
- auxoffset += aux->vda_next;
- }
- offset += def->vd_next;
- }
- }
- /*@switchbreak@*/ break;
- case SHT_GNU_verneed:
-fprintf(stderr, "\tsection %s\n", elf_strptr(elf, ehdr->e_shstrndx, shdr->sh_name));
- data = NULL;
- while ((data = elf_getdata (scn, data)) != NULL) {
- offset = 0;
- for (cnt = shdr->sh_info; --cnt >= 0; ) {
- need = gelf_getverneed (data, offset, &need_mem);
- if (need == NULL)
- break;
- auxoffset = offset + need->vn_aux;
- for (cnt2 = need->vn_cnt; --cnt2 >= 0; ) {
- GElf_Vernaux aux_mem, * aux;
-
- aux = gelf_getvernaux (data, auxoffset, &aux_mem);
- if (aux == NULL)
- break;
-fprintf(stderr, "\t\tverneed: %s\n", elf_strptr(elf, shdr->sh_link, aux->vna_name));
-
- auxoffset += aux->vna_next;
- }
- offset += need->vn_next;
- }
- }
- /*@switchbreak@*/ break;
- case SHT_DYNAMIC:
-fprintf(stderr, "\tsection %s\n", elf_strptr(elf, ehdr->e_shstrndx, shdr->sh_name));
- data = NULL;
- while ((data = elf_getdata (scn, data)) != NULL) {
- for (cnt = 0; cnt < (shdr->sh_size / shdr->sh_entsize); ++cnt) {
- dyn = gelf_getdyn (data, cnt, &dyn_mem);
- switch (dyn->d_tag) {
- default:
- /*@innercontinue@*/ continue;
- /*@notreached@*/ break;
- case DT_NEEDED:
-fprintf(stderr, "\t\tneeded: %s\n", elf_strptr(elf, shdr->sh_link, dyn->d_un.d_val));
- /*@switchbreak@*/ break;
- case DT_SONAME:
-fprintf(stderr, "\t\tsoname: %s\n", elf_strptr(elf, shdr->sh_link, dyn->d_un.d_val));
- /*@switchbreak@*/ break;
- }
- }
- }
- /*@switchbreak@*/ break;
- }
- }
- /*@=branchstate =uniondef @*/
-
-exit:
- if (elf) (void) elf_end(elf);
- return 0;
-#else
- return -1;
-#endif
-}
+static int print_provides;
+static int print_requires;
static struct poptOption optionsTable[] = {
@@ -143,6 +15,14 @@ static struct poptOption optionsTable[] = {
N_("Common options for all rpm modes and executables:"),
NULL },
+ { "rpmfcdebug", 'd', POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &_rpmfc_debug, -1,
+ NULL, NULL },
+
+ { "provides", 'P', POPT_ARG_VAL, &print_provides, -1,
+ NULL, NULL },
+ { "requires", 'R', POPT_ARG_VAL, &print_requires, -1,
+ NULL, NULL },
+
POPT_AUTOALIAS
POPT_AUTOHELP
POPT_TABLEEND
@@ -162,7 +42,7 @@ main(int argc, char *const argv[])
const char * s;
int ec = 1;
int xx;
-int fcolor;
+char buf[BUFSIZ];
optCon = rpmcliInit(argc, argv, optionsTable);
if (optCon == NULL)
@@ -194,18 +74,25 @@ int fcolor;
xx = argvSplit(&xav, getStringBuf(sb), "\n");
sb = freeStringBuf(sb);
- xx = argvSort(xav, argvCmp);
+ xx = argvSort(xav, NULL);
+
+ /* Build file class dictionary. */
+ fc = rpmfcNew();
+ xx = rpmfcClassify(fc, xav);
+
+ /* Build file/package dependency dictionary. */
+ xx = rpmfcApply(fc);
+
+if (_rpmfc_debug) {
+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);
+}
- fc = NULL;
- xx = rpmfcClassify(&fc, xav);
+ if (print_provides)
+ argvPrint(NULL, fc->provides, stdout);
+ if (print_requires)
+ argvPrint(NULL, fc->requires, stdout);
- for (fc->ix = 0; fc->fn[fc->ix] != NULL; fc->ix++) {
- fcolor = fc->fcolor->vals[fc->ix];
- if (fcolor & RPMFC_ELF) {
- xx = rpmfcELF(fc);
- continue;
- }
- }
fc = rpmfcFree(fc);
xav = argvFree(xav);