}
-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)
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)
* \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" {
/*@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 @*/;
/**
* @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 @*/;
--- /dev/null
+/*@-bounds@*/
+#include "system.h"
+
+#include <rpmbuild.h>
+#include <argv.h>
+#include <rpmfc.h>
+
+#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@*/
--- /dev/null
+#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_ */