From a0bdebee4dad4cae17a8585cf9be74fb7093a3c5 Mon Sep 17 00:00:00 2001 From: jbj Date: Mon, 14 Oct 2002 14:52:45 +0000 Subject: [PATCH] Spin mostly complete file classifier off to rpmfc.[ch]. CVS patchset: 5773 CVS date: 2002/10/14 14:52:45 --- build/Makefile.am | 4 +- build/argv.c | 75 +++++++++++++--- build/argv.h | 46 +++++++++- build/rpmfc.c | 254 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ build/rpmfc.h | 86 ++++++++++++++++++ build/tfr.c | 14 +-- 6 files changed, 456 insertions(+), 23 deletions(-) create mode 100644 build/rpmfc.c create mode 100644 build/rpmfc.h diff --git a/build/Makefile.am b/build/Makefile.am index 3ed2f50..fd6b6da 100644 --- a/build/Makefile.am +++ b/build/Makefile.am @@ -26,14 +26,14 @@ tfr_LDADD = \ pkgincdir = $(pkgincludedir) pkginc_HEADERS = rpmbuild.h rpmspec.h -noinst_HEADERS = argv.h buildio.h +noinst_HEADERS = argv.h buildio.h rpmfc.h lib_LTLIBRARIES = librpmbuild.la librpmbuild_la_SOURCES = \ argv.c build.c expression.c files.c misc.c names.c pack.c \ parseBuildInstallClean.c parseChangelog.c parseDescription.c \ parseFiles.c parsePreamble.c parsePrep.c parseReqs.c parseScript.c \ - parseSpec.c poptBT.c reqprov.c spec.c + parseSpec.c poptBT.c reqprov.c rpmfc.c spec.c librpmbuild_la_LDFLAGS = -release @VERSION@ # XXX Add internal libtool dependence diff --git a/build/argv.c b/build/argv.c index 3a84b76..01af214 100644 --- a/build/argv.c +++ b/build/argv.c @@ -33,16 +33,27 @@ void argvPrint(const char * msg, ARGV_t argv, FILE * fp) } -int argvFree(/*@only@*/ /*@null@*/ ARGV_t argv) +ARGI_t argiFree(ARGI_t argi) +{ + if (argi) { + argi->nvals = 0; + argi->vals = _free(argi->vals); + } + argi = _free(argi); + return NULL; +} + +ARGV_t argvFree(/*@only@*/ /*@null@*/ ARGV_t argv) { ARGV_t av; - if ((av = argv)) { - while (*av) - *av = _free(*av); - argv = _free(argv); - } - return 0; +/*@-branchstate@*/ + if (argv) + for (av = argv; *av; av++) + *av = _free(*av); +/*@=branchstate@*/ + argv = _free(argv); + return NULL; } int argvCount(/*@null@*/ const ARGV_t argv) @@ -57,22 +68,64 @@ int argvCount(/*@null@*/ const ARGV_t argv) int argvCmp(const void * a, const void * b) { /*@-boundsread@*/ - ARG_t astr = *(ARGV_t)a; - ARG_t bstr = *(ARGV_t)b; + ARGstr_t astr = *(ARGV_t)a; + ARGstr_t bstr = *(ARGV_t)b; /*@=boundsread@*/ return strcmp(astr, bstr); } int argvSort(ARGV_t argv, int (*compar)(const void *, const void *)) { + if (compar == NULL) + compar = argvCmp; qsort(argv, argvCount(argv), sizeof(*argv), compar); return 0; } -ARGV_t argvSearch(ARGV_t argv, ARG_t s, +ARGV_t argvSearch(ARGV_t argv, ARGstr_t val, int (*compar)(const void *, const void *)) { - return bsearch(&s, argv, argvCount(argv), sizeof(*argv), compar); + if (argv == NULL) + return NULL; + if (compar == NULL) + compar = argvCmp; + return bsearch(&val, argv, argvCount(argv), sizeof(*argv), compar); +} + +int argiAdd(/*@out@*/ ARGI_t * argip, unsigned ix, int val) +{ + ARGI_t argi; + + if (argip == NULL) + return -1; + if (*argip == NULL) + *argip = xcalloc(1, sizeof(**argip)); + argi = *argip; + if (ix >= argi->nvals) { + argi->vals = xrealloc(argi->vals, (ix + 1) * sizeof(*argi->vals)); + memset(argi->vals + argi->nvals, 0, + (ix - argi->nvals) * sizeof(*argi->vals)); + argi->nvals = ix + 1; + } + argi->vals[ix] = val; + return 0; +} + +int argvAdd(/*@out@*/ ARGV_t * argvp, ARGstr_t val) +{ + ARGV_t argv; + int argc; + + if (argvp == NULL) + return -1; + argc = argvCount(*argvp); +/*@-unqualifiedtrans@*/ + *argvp = xrealloc(*argvp, (argc + 1 + 1) * sizeof(**argvp)); +/*@=unqualifiedtrans@*/ + argv = *argvp; + argv[argc++] = xstrdup(val); + argv[argc ] = NULL; + return 0; } int argvAppend(/*@out@*/ ARGV_t * argvp, const ARGV_t av) diff --git a/build/argv.h b/build/argv.h index ae986f3..607be34 100644 --- a/build/argv.h +++ b/build/argv.h @@ -5,8 +5,15 @@ * \file build/argv.h */ -typedef const char * ARG_t; -typedef ARG_t * ARGV_t; +typedef const char * ARGstr_t; +typedef ARGstr_t * ARGV_t; + +typedef int * ARGint_t; +struct ARGI_s { + unsigned nvals; + ARGint_t vals; +}; +typedef struct ARGI_s * ARGI_t; #ifdef __cplusplus extern "C" { @@ -23,10 +30,21 @@ void argvPrint(const char * msg, ARGV_t argv, FILE * fp) /*@modifies *fp, fileSystem @*/; /** + * Destroy an argi array. + * @param argi argi array + * @return NULL always + */ +/*@null@*/ +ARGI_t argiFree(/*@only@*/ /*@null@*/ ARGI_t argi) + /*@modifies argi @*/; + +/** * Destroy an argv array. * @param argv argv array + * @return NULL always */ -int argvFree(/*@only@*/ /*@null@*/ ARGV_t argv) +/*@null@*/ +ARGV_t argvFree(/*@only@*/ /*@null@*/ ARGV_t argv) /*@modifies argv @*/; /** @@ -57,14 +75,34 @@ int argvSort(ARGV_t argv, int (*compar)(const void *, const void *)) * @param argv argv array */ /*@dependent@*/ /*@null@*/ -ARGV_t argvSearch(ARGV_t argv, ARG_t s, +ARGV_t argvSearch(ARGV_t argv, ARGstr_t val, int (*compar)(const void *, const void *)) /*@*/; /** + * Add an int to an argi array. + * @retval *argip argi array + * @parm ix argi array index + * @param val int arg to add + * @return 0 always + */ +int argiAdd(/*@out@*/ ARGI_t * argip, unsigned ix, int val) + /*@modifies *argip @*/; + +/** + * Add a string to an argv array. + * @retval *argvp argv array + * @param val string arg to append + * @return 0 always + */ +int argvAdd(/*@out@*/ ARGV_t * argvp, ARGstr_t val) + /*@modifies *argvp @*/; + +/** * Append one argv array to another. * @retval *argvp argv array * @param av argv array to append + * @return 0 always */ int argvAppend(/*@out@*/ ARGV_t * argvp, const ARGV_t av) /*@modifies *argvp @*/; diff --git a/build/rpmfc.c b/build/rpmfc.c new file mode 100644 index 0000000..6ec8860 --- /dev/null +++ b/build/rpmfc.c @@ -0,0 +1,254 @@ +/*@-bounds@*/ +#include "system.h" + +#include +#include +#include + +#include "debug.h" + +/** + */ +/*@unchecked@*/ /*@observer@*/ +static struct fclassTokens_s fclassTokens[] = { + { "ELF 32-bit", RPMFC_ELF32|RPMFC_INCLUDE }, + { "ELF 64-bit", RPMFC_ELF64|RPMFC_INCLUDE }, + { "executable", RPMFC_EXECUTABLE }, + { "script", RPMFC_SCRIPT }, + { "text", RPMFC_TEXT }, + { "document", RPMFC_DOCUMENT }, + + { "directory", RPMFC_DIRECTORY|RPMFC_INCLUDE }, + + { "statically linked", RPMFC_STATIC }, + { "not stripped", RPMFC_NOTSTRIPPED }, + { "compressed", RPMFC_COMPRESSED }, + { "font", RPMFC_FONT }, + + { "current ar archive", RPMFC_STATIC|RPMFC_LIBRARY|RPMFC_ARCHIVE|RPMFC_INCLUDE }, + { " font", RPMFC_FONT|RPMFC_INCLUDE }, + { " Font", RPMFC_FONT|RPMFC_INCLUDE }, + + { "Zip archive data", RPMFC_COMPRESSED|RPMFC_ARCHIVE|RPMFC_INCLUDE }, + { "tar archive", RPMFC_ARCHIVE|RPMFC_INCLUDE }, + { "cpio archive", RPMFC_ARCHIVE|RPMFC_INCLUDE }, + { "RPM v3", RPMFC_ARCHIVE|RPMFC_INCLUDE }, + + { "shell script", RPMFC_SCRIPT|RPMFC_INCLUDE }, + { "awk script", RPMFC_SCRIPT|RPMFC_INCLUDE }, + { "perl script", RPMFC_SCRIPT|RPMFC_INCLUDE }, + { "python script", RPMFC_SCRIPT|RPMFC_INCLUDE }, + + { "python compiled", RPMFC_SCRIPT|RPMFC_INCLUDE }, + { "PHP script", RPMFC_SCRIPT|RPMFC_INCLUDE }, + + { "empty", RPMFC_WHITE|RPMFC_INCLUDE }, + + { "HTML", RPMFC_WHITE|RPMFC_INCLUDE }, + { "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 }, + + { "ASCII", RPMFC_WHITE }, + { "ISO-8859", RPMFC_WHITE }, + + { "data", RPMFC_WHITE }, + + { "application", RPMFC_WHITE }, + { "boot", RPMFC_WHITE }, + { "catalog", RPMFC_WHITE }, + { "code", RPMFC_WHITE }, + { "file", RPMFC_WHITE }, + { "format", RPMFC_WHITE }, + { "message", RPMFC_WHITE }, + { "program", RPMFC_WHITE }, + { "text", RPMFC_WHITE }, + + { "broken symbolic link to ", RPMFC_WHITE|RPMFC_ERROR }, + { "can't read", RPMFC_WHITE|RPMFC_ERROR }, + { "can't stat", RPMFC_WHITE|RPMFC_ERROR }, + { "executable, can't read", RPMFC_WHITE|RPMFC_ERROR }, + { "core file", RPMFC_WHITE|RPMFC_ERROR }, + + { NULL, RPMFC_BLACK } +}; + +/*@unchecked@*/ +static int fcolorIgnore = + (RPMFC_ELF32|RPMFC_ELF64|RPMFC_DIRECTORY|RPMFC_LIBRARY|RPMFC_ARCHIVE|RPMFC_FONT|RPMFC_SCRIPT|RPMFC_WHITE); + +int fclassColoring(const char * fmstr) +{ + fclassToken fct; + int fcolor = RPMFC_BLACK; + + for (fct = fclassTokens; fct->token != NULL; fct++) { + if (strstr(fmstr, fct->token) == NULL) + continue; + fcolor |= fct->colors; + if (fcolor & RPMFC_INCLUDE) + return fcolor; + } + return fcolor; +} + +void fclassPrint(const char * msg, FCLASS_t fc, FILE * fp) +{ + int ac = 0; + int fcolor; + int ix; + + if (fp == NULL) fp = stderr; + + if (msg) + fprintf(fp, "===================================== %s\n", msg); + + 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; + + 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"); + } + + ac++; + } +} + +FCLASS_t fclassFree(FCLASS_t fc) +{ + if (fc) { + fc->fn = argvFree(fc->fn); + fc->fdictx = argiFree(fc->fdictx); + fc->fcolor = argiFree(fc->fcolor); + fc->dict = argvFree(fc->dict); + } + fc = _free(fc); + return NULL; +} + +FCLASS_t fclassNew(void) +{ + FCLASS_t fc = xcalloc(1, sizeof(*fc)); + return fc; +} + +int fclassClassify(FCLASS_t *fcp, ARGV_t argv) +{ + FCLASS_t fc; + char buf[BUFSIZ]; + ARGV_t dav; + const char * s, * se; + char * t; + int fcolor; + int xx; + int fknown, fwhite; + + + if (fcp == NULL || argv == NULL) + return 0; + + if (*fcp == NULL) + *fcp = fclassNew(); + fc = *fcp; + + /* Set up the file class dictionary. */ + xx = argvAdd(&fc->dict, ""); + xx = argvAdd(&fc->dict, "directory"); + +/*@-temptrans@*/ + fc->av = argv; +/*@=temptrans@*/ + while ((s = *fc->av++) != NULL) { + se = s; + while (*se && !(se[0] == ':' && se[1] == ' ')) + se++; + if (*se == '\0') + return -1; + + se++; + while (*se && (*se == ' ' || *se == '\t')) + se++; + if (*se == '\0') + return -1; + + fcolor = fclassColoring(se); + if (fcolor == RPMFC_WHITE || !(fcolor & RPMFC_INCLUDE)) + continue; + + dav = argvSearch(fc->dict, se, NULL); + if (dav == NULL) { + xx = argvAdd(&fc->dict, se); + xx = argvSort(fc->dict, NULL); + } + } + + /* Classify files. */ +/*@-kepttrans@*/ + fc->av = argv; +/*@=kepttrans@*/ + fc->ix = 0; + fknown = 0; + while ((s = *fc->av++) != NULL) { + se = s; + while (*se && !(se[0] == ':' && se[1] == ' ')) + se++; + if (*se == '\0') + return -1; + + t = stpncpy(buf, s, (se - s)); + *t = '\0'; + + xx = argvAdd(&fc->fn, buf); + + se++; + while (*se && (*se == ' ' || *se == '\t')) + se++; + if (*se == '\0') + return -1; + + dav = argvSearch(fc->dict, se, NULL); + if (dav) { + xx = argiAdd(&fc->fdictx, fc->ix, (dav - fc->dict)); + fknown++; + } else { + xx = argiAdd(&fc->fdictx, fc->ix, 0); + fwhite++; + } + + xx = argiAdd(&fc->fcolor, fc->ix, fclassColoring(se)); + + fc->ix++; + } + fc->av = NULL; + +/*@-modfilesys@*/ +sprintf(buf, "final: files %d dict[%d] %d%%", argvCount(fc->fn), argvCount(fc->dict), ((100 * fknown)/fc->ix)); +fclassPrint(buf, fc, NULL); +/*@=modfilesys@*/ + + return 0; +} +/*@=bounds@*/ diff --git a/build/rpmfc.h b/build/rpmfc.h new file mode 100644 index 0000000..c922972 --- /dev/null +++ b/build/rpmfc.h @@ -0,0 +1,86 @@ +#ifndef _H_RPMFC_ +#define _H_RPMFC_ + +typedef struct fclass_s * FCLASS_t; + +struct fclass_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 */ +}; + + +enum FCOLOR_e { + RPMFC_BLACK = 0, + RPMFC_ELF32 = (1 << 0), + RPMFC_ELF64 = (1 << 1), + + RPMFC_EXECUTABLE = (1 << 2), + RPMFC_SCRIPT = (1 << 3), + RPMFC_TEXT = (1 << 4), + + RPMFC_DIRECTORY = (1 << 8), + RPMFC_LIBRARY = (1 << 9), + RPMFC_DOCUMENT = (1 << 10), + + RPMFC_STATIC = (1 << 16), + RPMFC_NOTSTRIPPED = (1 << 18), + RPMFC_COMPRESSED = (1 << 19), + + RPMFC_SYMLINK = (1 << 24), + RPMFC_ARCHIVE = (1 << 25), + RPMFC_FONT = (1 << 26), + + RPMFC_WHITE = (1 << 29), + RPMFC_INCLUDE = (1 << 30), + RPMFC_ERROR = (1 << 31) +}; +typedef enum FCOLOR_e FCOLOR_t; + +struct fclassTokens_s { +/*@observer@*/ + const char * token; + int colors; +}; + +typedef struct fclassTokens_s * fclassToken; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + */ +int fclassColoring(const char * fmstr) + /*@*/; + +/** + */ +void fclassPrint(const char * msg, FCLASS_t fc, FILE * fp) + /*@globals fileSystem @*/ + /*@modifies *fp, fileSystem @*/; +/** + */ +/*@null@*/ +FCLASS_t fclassFree(/*@only@*/ /*@null@*/ FCLASS_t fc) + /*@modifies fc @*/; + +/** + */ +FCLASS_t fclassNew(void) + /*@*/; + +/** + */ +int fclassClassify(/*@out@*/ FCLASS_t *fcp, ARGV_t argv) + /*@modifies *fcp @*/; + +#ifdef __cplusplus +} +#endif + +#endif /* _H_RPMFC_ */ diff --git a/build/tfr.c b/build/tfr.c index 46c7623..66726c2 100644 --- a/build/tfr.c +++ b/build/tfr.c @@ -2,6 +2,7 @@ #include #include +#include #include "debug.h" @@ -25,6 +26,7 @@ main(int argc, char *const argv[]) int pac = 0; ARGV_t xav; ARGV_t av = NULL; + FCLASS_t fc; int ac = 0; const char * s; int ec = 1; @@ -50,23 +52,23 @@ main(int argc, char *const argv[]) xav = NULL; xx = argvAppend(&xav, pav); xx = argvAppend(&xav, av); - pav = _free(pav); + pav = _free(pav); /* XXX popt mallocs in single blob. */ s = _free(s); /* Read file(1) output. */ sb = getOutputFrom(NULL, xav, NULL, 0, 1); + xav = argvFree(xav); - xx = argvFree(xav); - - xav = NULL; xx = argvSplit(&xav, getStringBuf(sb), "\n"); sb = freeStringBuf(sb); xx = argvSort(xav, argvCmp); -argvPrint("final", xav, NULL); + fc = NULL; + xx = fclassClassify(&fc, xav); + fc = fclassFree(fc); - xx = argvFree(xav); + xav = argvFree(xav); exit: optCon = rpmcliFini(optCon); -- 2.7.4