diff --git a/include/.symlinks b/include/.symlinks index 6746e7365..a30c92b2e 100644 --- a/include/.symlinks +++ b/include/.symlinks @@ -7,8 +7,9 @@ ../lib/device/dev-cache.h ../lib/device/device.h ../lib/display/display.h -../lib/filters/filter.h +../lib/filters/filter-persistent.h ../lib/filters/filter-regex.h +../lib/filters/filter.h ../lib/format1/format1.h ../lib/log/log.h ../lib/metadata/metadata.h diff --git a/lib/Makefile.in b/lib/Makefile.in index 8fc245d58..58af73cc8 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -16,9 +16,10 @@ SOURCES=\ device/dev-cache.c \ device/dev-io.c \ device/device.c \ + filters/filter-persistent.c \ + filters/filter-regex.c \ display/display.c \ filters/filter.c \ - filters/filter-regex.c \ format1/disk-rep.c \ format1/format1.c \ format1/import-export.c \ @@ -28,8 +29,8 @@ SOURCES=\ metadata/metadata.c \ mm/dbg_malloc.c \ mm/pool.c \ - regex/parse_rx.c \ regex/matcher.c \ + regex/parse_rx.c \ regex/ttree.c \ uuid/uuid.c diff --git a/lib/datastruct/hash.c b/lib/datastruct/hash.c index 554b9dd12..002ff7fbb 100644 --- a/lib/datastruct/hash.c +++ b/lib/datastruct/hash.c @@ -127,7 +127,7 @@ static inline struct hash_node **_find(struct hash_table *t, const char *key) return c; } -char *hash_lookup(struct hash_table *t, const char *key) +void *hash_lookup(struct hash_table *t, const char *key) { struct hash_node **c = _find(t, key); return *c ? (*c)->data : 0; @@ -181,6 +181,11 @@ void hash_iterate(struct hash_table *t, iterate_fn f) f(c->data); } +char *hash_get_key(struct hash_table *t, struct hash_node *n) +{ + return n->key; +} + void *hash_get_data(struct hash_table *t, struct hash_node *n) { return n->data; diff --git a/lib/datastruct/hash.h b/lib/datastruct/hash.h index 17024afb8..bd0c4eba2 100644 --- a/lib/datastruct/hash.h +++ b/lib/datastruct/hash.h @@ -15,13 +15,14 @@ typedef void (*iterate_fn)(void *data); struct hash_table *hash_create(unsigned size_hint); void hash_destroy(struct hash_table *t); -char *hash_lookup(struct hash_table *t, const char *key); +void *hash_lookup(struct hash_table *t, const char *key); int hash_insert(struct hash_table *t, const char *key, void *data); void hash_remove(struct hash_table *t, const char *key); unsigned hash_get_num_entries(struct hash_table *t); void hash_iterate(struct hash_table *t, iterate_fn f); +char *hash_get_key(struct hash_table *t, struct hash_node *n); void *hash_get_data(struct hash_table *t, struct hash_node *n); struct hash_node *hash_get_first(struct hash_table *t); struct hash_node *hash_get_next(struct hash_table *t, struct hash_node *n); diff --git a/lib/filters/filter-persistent.c b/lib/filters/filter-persistent.c new file mode 100644 index 000000000..b236e3be9 --- /dev/null +++ b/lib/filters/filter-persistent.c @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2001 Sistina Software (UK) Limited. + * + * This file is released under the GPL. + */ + +#include "config.h" +#include "dev-cache.h" +#include "hash.h" +#include "dbg_malloc.h" +#include "log.h" +#include "filter-persistent.h" + +#include +#include +#include +#include + +struct pfilter { + char *file; + struct hash_table *devices; +}; + +/* + * entries in the table can be in one of these + * states. + */ +#define PF_UNCHECKED ((void *) 1) +#define PF_CHECKED ((void *) 2) + +int _init_hash(struct pfilter *pf) +{ + if (pf->devices) + hash_destroy(pf->devices); + + pf->devices = hash_create(128); + return pf ? 1 : 0; +} + +int _load(struct pfilter *pf) +{ + int r = 0; + struct config_file *cf; + struct config_node *cn; + struct config_value *cv; + + if (!(cf = create_config_file())) { + stack; + return 0; + } + + if (!read_config(cf, pf->file)) { + stack; + goto out; + } + + if (!(cn = find_config_node(cf->root, "/valid_devices", '/'))) { + log_info("couldn't find 'valid_devices' array in '%s'", + pf->file); + goto out; + } + + /* + * iterate through the array, adding + * devices as we go. + */ + for (cv = cn->v; cv; cv = cv->next) { + if (cv->type != CFG_STRING) { + log_info("valid_devices array contains a value " + "which is not a string ... ignoring"); + continue; + } + + if (!hash_insert(pf->devices, cv->v.str, PF_UNCHECKED)) + log_info("couldn't add '%s' to filter ... ignoring", + cv->v.str); + } + r = 1; + + out: + destroy_config_file(cf); + return r; +} + +int _dump(struct pfilter *pf) +{ + int first = 1; + struct hash_node *n; + FILE *fp = fopen(pf->file, "w"); + + if (!fp) { + log_info("Couldn't open '%s' for to hold valid devices.", + pf->file); + return 0; + } + + fprintf(fp, "# This file is automatically maintained by lvm.\n\n"); + fprintf(fp, "valid_devices=[\n"); + + for (n = hash_get_first(pf->devices); n; + n = hash_get_next(pf->devices, n)) { + if (!first) + fprintf(fp, ",\n"); + else + first = 0; + + fprintf(fp, "\t\"%s\"", hash_get_key(pf->devices, n)); + } + + fprintf(fp, "\n]\n"); + fclose(fp); + return 1; +} + +int _check(const char *path) +{ + int fd = open(path, O_RDONLY), r = 0; + + if (fd >= 0) + r = 1; + + close(fd); + return r; +} + +int _init_valid_p(struct dev_filter *f, struct device *dev) +{ + struct pfilter *pf = (struct pfilter *) f->private; + void *l = hash_lookup(pf->devices, dev->name); + + if (l) + return 1; + + if (_check(dev->name)) { + hash_insert(pf->devices, dev->name, PF_CHECKED); + return 1; + } + + return 0; +} + +int _valid_p(struct dev_filter *f, struct device *dev) +{ + struct pfilter *pf = (struct pfilter *) f->private; + void *l = hash_lookup(pf->devices, dev->name); + + if (!l) + return 0; + + if (l == PF_UNCHECKED && !_check(dev->name)) { + hash_remove(pf->devices, dev->name); + return 0; + } + + return 1; +} + +void _destroy(struct dev_filter *f) +{ + struct pfilter *pf = (struct pfilter *) f->private; + + _dump(pf); + hash_destroy(pf->devices); + dbg_free(pf->file); + dbg_free(pf); + dbg_free(f); +} + +struct dev_filter *persistent_filter_create(const char *file, int init) +{ + struct pfilter *pf; + struct dev_filter *f = NULL; + + if (!(pf = dbg_malloc(sizeof(*pf)))) { + stack; + return NULL; + } + memset(pf, 0, sizeof(*pf)); + + if (!(pf->file = dbg_malloc(strlen(file) + 1))) { + stack; + goto bad; + } + strcpy(pf->file, file); + + if (!(_init_hash(pf))) { + log_err("Couldn't create hash table for persistent filter."); + goto bad; + } + + if (!init) + _load(pf); + + if (!(f = dbg_malloc(sizeof(*f)))) { + stack; + goto bad; + } + + f->passes_filter = init ? _init_valid_p : _valid_p; + f->destroy = _destroy; + f->private = pf; + + return f; + + bad: + dbg_free(pf->file); + if (pf->devices) + hash_destroy(pf->devices); + dbg_free(pf); + dbg_free(f); + return NULL; +} + diff --git a/lib/filters/filter-persistent.h b/lib/filters/filter-persistent.h new file mode 100644 index 000000000..8f445762b --- /dev/null +++ b/lib/filters/filter-persistent.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2001 Sistina Software (UK) Limited. + * + * This file is released under the GPL. + */ + +#ifndef _LVM_FILTER_PERSISTENT_H +#define _LVM_FILTER_PERSISTENT_h + +#include "dev-cache.h" + +struct dev_filter *persistent_filter_create(const char *file, int init); + +#endif diff --git a/old-tests/filters/Makefile.in b/old-tests/filters/Makefile.in index 35fee47d1..036cb90c6 100644 --- a/old-tests/filters/Makefile.in +++ b/old-tests/filters/Makefile.in @@ -9,13 +9,18 @@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ SOURCES=\ - rfilter_t.c + rfilter_t.c \ + pfilter_t.c TARGETS=\ - rfilter_t + rfilter_t \ + pfilter_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 +pfilter_t: pfilter_t.o $(top_srcdir)/lib/liblvm.a + $(CC) -o pfilter_t pfilter_t.o -L$(top_srcdir)/lib -llvm + diff --git a/old-tests/filters/pfilter_t.c b/old-tests/filters/pfilter_t.c new file mode 100644 index 000000000..d03e4f8a4 --- /dev/null +++ b/old-tests/filters/pfilter_t.c @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2001 Sistina Software (UK) Limited. + * + * This file is released under the GPL. + */ + +#include "filter-persistent.h" +#include "log.h" +#include "dbg_malloc.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + struct dev_filter *filter; + struct dev_iter *iter; + struct device *dev; + + if (argc > 2) { + fprintf(stderr, "Usage : %s \n", argv[0]); + exit(1); + } + + init_log(stderr); + init_debug(_LOG_DEBUG); + + 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 = persistent_filter_create("./pfilter.cfg", 1))) { + 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(); + + dump_memory(); + fin_log(); + return 0; +} +