diff options
author | jbj <devnull@localhost> | 2003-12-21 23:42:22 +0000 |
---|---|---|
committer | jbj <devnull@localhost> | 2003-12-21 23:42:22 +0000 |
commit | 04a45c2ae849fa917cba3a6051cf8b41c414f26d (patch) | |
tree | aeacb9f1515f6b0c3b98bc92fe92e93d097fb032 /lib | |
parent | 3cd622588855dbf359b67b5532fd2629b0b6bb68 (diff) | |
download | librpm-tizen-04a45c2ae849fa917cba3a6051cf8b41c414f26d.tar.gz librpm-tizen-04a45c2ae849fa917cba3a6051cf8b41c414f26d.tar.bz2 librpm-tizen-04a45c2ae849fa917cba3a6051cf8b41c414f26d.zip |
More getter methods, add stems to regex pattern match.
CVS patchset: 6989
CVS date: 2003/12/21 23:42:22
Diffstat (limited to 'lib')
-rw-r--r-- | lib/rpmsx.c | 327 | ||||
-rw-r--r-- | lib/rpmsx.h | 52 | ||||
-rw-r--r-- | lib/setfiles.c | 13 |
3 files changed, 298 insertions, 94 deletions
diff --git a/lib/rpmsx.c b/lib/rpmsx.c index 64d8fd730..8c6eb48b3 100644 --- a/lib/rpmsx.c +++ b/lib/rpmsx.c @@ -13,6 +13,165 @@ /*@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(®_buf); -#else - sxp->stem_id = -1; -#endif + const char * reg_buf = regex; + sxp->fstem = rpmsxAdd(sx, ®_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; diff --git a/lib/rpmsx.h b/lib/rpmsx.h index 0a51bca9c..c654a1be7 100644 --- a/lib/rpmsx.h +++ b/lib/rpmsx.h @@ -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 diff --git a/lib/setfiles.c b/lib/setfiles.c index ac155c034..b799aae7f 100644 --- a/lib/setfiles.c +++ b/lib/setfiles.c @@ -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; |