1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-10-27 10:25:13 +03:00

o Filter for the dev cache that takes values from config file:

devices {

        # first match is final, eg.  /dev/ide/cdrom
		        # get's rejected due to the first pattern

					filter=["r/cdrom/",         # don't touch the music !
							"a/hd[a-d][0-9]+/",
							"a/ide/",
							"a/sd/",
							"a/md/",
							"a|loop/[0-9]+|", # accept devfs style loop back
							"r/loop/",        # and reject old style
							"a/dasd/",
							"a/dac960/",
							"a/nbd/",
							"a/ida/",
							"a/cciss/",
							"a/ubd/",
							"r/.*/"] # reject all others
}


Alasdair this is ready to roll into the tools now.
This commit is contained in:
Joe Thornber 2001-10-19 18:20:37 +00:00
parent d1b28647ed
commit 291ec3b6c0
16 changed files with 453 additions and 106 deletions

2
configure vendored
View File

@ -2163,6 +2163,7 @@ test/mm/Makefile \
test/device/Makefile \ test/device/Makefile \
test/format1/Makefile \ test/format1/Makefile \
test/regex/Makefile \ test/regex/Makefile \
test/filters/Makefile \
" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 " | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
EOF EOF
cat >> $CONFIG_STATUS <<EOF cat >> $CONFIG_STATUS <<EOF
@ -2262,6 +2263,7 @@ test/mm/Makefile \
test/device/Makefile \ test/device/Makefile \
test/format1/Makefile \ test/format1/Makefile \
test/regex/Makefile \ test/regex/Makefile \
test/filters/Makefile \
"} "}
EOF EOF
cat >> $CONFIG_STATUS <<\EOF cat >> $CONFIG_STATUS <<\EOF

View File

@ -139,4 +139,5 @@ test/mm/Makefile \
test/device/Makefile \ test/device/Makefile \
test/format1/Makefile \ test/format1/Makefile \
test/regex/Makefile \ test/regex/Makefile \
test/filters/Makefile \
) )

View File

@ -8,6 +8,7 @@
../lib/device/device.h ../lib/device/device.h
../lib/display/display.h ../lib/display/display.h
../lib/filters/filter.h ../lib/filters/filter.h
../lib/filters/filter-regex.h
../lib/format1/format1.h ../lib/format1/format1.h
../lib/log/log.h ../lib/log/log.h
../lib/metadata/metadata.h ../lib/metadata/metadata.h

View File

@ -17,6 +17,7 @@ SOURCES=\
device/dev-io.c \ device/dev-io.c \
device/device.c \ device/device.c \
filters/filter.c \ filters/filter.c \
filters/filter-regex.c \
format1/disk-rep.c \ format1/disk-rep.c \
format1/format1.c \ format1/format1.c \
format1/import-export.c \ format1/import-export.c \

View File

