More getter methods, add stems to regex pattern match.
authorjbj <devnull@localhost>
Sun, 21 Dec 2003 23:42:22 +0000 (23:42 +0000)
committerjbj <devnull@localhost>
Sun, 21 Dec 2003 23:42:22 +0000 (23:42 +0000)
CVS patchset: 6989
CVS date: 2003/12/21 23:42:22

lib/rpmsx.c
lib/rpmsx.h
lib/setfiles.c

index 64d8fd7..8c6eb48 100644 (file)
 /*@unchecked@*/
 int _rpmsx_debug = 0;
 
+/**
+ */
+static int rpmsxpCompare(const void* A, const void* B)
+       /*@*/
+{
+    rpmsxp sxpA = (rpmsxp) A;
+    rpmsxp sxpB = (rpmsxp) B;
+    return (sxpB->hasMetaChars - sxpA->hasMetaChars);
+}
+
+/**
+ * Sort the specifications with most general first.
+ * @param sx           security context patterns
+ */
+static void rpmsxSort(rpmsx sx)
+       /*@modifies sx @*/
+{
+    qsort(sx->sxp, sx->Count, sizeof(*sx->sxp), rpmsxpCompare);
+}
+
+/* Determine if the regular expression specification has any meta characters. */
+static void rpmsxpHasMetaChars(rpmsxp sxp)
+       /*@modifies sxp @*/
+{
+    const char * s = sxp->pattern;
+    size_t ns = strlen(s);
+    const char * se = s + ns;
+
+    sxp->hasMetaChars = 0; 
+
+    /* Look at each character in the RE specification string for a 
+     * meta character. Return when any meta character reached. */
+    while (s != se) {
+       switch(*s) {
+       case '.':
+       case '^':
+       case '$':
+       case '?':
+       case '*':
+       case '+':
+       case '|':
+       case '[':
+       case '(':
+       case '{':
+           sxp->hasMetaChars = 1;
+           return;
+           break;
+       case '\\':              /* skip the next character */
+           s++;
+           break;
+       default:
+           break;
+
+       }
+       s++;
+    }
+    return;
+}
+
+/**
+ * Return the length of the text that can be considered the stem.
+ * @return             stem length, 0 if no identifiable stem
+ */
+static size_t rpmsxsPStem(const char * const buf)
+       /*@*/
+{
+    static const char * const regex_chars = ".^$?*+|[({";
+    const char * tmp = strchr(buf + 1, '/');
+    const char * ind;
+
+    if (!tmp)
+       return 0;
+
+    for (ind = buf + 1; ind < tmp; ind++) {
+       if (strchr(regex_chars, (int)*ind))
+           return 0;
+    }
+    return tmp - buf;
+}
+
+/**
+ * Return the length of the text that is the stem of a file name.
+ * @return             stem length, 0 if no identifiable stem
+ */
+static size_t rpmsxsFStem(const char * const buf)
+       /*@*/
+{
+    const char * tmp = strchr(buf + 1, '/');
+
+    if (!tmp)
+       return 0;
+    return tmp - buf;
+}
+
+/**
+ * Find (or create) the stem of a file spec.
+ * Error iff a file in the root directory or a regex that is too complex.
+ *
+ * @retval *bpp                ptr to text after stem.
+ * @return             stem index, -1 on error
+ */
+static int rpmsxAdd(rpmsx sx, const char ** bpp)
+       /*@modifies sx, *bpp @*/
+{
+    size_t stem_len = rpmsxsPStem(*bpp);
+    rpmsxs sxs;
+    int i;
+
+    if (!stem_len)
+       return -1;
+    for (i = 0; i < sx->nsxs; i++) {
+       sxs = sx->sxs + i;
+       if (stem_len != sxs->len)
+           continue;
+       if (strncmp(*bpp, sxs->stem, stem_len))
+           continue;
+       *bpp += stem_len;
+       return i;
+    }
+
+    if (sx->nsxs == sx->maxsxs) {
+       sx->maxsxs = sx->maxsxs * 2 + 16;
+       sx->sxs = xrealloc(sx->sxs, sizeof(*sx->sxs) * sx->maxsxs);
+    }
+    sxs = sx->sxs + sx->nsxs;
+    sxs->len = stem_len;
+    sxs->stem = strndup(*bpp, stem_len);
+    sx->nsxs++;
+    *bpp += stem_len;
+    return sx->nsxs - 1;
+}
+
+/**
+ * Find the stem of a file name.
+ * Error iff a file in the root directory or a regex that is too complex.
+ *
+ * @retval *bpp                ptr to text after stem.
+ * @return             stem index, -1 on error
+ */
+static int rpmsxFind(const rpmsx sx, const char ** bpp)
+       /*@modifies *bpp @*/
+{
+    size_t stem_len = rpmsxsFStem(*bpp);
+    rpmsxs sxs;
+    int i;
+
+    if (stem_len)
+    for (i = 0; i < sx->nsxs; i++) {
+       sxs = sx->sxs + i;
+       if (stem_len != sxs->len)
+           continue;
+       if (strncmp(*bpp, sxs->stem, stem_len))
+           continue;
+       *bpp += stem_len;
+       return i;
+    }
+    return -1;
+}
+
 rpmsx XrpmsxUnlink(rpmsx sx, const char * msg, const char * fn, unsigned ln)
 {
     if (sx == NULL) return NULL;
@@ -62,10 +221,16 @@ fprintf(stderr, "*** sx %p\t%s[%d]\n", sx, __func__, sx->Count);
        regfree(sxp->preg);
        sxp->preg = _free(sxp->preg);
     }
