summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorjbj <devnull@localhost>2003-12-21 23:42:22 +0000
committerjbj <devnull@localhost>2003-12-21 23:42:22 +0000
commit04a45c2ae849fa917cba3a6051cf8b41c414f26d (patch)
treeaeacb9f1515f6b0c3b98bc92fe92e93d097fb032 /lib
parent3cd622588855dbf359b67b5532fd2629b0b6bb68 (diff)
downloadlibrpm-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.c327
-rw-r--r--lib/rpmsx.h52
-rw-r--r--lib/setfiles.c13
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(&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;
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;