@ -123,7 +123,7 @@ static int _insert(const char *path, int recurse)
struct stat info; struct stat info;
struct device *dev; struct device *dev;
log_very_verbose("dev-cache adding %s", path); //log_very_verbose("dev-cache adding %s", path);
if (stat(path, &info) < 0) { if (stat(path, &info) < 0) {
log_sys_very_verbose("stat", path); log_sys_very_verbose("stat", path);
@ -138,7 +138,7 @@ static int _insert(const char *path, int recurse)
} }
if (S_ISLNK(info.st_mode)) { if (S_ISLNK(info.st_mode)) {
log_debug("%s is a symbolic link, following", path); //log_debug("%s is a symbolic link, following", path);
if (!(path = _follow_link(path, &info))) { if (!(path = _follow_link(path, &info))) {
stack; stack;
return 0; return 0;
@ -146,7 +146,7 @@ static int _insert(const char *path, int recurse)
} }
if (!S_ISBLK(info.st_mode)) { if (!S_ISBLK(info.st_mode)) {
log_debug("%s is not a block device", path); //log_debug("%s is not a block device", path);
return 0; return 0;
} }

View File

@ -16,6 +16,7 @@
*/ */
struct dev_filter { struct dev_filter {
int (*passes_filter)(struct dev_filter *f, struct device *dev); int (*passes_filter)(struct dev_filter *f, struct device *dev);
void (*destroy)(struct dev_filter *f);
void *private; void *private;
}; };

207
lib/filters/filter-regex.c Normal file
View File

@ -0,0 +1,207 @@
/*
* Copyright (C) 2001 Sistina Software (UK) Limited.
*
* This file is released under the GPL.
*/
#include "pool.h"
#include "filter-regex.h"
#include "matcher.h"
#include "device.h"
#include "bitset.h"
#include "log.h"
struct rfilter {
struct pool *mem;
bitset_t accept;
struct matcher *engine;
};
int _extract_pattern(struct pool *mem, const char *pat,
char **regex, bitset_t accept, int index)
{
char sep, *r, *ptr;
/*
* is this an accept or reject pattern
*/
switch (*pat) {
case 'a':
bit_set(accept, index);
break;
case 'r':
bit_clear(accept, index);
break;
default:
log_info("pattern must begin with 'a' or 'r'");
return 0;
}
pat++;
/*
* get the seperator
*/
switch (*pat) {
case '(':
sep = ')';
break;
case '[':
sep = ']';
break;
case '{':
sep = '}';
break;
default:
sep = *pat;
}
pat++;
/*
* copy the regex
*/
if (!(r = pool_strdup(mem, pat))) {
stack;
return 0;
}
/*
* trim the trailing character, having checked it's sep.
*/
ptr = r + strlen(r) - 1;
if (*ptr != sep) {
log_info("invalid seperator at end of regex");
return 0;
}
*ptr = '\0';
regex[index] = r;
return 1;
}
int _build_matcher(struct rfilter *rf, struct config_value *val)
{
struct pool *scratch;
struct config_value *v;
char **regex;
int count = 0, i, r = 0;
if (!(scratch = pool_create(1024))) {
stack;
return 0;
}
/*
* count how many patterns we have.
*/
for (v = val; v; v = v->next) {
if (v->type != CFG_STRING) {
log_info("filter patterns must be enclosed in quotes");
goto out;
}
count++;
}
/*
* allocate space for them
*/
if (!(regex = pool_alloc(scratch, sizeof(*regex) * count))) {
stack;
goto out;
}
/*
* create the accept/reject bitset
*/
rf->accept = bitset_create(rf->mem, count);
/*
* fill the array back to front because we
* want the opposite precedence to what
* the matcher gives.
*/
for (v = val, i = count - 1; v; v = v->next, i--)
if (!_extract_pattern(scratch, v->v.str,
regex, rf->accept, i)) {
log_info("invalid filter pattern");
goto out;
}
/*
* build the matcher.
*/
if (!(rf->engine = matcher_create(rf->mem,
(const char **) regex, count)))
stack;
r = 1;
out:
pool_destroy(scratch);
return r;
}
static int _accept_p(struct dev_filter *f, struct device *dev)
{
int m;
struct rfilter *rf = (struct rfilter *) f->private;
m = matcher_run(rf->engine, dev->name);
/*
* pass everything that doesn't match,
* otherwise look it up in the accepts
* bitset.
*/
return (m < 0) ? 1 : bit(rf->accept, m);
}
static void _destroy(struct dev_filter *f)
{
struct rfilter *rf = (struct rfilter *) f->private;
pool_destroy(rf->mem);
}
struct dev_filter *regex_filter_create(struct config_value *patterns)
{
struct pool *mem = pool_create(256);
struct rfilter *rf;
struct dev_filter *f;
if (!mem) {
stack;
return NULL;
}
if (!(rf = pool_alloc(mem, sizeof(*rf)))) {
stack;
goto bad;
}
rf->mem = mem;
if (!_build_matcher(rf, patterns)) {
stack;
goto bad;
}
if (!(f = pool_zalloc(mem, sizeof(*f)))) {
stack;
goto bad;
}
f->passes_filter = _accept_p;
f->destroy = _destroy;
f->private = rf;
return f;
bad:
pool_destroy(mem);
return NULL;
}

View File

@ -0,0 +1,23 @@
/*
* Copyright (C) 2001 Sistina Software (UK) Limited.
*
* This file is released under the GPL.
*/
#ifndef _LVM_FILTER_REGEX_H
#define _LVM_FILTER_REGEX_H
#include "config.h"
#include "dev-cache.h"
/*
* patterns must be an array of strings of the form:
* [ra]<sep><regex><sep>, eg,
* r/cdrom/ - reject cdroms
* a|loop/[0-4]| - accept loops 0 to 4
* r|.*| - reject everything else
*/
struct dev_filter *regex_filter_create(struct config_value *patterns);
#endif

View File

@ -206,11 +206,11 @@ static int _calc_states(struct matcher *m, struct rx_node *rx)
/* create first state */ /* create first state */
dfa = _create_dfa_state(m->mem); dfa = _create_dfa_state(m->mem);
m->start = dfa; m->start = dfa;
ttree_insert(tt, rx->firstpos, dfa); ttree_insert(tt, rx->firstpos + 1, dfa);
/* prime the queue */ /* prime the queue */
h = t = _create_state_queue(m->scratch, dfa, rx->firstpos); h = t = _create_state_queue(m->scratch, dfa, rx->firstpos);
while(h) { while (h) {
/* pop state off front of the queue */ /* pop state off front of the queue */
dfa = h->s; dfa = h->s;
dfa_bits = h->bits; dfa_bits = h->bits;
@ -256,7 +256,7 @@ static int _calc_states(struct matcher *m, struct rx_node *rx)
} }
} }
log_debug("Lexer built with %d dfa states", count); log_debug("Matcher built with %d dfa states", count);
return 1; return 1;
} }
@ -330,20 +330,20 @@ struct matcher *matcher_create(struct pool *mem,
return NULL; return NULL;
} }
int matcher_run(struct matcher *m, const char *b, const char *e) int matcher_run(struct matcher *m, const char *b)
{ {
struct dfa_state *cs = m->start; struct dfa_state *cs = m->start;
int r = -1; int r = 0;
for (; b != e; b++) { for (; *b; b++) {
if (!(cs = cs->lookup[(int) (unsigned char) *b])) if (!(cs = cs->lookup[(int) (unsigned char) *b]))
break; break;
if (cs->final) if (cs->final && (!r || cs->final > r))
r = cs->final; r = cs->final;
} }
/* subtract 1 to get back to zero index */ /* subtract 1 to get back to zero index */
return (r < 0) ? r : (r - 1); return r - 1;
} }

