LCOV - code coverage report
Current view: top level - lib - parser.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 38 80 47.5 %
Date: 2015-04-12 14:34:49 Functions: 5 9 55.6 %

          Line data    Source code
       1             : /*
       2             :  * lib/parser.c - simple parser for mount, etc. options.
       3             :  *
       4             :  * This source code is licensed under the GNU General Public License,
       5             :  * Version 2.  See the file COPYING for more details.
       6             :  */
       7             : 
       8             : #include <linux/ctype.h>
       9             : #include <linux/types.h>
      10             : #include <linux/export.h>
      11             : #include <linux/parser.h>
      12             : #include <linux/slab.h>
      13             : #include <linux/string.h>
      14             : 
      15             : /**
      16             :  * match_one: - Determines if a string matches a simple pattern
      17             :  * @s: the string to examine for presence of the pattern
      18             :  * @p: the string containing the pattern
      19             :  * @args: array of %MAX_OPT_ARGS &substring_t elements. Used to return match
      20             :  * locations.
      21             :  *
      22             :  * Description: Determines if the pattern @p is present in string @s. Can only
      23             :  * match extremely simple token=arg style patterns. If the pattern is found,
      24             :  * the location(s) of the arguments will be returned in the @args array.
      25             :  */
      26          19 : static int match_one(char *s, const char *p, substring_t args[])
      27             : {
      28             :         char *meta;
      29             :         int argc = 0;
      30             : 
      31          19 :         if (!p)
      32             :                 return 1;
      33             : 
      34             :         while(1) {
      35             :                 int len = -1;
      36          26 :                 meta = strchr(p, '%');
      37          26 :                 if (!meta)
      38           7 :                         return strcmp(p, s) == 0;
      39             : 
      40          19 :                 if (strncmp(p, s, meta-p))
      41             :                         return 0;
      42             : 
      43           7 :                 s += meta - p;
      44           7 :                 p = meta + 1;
      45             : 
      46           7 :                 if (isdigit(*p))
      47           0 :                         len = simple_strtoul(p, (char **) &p, 10);
      48           7 :                 else if (*p == '%') {
      49           0 :                         if (*s++ != '%')
      50             :                                 return 0;
      51           0 :                         p++;
      52           0 :                         continue;
      53             :                 }
      54             : 
      55           7 :                 if (argc >= MAX_OPT_ARGS)
      56             :                         return 0;
      57             : 
      58           7 :                 args[argc].from = s;
      59           7 :                 switch (*p++) {
      60             :                 case 's': {
      61           0 :                         size_t str_len = strlen(s);
      62             : 
      63           0 :                         if (str_len == 0)
      64             :                                 return 0;
      65           0 :                         if (len == -1 || len > str_len)
      66           0 :                                 len = str_len;
      67           0 :                         args[argc].to = s + len;
      68           0 :                         break;
      69             :                 }
      70             :                 case 'd':
      71           0 :                         simple_strtol(s, &args[argc].to, 0);
      72           0 :                         goto num;
      73             :                 case 'u':
      74           3 :                         simple_strtoul(s, &args[argc].to, 0);
      75           3 :                         goto num;
      76             :                 case 'o':
      77           4 :                         simple_strtoul(s, &args[argc].to, 8);
      78           4 :                         goto num;
      79             :                 case 'x':
      80           0 :                         simple_strtoul(s, &args[argc].to, 16);
      81             :                 num:
      82           7 :                         if (args[argc].to == args[argc].from)
      83             :                                 return 0;
      84             :                         break;
      85             :                 default:
      86             :                         return 0;
      87             :                 }
      88           7 :                 s = args[argc].to;
      89           7 :                 argc++;
      90             :         }
      91             : }
      92             : 
      93             : /**
      94             :  * match_token: - Find a token (and optional args) in a string
      95             :  * @s: the string to examine for token/argument pairs
      96             :  * @table: match_table_t describing the set of allowed option tokens and the
      97             :  * arguments that may be associated with them. Must be terminated with a
      98             :  * &struct match_token whose pattern is set to the NULL pointer.
      99             :  * @args: array of %MAX_OPT_ARGS &substring_t elements. Used to return match
     100             :  * locations.
     101             :  *
     102             :  * Description: Detects which if any of a set of token strings has been passed
     103             :  * to it. Tokens can include up to MAX_OPT_ARGS instances of basic c-style
     104             :  * format identifiers which will be taken into account when matching the
     105             :  * tokens, and whose locations will be returned in the @args array.
     106             :  */
     107           7 : int match_token(char *s, const match_table_t table, substring_t args[])
     108             : {
     109             :         const struct match_token *p;
     110             : 
     111           7 :         for (p = table; !match_one(s, p->pattern, args) ; p++)
     112             :                 ;
     113             : 
     114           7 :         return p->token;
     115             : }
     116             : EXPORT_SYMBOL(match_token);
     117             : 
     118             : /**
     119             :  * match_number: scan a number in the given base from a substring_t
     120             :  * @s: substring to be scanned
     121             :  * @result: resulting integer on success
     122             :  * @base: base to use when converting string
     123             :  *
     124             :  * Description: Given a &substring_t and a base, attempts to parse the substring
     125             :  * as a number in that base. On success, sets @result to the integer represented
     126             :  * by the string and returns 0. Returns -ENOMEM, -EINVAL, or -ERANGE on failure.
     127             :  */
     128           7 : static int match_number(substring_t *s, int *result, int base)
     129             : {
     130             :         char *endp;
     131             :         char *buf;
     132             :         int ret;
     133             :         long val;
     134           7 :         size_t len = s->to - s->from;
     135             : 
     136           7 :         buf = kmalloc(len + 1, GFP_KERNEL);
     137           7 :         if (!buf)
     138             :                 return -ENOMEM;
     139           7 :         memcpy(buf, s->from, len);
     140           7 :         buf[len] = '\0';
     141             : 
     142             :         ret = 0;
     143           7 :         val = simple_strtol(buf, &endp, base);
     144           7 :         if (endp == buf)
     145             :                 ret = -EINVAL;
     146             :         else if (val < (long)INT_MIN || val > (long)INT_MAX)
     147             :                 ret = -ERANGE;
     148             :         else
     149           7 :                 *result = (int) val;
     150           7 :         kfree(buf);
     151           7 :         return ret;
     152             : }
     153             : 
     154             : /**
     155             :  * match_int: - scan a decimal representation of an integer from a substring_t
     156             :  * @s: substring_t to be scanned
     157             :  * @result: resulting integer on success
     158             :  *
     159             :  * Description: Attempts to parse the &substring_t @s as a decimal integer. On
     160             :  * success, sets @result to the integer represented by the string and returns 0.
     161             :  * Returns -ENOMEM, -EINVAL, or -ERANGE on failure.
     162             :  */
     163           3 : int match_int(substring_t *s, int *result)
     164             : {
     165           3 :         return match_number(s, result, 0);
     166             : }
     167             : EXPORT_SYMBOL(match_int);
     168             : 
     169             : /**
     170             :  * match_octal: - scan an octal representation of an integer from a substring_t
     171             :  * @s: substring_t to be scanned
     172             :  * @result: resulting integer on success
     173             :  *
     174             :  * Description: Attempts to parse the &substring_t @s as an octal integer. On
     175             :  * success, sets @result to the integer represented by the string and returns
     176             :  * 0. Returns -ENOMEM, -EINVAL, or -ERANGE on failure.
     177             :  */
     178           4 : int match_octal(substring_t *s, int *result)
     179             : {
     180           4 :         return match_number(s, result, 8);
     181             : }
     182             : EXPORT_SYMBOL(match_octal);
     183             : 
     184             : /**
     185             :  * match_hex: - scan a hex representation of an integer from a substring_t
     186             :  * @s: substring_t to be scanned
     187             :  * @result: resulting integer on success
     188             :  *
     189             :  * Description: Attempts to parse the &substring_t @s as a hexadecimal integer.
     190             :  * On success, sets @result to the integer represented by the string and
     191             :  * returns 0. Returns -ENOMEM, -EINVAL, or -ERANGE on failure.
     192             :  */
     193           0 : int match_hex(substring_t *s, int *result)
     194             : {
     195           0 :         return match_number(s, result, 16);
     196             : }
     197             : EXPORT_SYMBOL(match_hex);
     198             : 
     199             : /**
     200             :  * match_wildcard: - parse if a string matches given wildcard pattern
     201             :  * @pattern: wildcard pattern
     202             :  * @str: the string to be parsed
     203             :  *
     204             :  * Description: Parse the string @str to check if matches wildcard
     205             :  * pattern @pattern. The pattern may contain two type wildcardes:
     206             :  *   '*' - matches zero or more characters
     207             :  *   '?' - matches one character
     208             :  * If it's matched, return true, else return false.
     209             :  */
     210           0 : bool match_wildcard(const char *pattern, const char *str)
     211             : {
     212             :         const char *s = str;
     213             :         const char *p = pattern;
     214             :         bool star = false;
     215             : 
     216           0 :         while (*s) {
     217           0 :                 switch (*p) {
     218             :                 case '?':
     219           0 :                         s++;
     220           0 :                         p++;
     221           0 :                         break;
     222             :                 case '*':
     223             :                         star = true;
     224             :                         str = s;
     225           0 :                         if (!*++p)
     226             :                                 return true;
     227             :                         pattern = p;
     228             :                         break;
     229             :                 default:
     230           0 :                         if (*s == *p) {
     231           0 :                                 s++;
     232           0 :                                 p++;
     233             :                         } else {
     234           0 :                                 if (!star)
     235             :                                         return false;
     236           0 :                                 str++;
     237             :                                 s = str;
     238             :                                 p = pattern;
     239             :                         }
     240             :                         break;
     241             :                 }
     242             :         }
     243             : 
     244           0 :         if (*p == '*')
     245           0 :                 ++p;
     246           0 :         return !*p;
     247             : }
     248             : EXPORT_SYMBOL(match_wildcard);
     249             : 
     250             : /**
     251             :  * match_strlcpy: - Copy the characters from a substring_t to a sized buffer
     252             :  * @dest: where to copy to
     253             :  * @src: &substring_t to copy
     254             :  * @size: size of destination buffer
     255             :  *
     256             :  * Description: Copy the characters in &substring_t @src to the
     257             :  * c-style string @dest.  Copy no more than @size - 1 characters, plus
     258             :  * the terminating NUL.  Return length of @src.
     259             :  */
     260           0 : size_t match_strlcpy(char *dest, const substring_t *src, size_t size)
     261             : {
     262           0 :         size_t ret = src->to - src->from;
     263             : 
     264           0 :         if (size) {
     265           0 :                 size_t len = ret >= size ? size - 1 : ret;
     266           0 :                 memcpy(dest, src->from, len);
     267           0 :                 dest[len] = '\0';
     268             :         }
     269           0 :         return ret;
     270             : }
     271             : EXPORT_SYMBOL(match_strlcpy);
     272             : 
     273             : /**
     274             :  * match_strdup: - allocate a new string with the contents of a substring_t
     275             :  * @s: &substring_t to copy
     276             :  *
     277             :  * Description: Allocates and returns a string filled with the contents of
     278             :  * the &substring_t @s. The caller is responsible for freeing the returned
     279             :  * string with kfree().
     280             :  */
     281           0 : char *match_strdup(const substring_t *s)
     282             : {
     283           0 :         size_t sz = s->to - s->from + 1;
     284             :         char *p = kmalloc(sz, GFP_KERNEL);
     285           0 :         if (p)
     286           0 :                 match_strlcpy(p, s, sz);
     287           0 :         return p;
     288             : }
     289             : EXPORT_SYMBOL(match_strdup);

Generated by: LCOV version 1.11