LCOV - code coverage report
Current view: top level - lib - cmdline.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 32 88 36.4 %
Date: 2023-07-19 18:55:55 Functions: 3 6 50.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-only
       2             : /*
       3             :  * linux/lib/cmdline.c
       4             :  * Helper functions generally used for parsing kernel command line
       5             :  * and module options.
       6             :  *
       7             :  * Code and copyrights come from init/main.c and arch/i386/kernel/setup.c.
       8             :  *
       9             :  * GNU Indent formatting options for this file: -kr -i8 -npsl -pcs
      10             :  */
      11             : 
      12             : #include <linux/export.h>
      13             : #include <linux/kernel.h>
      14             : #include <linux/string.h>
      15             : #include <linux/ctype.h>
      16             : 
      17             : /*
      18             :  *      If a hyphen was found in get_option, this will handle the
      19             :  *      range of numbers, M-N.  This will expand the range and insert
      20             :  *      the values[M, M+1, ..., N] into the ints array in get_options.
      21             :  */
      22             : 
      23           0 : static int get_range(char **str, int *pint, int n)
      24             : {
      25             :         int x, inc_counter, upper_range;
      26             : 
      27           0 :         (*str)++;
      28           0 :         upper_range = simple_strtol((*str), NULL, 0);
      29           0 :         inc_counter = upper_range - *pint;
      30           0 :         for (x = *pint; n && x < upper_range; x++, n--)
      31           0 :                 *pint++ = x;
      32           0 :         return inc_counter;
      33             : }
      34             : 
      35             : /**
      36             :  *      get_option - Parse integer from an option string
      37             :  *      @str: option string
      38             :  *      @pint: (optional output) integer value parsed from @str
      39             :  *
      40             :  *      Read an int from an option string; if available accept a subsequent
      41             :  *      comma as well.
      42             :  *
      43             :  *      When @pint is NULL the function can be used as a validator of
      44             :  *      the current option in the string.
      45             :  *
      46             :  *      Return values:
      47             :  *      0 - no int in string
      48             :  *      1 - int found, no subsequent comma
      49             :  *      2 - int found including a subsequent comma
      50             :  *      3 - hyphen found to denote a range
      51             :  *
      52             :  *      Leading hyphen without integer is no integer case, but we consume it
      53             :  *      for the sake of simplification.
      54             :  */
      55             : 
      56           0 : int get_option(char **str, int *pint)
      57             : {
      58           0 :         char *cur = *str;
      59             :         int value;
      60             : 
      61           0 :         if (!cur || !(*cur))
      62             :                 return 0;
      63           0 :         if (*cur == '-')
      64           0 :                 value = -simple_strtoull(++cur, str, 0);
      65             :         else
      66           0 :                 value = simple_strtoull(cur, str, 0);
      67           0 :         if (pint)
      68           0 :                 *pint = value;
      69           0 :         if (cur == *str)
      70             :                 return 0;
      71           0 :         if (**str == ',') {
      72           0 :                 (*str)++;
      73           0 :                 return 2;
      74             :         }
      75           0 :         if (**str == '-')
      76             :                 return 3;
      77             : 
      78           0 :         return 1;
      79             : }
      80             : EXPORT_SYMBOL(get_option);
      81             : 
      82             : /**
      83             :  *      get_options - Parse a string into a list of integers
      84             :  *      @str: String to be parsed
      85             :  *      @nints: size of integer array
      86             :  *      @ints: integer array (must have room for at least one element)
      87             :  *
      88             :  *      This function parses a string containing a comma-separated
      89             :  *      list of integers, a hyphen-separated range of _positive_ integers,
      90             :  *      or a combination of both.  The parse halts when the array is
      91             :  *      full, or when no more numbers can be retrieved from the
      92             :  *      string.
      93             :  *
      94             :  *      When @nints is 0, the function just validates the given @str and
      95             :  *      returns the amount of parseable integers as described below.
      96             :  *
      97             :  *      Returns:
      98             :  *
      99             :  *      The first element is filled by the number of collected integers
     100             :  *      in the range. The rest is what was parsed from the @str.
     101             :  *
     102             :  *      Return value is the character in the string which caused
     103             :  *      the parse to end (typically a null terminator, if @str is
     104             :  *      completely parseable).
     105             :  */
     106             : 
     107           0 : char *get_options(const char *str, int nints, int *ints)
     108             : {
     109           0 :         bool validate = (nints == 0);
     110           0 :         int res, i = 1;
     111             : 
     112           0 :         while (i < nints || validate) {
     113           0 :                 int *pint = validate ? ints : ints + i;
     114             : 
     115           0 :                 res = get_option((char **)&str, pint);
     116           0 :                 if (res == 0)
     117             :                         break;
     118           0 :                 if (res == 3) {
     119           0 :                         int n = validate ? 0 : nints - i;
     120             :                         int range_nums;
     121             : 
     122           0 :                         range_nums = get_range((char **)&str, pint, n);
     123           0 :                         if (range_nums < 0)
     124             :                                 break;
     125             :                         /*
     126             :                          * Decrement the result by one to leave out the
     127             :                          * last number in the range.  The next iteration
     128             :                          * will handle the upper number in the range
     129             :                          */
     130           0 :                         i += (range_nums - 1);
     131             :                 }
     132           0 :                 i++;
     133           0 :                 if (res == 1)
     134             :                         break;
     135             :         }
     136           0 :         ints[0] = i - 1;
     137           0 :         return (char *)str;
     138             : }
     139             : EXPORT_SYMBOL(get_options);
     140             : 
     141             : /**
     142             :  *      memparse - parse a string with mem suffixes into a number
     143             :  *      @ptr: Where parse begins
     144             :  *      @retptr: (output) Optional pointer to next char after parse completes
     145             :  *
     146             :  *      Parses a string into a number.  The number stored at @ptr is
     147             :  *      potentially suffixed with K, M, G, T, P, E.
     148             :  */
     149             : 
     150           5 : unsigned long long memparse(const char *ptr, char **retptr)
     151             : {
     152             :         char *endptr;   /* local pointer to end of parsed string */
     153             : 
     154           5 :         unsigned long long ret = simple_strtoull(ptr, &endptr, 0);
     155             : 
     156           5 :         switch (*endptr) {
     157             :         case 'E':
     158             :         case 'e':
     159           0 :                 ret <<= 10;
     160             :                 fallthrough;
     161             :         case 'P':
     162             :         case 'p':
     163           0 :                 ret <<= 10;
     164             :                 fallthrough;
     165             :         case 'T':
     166             :         case 't':
     167           0 :                 ret <<= 10;
     168             :                 fallthrough;
     169             :         case 'G':
     170             :         case 'g':
     171           5 :                 ret <<= 10;
     172             :                 fallthrough;
     173             :         case 'M':
     174             :         case 'm':
     175           5 :                 ret <<= 10;
     176             :                 fallthrough;
     177             :         case 'K':
     178             :         case 'k':
     179           5 :                 ret <<= 10;
     180           5 :                 endptr++;
     181             :                 fallthrough;
     182             :         default:
     183             :                 break;
     184             :         }
     185             : 
     186           5 :         if (retptr)
     187           5 :                 *retptr = endptr;
     188             : 
     189           5 :         return ret;
     190             : }
     191             : EXPORT_SYMBOL(memparse);
     192             : 
     193             : /**
     194             :  *      parse_option_str - Parse a string and check an option is set or not
     195             :  *      @str: String to be parsed
     196             :  *      @option: option name
     197             :  *
     198             :  *      This function parses a string containing a comma-separated list of
     199             :  *      strings like a=b,c.
     200             :  *
     201             :  *      Return true if there's such option in the string, or return false.
     202             :  */
     203          45 : bool parse_option_str(const char *str, const char *option)
     204             : {
     205          90 :         while (*str) {
     206           0 :                 if (!strncmp(str, option, strlen(option))) {
     207           0 :                         str += strlen(option);
     208           0 :                         if (!*str || *str == ',')
     209             :                                 return true;
     210             :                 }
     211             : 
     212           0 :                 while (*str && *str != ',')
     213           0 :                         str++;
     214             : 
     215           0 :                 if (*str == ',')
     216           0 :                         str++;
     217             :         }
     218             : 
     219             :         return false;
     220             : }
     221             : 
     222             : /*
     223             :  * Parse a string to get a param value pair.
     224             :  * You can use " around spaces, but can't escape ".
     225             :  * Hyphens and underscores equivalent in parameter names.
     226             :  */
     227          50 : char *next_arg(char *args, char **param, char **val)
     228             : {
     229          50 :         unsigned int i, equals = 0;
     230          50 :         int in_quote = 0, quoted = 0;
     231             : 
     232          50 :         if (*args == '"') {
     233           0 :                 args++;
     234           0 :                 in_quote = 1;
     235           0 :                 quoted = 1;
     236             :         }
     237             : 
     238         640 :         for (i = 0; args[i]; i++) {
     239         630 :                 if (isspace(args[i]) && !in_quote)
     240             :                         break;
     241         590 :                 if (equals == 0) {
     242         450 :                         if (args[i] == '=')
     243          50 :                                 equals = i;
     244             :                 }
     245         590 :                 if (args[i] == '"')
     246           0 :                         in_quote = !in_quote;
     247             :         }
     248             : 
     249          50 :         *param = args;
     250          50 :         if (!equals)
     251           0 :                 *val = NULL;
     252             :         else {
     253          50 :                 args[equals] = '\0';
     254          50 :                 *val = args + equals + 1;
     255             : 
     256             :                 /* Don't include quotes in value. */
     257          50 :                 if (**val == '"') {
     258           0 :                         (*val)++;
     259           0 :                         if (args[i-1] == '"')
     260           0 :                                 args[i-1] = '\0';
     261             :                 }
     262             :         }
     263          50 :         if (quoted && i > 0 && args[i-1] == '"')
     264           0 :                 args[i-1] = '\0';
     265             : 
     266          50 :         if (args[i]) {
     267          40 :                 args[i] = '\0';
     268          40 :                 args += i + 1;
     269             :         } else
     270             :                 args += i;
     271             : 
     272             :         /* Chew up trailing spaces. */
     273          50 :         return skip_spaces(args);
     274             : }
     275             : EXPORT_SYMBOL(next_arg);

Generated by: LCOV version 1.14