View File

@ -13,6 +13,6 @@ struct matcher;
struct matcher *matcher_create(struct pool *mem, struct matcher *matcher_create(struct pool *mem,
const char **patterns, int num); const char **patterns, int num);
int matcher_run(struct matcher *m, const char *begin, const char *end); int matcher_run(struct matcher *m, const char *begin);
#endif #endif

View File

@ -22,6 +22,83 @@ struct ttree {
struct node *root; struct node *root;
}; };
struct node **_lookup_single(struct node **c, unsigned int k)
{
while (*c) {
if (k < (*c)->k)
c = &((*c)->l);
else if (k > (*c)->k)
c = &((*c)->r);
else {
c = &((*c)->m);
break;
}
}
return c;
}
void *ttree_lookup(struct ttree *tt, unsigned *key)
{
struct node **c = &tt->root;
int count = tt->klen;
unsigned int k;
while (*c && count) {
k = *key++;
count--;
c = _lookup_single(c, k);
}
return *c ? (*c)->data : NULL;
}
static struct node *_create_node(struct pool *mem, unsigned int k)
{
struct node *n = pool_zalloc(mem, sizeof(*n));
if (n)
n->k = k;
return n;
}
int ttree_insert(struct ttree *tt, unsigned int *key, void *data)
{
struct node **c = &tt->root;
int count = tt->klen;
unsigned int k;
while (*c && count) {
k = *key++;
count--;
c = _lookup_single(c, k);
}
if (!*c) {
count++;
while (count--) {
if (!(*c = _create_node(tt->mem, k))) {
stack;
return 0;
}
k = *key++;
if (count)
c = &((*c)->m);
}
}
(*c)->data = data;
return 1;
}
struct ttree *ttree_create(struct pool *mem, unsigned int klen) struct ttree *ttree_create(struct pool *mem, unsigned int klen)
{ {
struct ttree *tt; struct ttree *tt;
@ -35,95 +112,3 @@ struct ttree *ttree_create(struct pool *mem, unsigned int klen)
tt->mem = mem; tt->mem = mem;
return tt; return tt;
} }
void *ttree_lookup(struct ttree *tt, unsigned *key)
{
struct node *c = tt->root;
int count = tt->klen;
unsigned k = *key++;
while (c) {
if (k < c->k)
c = c->l;
else if (k > c->k)
c = c->r;
else {
if (!--count)
break;
c = c->m;
k = *key++;
}
}
return c ? c->data : 0;
}
void *ttree_insert(struct ttree *tt, unsigned *key, void *data)
{
struct node *c = tt->root, *p = 0;
int count = tt->klen, first = 1;
unsigned k = *key;
void *r = NULL;
while (c) {
p = c;
if (k < c->k)
c = c->l;
else if (k > c->k)
c = c->r;
else {
c = c->m;
if (!--count)
break;
k = *++key;
}
}
if (!count) {
/* key is already in the tree */
r = p->data;
p->data = data;
} else {
/* FIXME: put this in seperate function */
/* insert new chain of nodes */
while (count--) {
k = *key++;
c = pool_alloc(tt->mem, sizeof(*c));
if (!c) {
stack;
return NULL;
}
c->k = k;
c->l = c->m = c->r = c->data = 0;
if (!p)
tt->root = c;
else if (first) {
if (k < p->k)
p->l = c;
else if (k > p->k)
p->r = c;
else
p->m = c;
first = 0;
} else
p->m = c;
p = c;
}
c->data = data;
}
return r;
}

