2 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
3 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
5 * This file is part of LVM2.
7 * This copyrighted material is made available to anyone wishing to use,
8 * modify, copy, or redistribute it subject to the terms and conditions
9 * of the GNU Lesser General Public License v.2.1.
11 * You should have received a copy of the GNU Lesser General Public License
12 * along with this program; if not, write to the Free Software Foundation,
13 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 #include "filter-regex.h"
23 struct dm_regex *engine;
26 static int _extract_pattern(struct dm_pool *mem, const char *pat,
27 char **regex, dm_bitset_t accept, int ix)
32 * is this an accept or reject pattern
36 dm_bit_set(accept, ix);
40 dm_bit_clear(accept, ix);
44 log_info("pattern must begin with 'a' or 'r'");
73 if (!(r = dm_pool_strdup(mem, pat)))
77 * trim the trailing character, having checked it's sep.
79 ptr = r + strlen(r) - 1;
81 log_info("invalid separator at end of regex");
90 static int _build_matcher(struct rfilter *rf, const struct config_value *val)
92 struct dm_pool *scratch;
93 const struct config_value *v;
98 if (!(scratch = dm_pool_create("filter dm_regex", 1024)))
102 * count how many patterns we have.
104 for (v = val; v; v = v->next) {
105 if (v->type != CFG_STRING) {
106 log_error("Filter patterns must be enclosed in quotes.");
114 * allocate space for them
116 if (!(regex = dm_pool_alloc(scratch, sizeof(*regex) * count)))
120 * create the accept/reject bitset
122 rf->accept = dm_bitset_create(rf->mem, count);
125 * fill the array back to front because we
126 * want the opposite precedence to what
129 for (v = val, i = count - 1; v; v = v->next, i--)
130 if (!_extract_pattern(scratch, v->v.str, regex, rf->accept, i)) {
131 log_error("Invalid filter pattern \"%s\".", v->v.str);
138 if (!(rf->engine = dm_regex_create(rf->mem, (const char **) regex,
144 dm_pool_destroy(scratch);
148 static int _accept_p(struct dev_filter *f, struct device *dev)
150 int m, first = 1, rejected = 0;
151 struct rfilter *rf = (struct rfilter *) f->private;
154 dm_list_iterate_items(sl, &dev->aliases) {
155 m = dm_regex_match(rf->engine, sl->str);
158 if (dm_bit(rf->accept, m)) {
160 dev_set_preferred_name(sl, dev);
172 log_debug("%s: Skipping (regex)", dev_name(dev));
175 * pass everything that doesn't match
181 static void _regex_destroy(struct dev_filter *f)
183 struct rfilter *rf = (struct rfilter *) f->private;
186 log_error(INTERNAL_ERROR "Destroying regex filter while in use %u times.", f->use_count);
188 dm_pool_destroy(rf->mem);
191 struct dev_filter *regex_filter_create(const struct config_value *patterns)
193 struct dm_pool *mem = dm_pool_create("filter regex", 10 * 1024);
195 struct dev_filter *f;
200 if (!(rf = dm_pool_alloc(mem, sizeof(*rf))))
205 if (!_build_matcher(rf, patterns))
208 if (!(f = dm_pool_zalloc(mem, sizeof(*f))))
211 f->passes_filter = _accept_p;
212 f->destroy = _regex_destroy;
218 dm_pool_destroy(mem);