-    /*@=branchstate@*/
-
     sx->sxp = _free(sx->sxp);
 
+    if (sx->nsxs > 0)
+    for (i = 0; i < sx->nsxs; i++) {
+       rpmsxs sxs = sx->sxs + i;
+       sxs->stem = _free(sxs->stem);
+    }
+    sx->sxs = _free(sx->sxs);
+    /*@=branchstate@*/
+
     (void) rpmsxUnlink(sx, __func__);
     /*@-refcounttrans -usereleased@*/
 /*@-bounsxwrite@*/
@@ -76,51 +241,6 @@ fprintf(stderr, "*** sx %p\t%s[%d]\n", sx, __func__, sx->Count);
     return NULL;
 }
 
-static int rpmsxpCompare(const void* A, const void* B)
-{
-    rpmsxp sxpA = (rpmsxp) A;
-    rpmsxp sxpB = (rpmsxp) B;
-    return (sxpA->hasMetaChars - sxpB->hasMetaChars);
-}
-
-/* Determine if the regular expression specification has any meta characters. */
-static void rpmsxpHasMetaChars(rpmsxp sxp)
-{
-    const char * s = sxp->pattern;
-    size_t ns = strlen(s);
-    const char * se = s + ns;
-
-    sxp->hasMetaChars = 0; 
-
-    /* Look at each character in the RE specification string for a 
-     * meta character. Return when any meta character reached. */
-    while (s != se) {
-       switch(*s) {
-       case '.':
-       case '^':
-       case '$':
-       case '?':
-       case '*':
-       case '+':
-       case '|':
-       case '[':
-       case '(':
-       case '{':
-           sxp->hasMetaChars = 1;
-           return;
-           break;
-       case '\\':              /* skip the next character */
-           s++;
-           break;
-       default:
-           break;
-
-       }
-       s++;
-    }
-    return;
-}
-
 /**
  * Check for duplicate specifications. If a duplicate specification is found 
  * and the context is the same, give a warning to the user. If a duplicate 
@@ -131,6 +251,7 @@ static void rpmsxpHasMetaChars(rpmsxp sxp)
  * @return             0 on success
  */
 static int rpmsxpCheckNoDupes(const rpmsx sx)
