LCOV - code coverage report
Current view: top level - misc/kabi/lvm2.git/lib/filters - filter-regex.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 59 85 69.4 %
Date: 2010-04-13 Functions: 5 5 100.0 %
Branches: 23 43 53.5 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
       3                 :            :  * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
       4                 :            :  *
       5                 :            :  * This file is part of LVM2.
       6                 :            :  *
       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.
      10                 :            :  *
      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
      14                 :            :  */
      15                 :            : 
      16                 :            : #include "lib.h"
      17                 :            : #include "filter-regex.h"
      18                 :            : #include "device.h"
      19                 :            : 
      20                 :            : struct rfilter {
      21                 :            :         struct dm_pool *mem;
      22                 :            :         dm_bitset_t accept;
      23                 :            :         struct dm_regex *engine;
      24                 :            : };
      25                 :            : 
      26                 :        312 : static int _extract_pattern(struct dm_pool *mem, const char *pat,
      27                 :            :                             char **regex, dm_bitset_t accept, int ix)
      28                 :            : {
      29                 :            :         char sep, *r, *ptr;
      30                 :            : 
      31                 :            :         /*
      32                 :            :          * is this an accept or reject pattern
      33                 :            :          */
      34      [ +  +  - ]:        312 :         switch (*pat) {
      35                 :            :         case 'a':
      36                 :        309 :                 dm_bit_set(accept, ix);
      37                 :        309 :                 break;
      38                 :            : 
      39                 :            :         case 'r':
      40                 :          3 :                 dm_bit_clear(accept, ix);
      41                 :          3 :                 break;
      42                 :            : 
      43                 :            :         default:
      44                 :          0 :                 log_info("pattern must begin with 'a' or 'r'");
      45                 :          0 :                 return 0;
      46                 :            :         }
      47                 :        312 :         pat++;
      48                 :            : 
      49                 :            :         /*
      50                 :            :          * get the separator
      51                 :            :          */
      52   [ -  -  -  + ]:        312 :         switch (*pat) {
      53                 :            :         case '(':
      54                 :          0 :                 sep = ')';
      55                 :          0 :                 break;
      56                 :            : 
      57                 :            :         case '[':
      58                 :          0 :                 sep = ']';
      59                 :          0 :                 break;
      60                 :            : 
      61                 :            :         case '{':
      62                 :          0 :                 sep = '}';
      63                 :          0 :                 break;
      64                 :            : 
      65                 :            :         default:
      66                 :        312 :                 sep = *pat;
      67                 :            :         }
      68                 :        312 :         pat++;
      69                 :            : 
      70                 :            :         /*
      71                 :            :          * copy the regex
      72                 :            :          */
      73         [ -  + ]:        312 :         if (!(r = dm_pool_strdup(mem, pat)))
      74                 :          0 :                 return_0;
      75                 :            : 
      76                 :            :         /*
      77                 :            :          * trim the trailing character, having checked it's sep.
      78                 :            :          */
      79                 :        312 :         ptr = r + strlen(r) - 1;
      80         [ -  + ]:        312 :         if (*ptr != sep) {
      81                 :          0 :                 log_info("invalid separator at end of regex");
      82                 :          0 :                 return 0;
      83                 :            :         }
      84                 :        312 :         *ptr = '\0';
      85                 :            : 
      86                 :        312 :         regex[ix] = r;
      87                 :        312 :         return 1;
      88                 :            : }
      89                 :            : 
      90                 :          3 : static int _build_matcher(struct rfilter *rf, struct config_value *val)
      91                 :            : {
      92                 :            :         struct dm_pool *scratch;
      93                 :            :         struct config_value *v;
      94                 :            :         char **regex;
      95                 :          3 :         unsigned count = 0;
      96                 :          3 :         int i, r = 0;
      97                 :            : 
      98         [ -  + ]:          3 :         if (!(scratch = dm_pool_create("filter dm_regex", 1024)))
      99                 :          0 :                 return_0;
     100                 :            : 
     101                 :            :         /*
     102                 :            :          * count how many patterns we have.
     103                 :            :          */
     104         [ +  + ]:        315 :         for (v = val; v; v = v->next) {
     105         [ -  + ]:        312 :                 if (v->type != CFG_STRING) {
     106                 :          0 :                         log_error("filter patterns must be enclosed in quotes");
     107                 :          0 :                         goto out;
     108                 :            :                 }
     109                 :            : 
     110                 :        312 :                 count++;
     111                 :            :         }
     112                 :            : 
     113                 :            :         /*
     114                 :            :          * allocate space for them
     115                 :            :          */
     116         [ -  + ]:          3 :         if (!(regex = dm_pool_alloc(scratch, sizeof(*regex) * count)))
     117                 :          0 :                 goto_out;
     118                 :            : 
     119                 :            :         /*
     120                 :            :          * create the accept/reject bitset
     121                 :            :          */
     122                 :          3 :         rf->accept = dm_bitset_create(rf->mem, count);
     123                 :            : 
     124                 :            :         /*
     125                 :            :          * fill the array back to front because we
     126                 :            :          * want the opposite precedence to what
     127                 :            :          * the matcher gives.
     128                 :            :          */
     129         [ +  + ]:        315 :         for (v = val, i = count - 1; v; v = v->next, i--)
     130         [ -  + ]:        312 :                 if (!_extract_pattern(scratch, v->v.str, regex, rf->accept, i)) {
     131                 :          0 :                         log_error("invalid filter pattern");
     132                 :          0 :                         goto out;
     133                 :            :                 }
     134                 :            : 
     135                 :            :         /*
     136                 :            :          * build the matcher.
     137                 :            :          */
     138         [ -  + ]:          3 :         if (!(rf->engine = dm_regex_create(rf->mem, (const char **) regex,
     139                 :            :                                            count)))
     140                 :          0 :                 stack;
     141                 :          3 :         r = 1;
     142                 :            : 
     143                 :            :       out:
     144                 :          3 :         dm_pool_destroy(scratch);
     145                 :          3 :         return r;
     146                 :            : }
     147                 :            : 
     148                 :         39 : static int _accept_p(struct dev_filter *f, struct device *dev)
     149                 :            : {
     150                 :         39 :         int m, first = 1, rejected = 0;
     151                 :         39 :         struct rfilter *rf = (struct rfilter *) f->private;
     152                 :            :         struct str_list *sl;
     153                 :            : 
     154         [ +  + ]:        160 :         dm_list_iterate_items(sl, &dev->aliases) {
     155                 :        121 :                 m = dm_regex_match(rf->engine, sl->str);
     156                 :            : 
     157         [ +  - ]:        121 :                 if (m >= 0) {
     158         [ -  + ]:        121 :                         if (dm_bit(rf->accept, m)) {
     159         [ #  # ]:          0 :                                 if (!first)
     160                 :          0 :                                         dev_set_preferred_name(sl, dev);
     161                 :            : 
     162                 :          0 :                                 return 1;
     163                 :            :                         }
     164                 :            : 
     165                 :        121 :                         rejected = 1;
     166                 :            :                 }
     167                 :            : 
     168                 :        121 :                 first = 0;
     169                 :            :         }
     170                 :            : 
     171         [ +  - ]:         39 :         if (rejected)
     172                 :         39 :                 log_debug("%s: Skipping (regex)", dev_name(dev));
     173                 :            : 
     174                 :            :         /*
     175                 :            :          * pass everything that doesn't match
     176                 :            :          * anything.
     177                 :            :          */
     178                 :         39 :         return !rejected;
     179                 :            : }
     180                 :            : 
     181                 :          3 : static void _regex_destroy(struct dev_filter *f)
     182                 :            : {
     183                 :          3 :         struct rfilter *rf = (struct rfilter *) f->private;
     184                 :          3 :         dm_pool_destroy(rf->mem);
     185                 :          3 : }
     186                 :            : 
     187                 :          3 : struct dev_filter *regex_filter_create(struct config_value *patterns)
     188                 :            : {
     189                 :          3 :         struct dm_pool *mem = dm_pool_create("filter regex", 10 * 1024);
     190                 :            :         struct rfilter *rf;
     191                 :            :         struct dev_filter *f;
     192                 :            : 
     193         [ -  + ]:          3 :         if (!mem)
     194                 :          0 :                 return_NULL;
     195                 :            : 
     196         [ -  + ]:          3 :         if (!(rf = dm_pool_alloc(mem, sizeof(*rf))))
     197                 :          0 :                 goto_bad;
     198                 :            : 
     199                 :          3 :         rf->mem = mem;
     200                 :            : 
     201         [ -  + ]:          3 :         if (!_build_matcher(rf, patterns))
     202                 :          0 :                 goto_bad;
     203                 :            : 
     204         [ -  + ]:          3 :         if (!(f = dm_pool_zalloc(mem, sizeof(*f))))
     205                 :          0 :                 goto_bad;
     206                 :            : 
     207                 :          3 :         f->passes_filter = _accept_p;
     208                 :          3 :         f->destroy = _regex_destroy;
     209                 :          3 :         f->private = rf;
     210                 :          3 :         return f;
     211                 :            : 
     212                 :            :       bad:
     213                 :          0 :         dm_pool_destroy(mem);
     214                 :          3 :         return NULL;
     215                 :            : }

Generated by: LCOV version 1.8