View File

@ -14,6 +14,6 @@ struct ttree;
struct ttree *ttree_create(struct pool *mem, unsigned int klen); struct ttree *ttree_create(struct pool *mem, unsigned int klen);
void *ttree_lookup(struct ttree *tt, unsigned *key); void *ttree_lookup(struct ttree *tt, unsigned *key);
void *ttree_insert(struct ttree *tt, unsigned *key, void *data); int ttree_insert(struct ttree *tt, unsigned *key, void *data);
#endif #endif

View File

@ -0,0 +1,21 @@
#
# Copyright (C) 2001 Sistina Software (UK) Limited
#
# This file is released under the GPL.
#
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
SOURCES=\
rfilter_t.c
TARGETS=\
rfilter_t
include ../../make.tmpl
rfilter_t: rfilter_t.o $(top_srcdir)/lib/liblvm.a
$(CC) -o rfilter_t rfilter_t.o -L$(top_srcdir)/lib -llvm

View File

@ -0,0 +1,84 @@
/*
* Copyright (C) 2001 Sistina Software (UK) Limited.
*
* This file is released under the GPL.
*/
#include "filter-regex.h"
#include "config.h"
#include "log.h"
#include "dbg_malloc.h"
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
int main(int argc, char **argv)
{
struct config_file *cf;
struct config_node *cn;
struct dev_filter *filter;
struct dev_iter *iter;
struct device *dev;
if (argc < 2) {
fprintf(stderr, "Usage : %s <config_file>\n", argv[0]);
exit(1);
}
init_log(stderr);
init_debug(_LOG_DEBUG);
if (!(cf = create_config_file())) {
fprintf(stderr, "couldn't create config file\n");
exit(1);
}
if (!read_config(cf, argv[1])) {
fprintf(stderr, "couldn't read config file\n");
exit(1);
}
if (!(cn = find_config_node(cf->root, "/devices/filter", '/'))) {
fprintf(stderr, "couldn't find filter section\n");
exit(1);
}
if (!dev_cache_init()) {
fprintf(stderr, "couldn't initialise dev_cache_init failed\n");
exit(1);
}
if (!dev_cache_add_dir("/dev")) {
fprintf(stderr, "couldn't add '/dev' to dev_cache\n");
exit(1);
}
if (!(filter = regex_filter_create(cn->v))) {
fprintf(stderr, "couldn't build filter\n");
exit(1);
}
if (!(iter = dev_iter_create(filter))) {
log_err("couldn't create iterator");
exit(1);
}
while ((dev = dev_iter_get(iter)))
printf("%s\n", dev->name);
dev_iter_destroy(iter);
filter->destroy(filter);
dev_cache_exit();
destroy_config_file(cf);
dump_memory();
fin_log();
return 0;
}

View File

@ -0,0 +1,21 @@
devices {
# first match is final, eg. /dev/ide/cdrom
# get's rejected due to the first pattern
filter=["r/cdrom/", # don't touch the music !
"a/hd[a-d][0-9]+/",
"a/ide/",
"a/sd/",
"a/md/",
"a|loop/[0-9]+|", # accept devfs style loop back
"r/loop/", # and reject old style
"a/dasd/",
"a/dac960/",
"a/nbd/",
"a/ida/",
"a/cciss/",
"a/ubd/",
"r/.*/"] # reject all others
}

View File

@ -87,7 +87,7 @@ static void _scan_input(struct matcher *m, char **regex)
if ((ptr = strchr(buffer, '\n'))) if ((ptr = strchr(buffer, '\n')))
*ptr = '\0'; *ptr = '\0';
r = matcher_run(m, buffer, buffer + strlen(buffer)); r = matcher_run(m, buffer);
if (r >= 0) if (r >= 0)
printf("%s : %s\n", buffer, regex[r]); printf("%s : %s\n", buffer, regex[r]);