+       /*@*/
 {
     int i, j;
     int rc = 0;
@@ -143,7 +264,7 @@ static int rpmsxpCheckNoDupes(const rpmsx sx)
            /* Check if same RE string */
            if (strcmp(sxpj->pattern, sxpi->pattern))
                continue;
-           if (sxpj->mode && sxpi->mode && sxpj->mode != sxpi->mode)
+           if (sxpj->fmode && sxpi->fmode && sxpj->fmode != sxpi->fmode)
                continue;
 
            /* Same RE string found */
@@ -167,7 +288,7 @@ static int rpmsxpCheckNoDupes(const rpmsx sx)
 static int nerr;
 #define        inc_err()       nerr++
 
-int rpmsxParse(rpmsx sx, const char *fn)
+int rpmsxParse(rpmsx sx, const char * fn)
 {
     FILE * fp;
     char errbuf[255 + 1];
@@ -240,14 +361,10 @@ int rpmsxParse(rpmsx sx, const char *fn)
                type = 0;
            }
 
+           /* On pass 2, compile and store the specification. */
            if (pass == 1) {
-               /* On the second pass, compile and store the specification in spec. */
-               const char *reg_buf = regex;
-#ifdef NOTYET
-               sxp->stem_id = find_stem_from_spec(&reg_buf);
-#else
-               sxp->stem_id = -1;
-#endif
+               const char * reg_buf = regex;
+               sxp->fstem = rpmsxAdd(sx, &reg_buf);
                sxp->pattern = regex;
 
                /* Anchor the regular expression. */
@@ -271,7 +388,7 @@ int rpmsxParse(rpmsx sx, const char *fn)
 
                /* Convert the type string to a mode format */
                sxp->type = type;
-               sxp->mode = 0;
+               sxp->fmode = 0;
                if (!type)
                    goto skip_type;
                len = strlen(type);
@@ -283,27 +400,13 @@ int rpmsxParse(rpmsx sx, const char *fn)
                    goto skip_type;
                }
                switch (type[1]) {
-               case 'b':
-                   sxp->mode = S_IFBLK;
-                   break;
-               case 'c':
-                   sxp->mode = S_IFCHR;
-                   break;
-               case 'd':
-                   sxp->mode = S_IFDIR;
-                   break;
-               case 'p':
-                   sxp->mode = S_IFIFO;
-                   break;
-               case 'l':
-                   sxp->mode = S_IFLNK;
-                   break;
-               case 's':
-                   sxp->mode = S_IFSOCK;
-                   break;
-               case '-':
-                   sxp->mode = S_IFREG;
-                   break;
+               case 'b':       sxp->fmode = S_IFBLK;   break;
+               case 'c':       sxp->fmode = S_IFCHR;   break;
+               case 'd':       sxp->fmode = S_IFDIR;   break;
+               case 'p':       sxp->fmode = S_IFIFO;   break;
+               case 'l':       sxp->fmode = S_IFLNK;   break;
+               case 's':       sxp->fmode = S_IFSOCK;  break;
+               case '-':       sxp->fmode = S_IFREG;   break;
                default:
                    fprintf(stderr,
                        _("%s:  invalid type specifier %s on line number %d\n"),
@@ -352,7 +455,7 @@ int rpmsxParse(rpmsx sx, const char *fn)
     fclose(fp);
 
     /* Sort the specifications with most general first */
-    qsort(sx->sxp, sx->Count, sizeof(*sx->sxp), rpmsxpCompare);
+    rpmsxSort(sx);
 
     /* Verify no exact duplicates */
     if (rpmsxpCheckNoDupes(sx) != 0)
@@ -366,9 +469,13 @@ rpmsx rpmsxNew(const char * fn)
     rpmsx sx;
 
     sx = xcalloc(1, sizeof(*sx));
+    sx->sxp = NULL;
     sx->Count = 0;
     sx->i = -1;
-    sx->sxp = NULL;
+    sx->sxs = NULL;
+    sx->nsxs = 0;
+    sx->maxsxs = 0;
+    sx->reverse = 0;
 
     (void) rpmsxLink(sx, __func__);
 
@@ -435,6 +542,24 @@ regex_t * rpmsxRE(const rpmsx sx)
     return preg;
 }
 
+mode_t rpmsxFMode(const rpmsx sx)
+{
+    mode_t fmode = 0;
+
+    if (sx != NULL && sx->i >= 0 && sx->i < sx->Count)
+       fmode = (sx->sxp + sx->i)->fmode;
+    return fmode;
+}
+
+int rpmsxFStem(const rpmsx sx)
+{
+    int fstem = -1;
+
+    if (sx != NULL && sx->i >= 0 && sx->i < sx->Count)
+       fstem = (sx->sxp + sx->i)->fstem;
+    return fstem;
+}
+
 int rpmsxNext(/*@null@*/ rpmsx sx)
        /*@modifies sx @*/
 {
@@ -479,13 +604,49 @@ rpmsx rpmsxInit(/*@null@*/ rpmsx sx, int reverse)
     /*@=refcounttrans@*/
 }
 
-const char * rpmsxApply(rpmsx sx, const char * fn)
+const char * rpmsxFContext(rpmsx sx, const char * fn, mode_t fmode)
 {
-   const char * context = NULL;
+    const char * context = NULL;
+    const char * myfn = fn;
+    int fstem = rpmsxFind(sx, &myfn);
+    int i;
 
     sx = rpmsxInit(sx, 1);
     if (sx != NULL)
-    while (rpmsxNext(sx) >= 0) {
+    while ((i = rpmsxNext(sx)) >= 0) {
+       regex_t * preg;
+       mode_t sxfmode;
+       int sxfstem;
+       int ret;
+
+       sxfstem = rpmsxFStem(sx);
+       if (sxfstem != -1 && sxfstem != fstem)
+           continue;
+
+       sxfmode = rpmsxFMode(sx);
+       if (sxfmode && (fmode & S_IFMT) != sxfmode)
+           continue;
+
+       preg = rpmsxRE(sx);
+       if (preg == NULL)
+           continue;
+
+       ret = regexec(preg, (sxfstem == -1 ? fn : myfn), 0, NULL, 0);
+       switch (ret) {
+       case REG_NOMATCH:
+           continue;
+           /*@notreaached@*/ break;
+       case 0:
+           context = rpmsxContext(sx);
+           break;
+       default:
+         { static char errbuf[255 + 1];
+           regerror(ret, preg, errbuf, sizeof errbuf);
+           fprintf(stderr, "unable to match %s against %s:  %s\n",
+                fn, rpmsxPattern(sx), errbuf);
+         } break;
+       }
+       break;
     }
 
     return context;
index 0a51bca..c654a1b 100644 (file)
@@ -23,8 +23,9 @@ extern int _rpmsx_debug;
 extern int _rpmsx_nopromote;
 /*@=exportlocal@*/
 
-typedef struct rpmsxp_s * rpmsxp;
 typedef struct rpmsx_s * rpmsx;
+typedef struct rpmsxp_s * rpmsxp;
+typedef struct rpmsxs_s * rpmsxs;
 
 #if defined(_RPMSX_INTERNAL)
 /**
@@ -39,10 +40,19 @@ struct rpmsxp_s {
     const char * context;      /*!< Security context. */
 /*@only@*/ /*@null@*/
     regex_t * preg;            /*!< Compiled regex. */
-    mode_t mode;               /*!< File type. */
+    mode_t fmode;              /*!< File type. */
     int matches;
     int hasMetaChars;
-    int stem_id;
+    int fstem;                 /*!< Stem id. */
+};
+
+/**
+ * File/pattern stem.
+ */
+struct rpmsxs_s {
+/*@only@*/ /*@null@*/
+    const char * stem;
+    int len;
 };
 
 /**
@@ -51,8 +61,11 @@ struct rpmsxp_s {
 struct rpmsx_s {
 /*@only@*/ /*@null@*/
     rpmsxp sxp;                        /*!< File context patterns. */
-    int Count;                 /*!< No. of elements */
-    int i;                     /*!< Current element index. */
+    int Count;                 /*!< No. of file context patterns. */
+    int i;                     /*!< Current pattern index. */
+    rpmsxs sxs;                        /*!< File stems. */
+    int nsxs;                  /*!< No. of file stems. */
+    int maxsxs;                        /*!< No. of allocated file stems. */
     int reverse;               /*!< Reverse traversal? */
     int nrefs;                 /*!< Reference count. */
 };
@@ -190,6 +203,24 @@ extern regex_t * rpmsxRE(/*@null@*/ const rpmsx sx)
        /*@*/;
 
 /**
+ * Return current file mode.
+ * @param sx           security context patterns
+ * @return             current file mode, 0 on invalid
+ */
+/*@observer@*/ /*@null@*/
+extern mode_t rpmsxFMode(/*@null@*/ const rpmsx sx)
+       /*@*/;
+
+/**
+ * Return current file stem.
+ * @param sx           security context patterns
+ * @return             current file stem, -1 on invalid
+ */
+/*@observer@*/ /*@null@*/
+extern int rpmsxFStem(/*@null@*/ const rpmsx sx)
+       /*@*/;
+
+/**
  * Return next security context patterns iterator index.
  * @param sx           security context patterns
  * @return             security context patterns iterator index, -1 on termination
@@ -207,6 +238,17 @@ int rpmsxNext(/*@null@*/ rpmsx sx)
 rpmsx rpmsxInit(/*@null@*/ rpmsx sx, int reverse)
        /*@modifies sx @*/;
 
+/**
+ * Find file security context from path and type.
+ * @param sx           security context patterns
+ * @param fn           file path
+ * @param fmode                file mode
+ * @return             file security context
+ */
+/*@null@*/
+const char * rpmsxFContext(rpmsx sx, const char * fn, mode_t fmode)
+       /*@*/;
+
 #ifdef __cplusplus
 }
 #endif
