diff options
author | jbj <devnull@localhost> | 2002-10-19 22:48:25 +0000 |
---|---|---|
committer | jbj <devnull@localhost> | 2002-10-19 22:48:25 +0000 |
commit | e9e68be03a2965f0379e4eef1d60ff70eb2ef4a6 (patch) | |
tree | 390bfdb472f2b1c0b00791827e6d4db6b79905ad /build | |
parent | 4a77efce46d82f91c0539c3c012381ff20d0d2f5 (diff) | |
download | rpm-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.c | 20 | ||||
-rw-r--r-- | build/argv.h | 11 | ||||
-rw-r--r-- | build/rpmfc.c | 527 | ||||
-rw-r--r-- | build/rpmfc.h | 40 | ||||
-rw-r--r-- | build/tfr.c | 169 |
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); |