index ac155c0..b799aae 100644 (file)
@@ -634,6 +634,7 @@ int parseREContexts(const char *fn)
     int lineno;
     int pass;
     int regerr;
+    spec_t sp;
 
     if ((fp = fopen(fn, "r")) == NULL) {
        perror(fn);
@@ -649,8 +650,6 @@ int parseREContexts(const char *fn)
      * and fills in the spec array.
      */
     for (pass = 0; pass < 2; pass++) {
-       spec_t sp;
-
        lineno = 0;
        nspec = 0;
        sp = spec_arr;
@@ -884,15 +883,17 @@ int main(int argc, char **argv)
     av = poptGetArgs(optCon);
     if (use_stdin) {
        add_assoc = 0;
-       /* Cannot mix with pathname arguments. */
-       if (av[0] != NULL)
+       /* Check exactly 1 arg */
+       if (av == NULL || !(av[0] != NULL && av[1] == NULL)) {
            usage(__progname, optCon);
+       }
     } else {
-       if (av[0] == NULL || av[1] == NULL)
+       /* Check at least 2 args */
+       if (av == NULL || !(av[0] != NULL && av[1] != NULL))
            usage(__progname, optCon);
     }
 
-       /* Parse the specification file. */
+    /* Parse the specification file. */
     if (parseREContexts(*av) != 0) {
        perror(*av);
        goto exit;