Branch data 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: (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 : : * Return values: 44 : : * 0 - no int in string 45 : : * 1 - int found, no subsequent comma 46 : : * 2 - int found including a subsequent comma 47 : : * 3 - hyphen found to denote a range 48 : : */ 49 : : 50 : 1 : int get_option(char **str, int *pint) 51 : : { 52 : 1 : char *cur = *str; 53 : : 54 : 1 : if (!cur || !(*cur)) 55 : : return 0; 56 : 1 : *pint = simple_strtol(cur, str, 0); 57 : 1 : if (cur == *str) 58 : : return 0; 59 : 1 : if (**str == ',') { 60 : 0 : (*str)++; 61 : 0 : return 2; 62 : : } 63 : 1 : if (**str == '-') 64 : : return 3; 65 : : 66 : 1 : return 1; 67 : : } 68 : : EXPORT_SYMBOL(get_option); 69 : : 70 : : /** 71 : : * get_options - Parse a string into a list of integers 72 : : * @str: String to be parsed 73 : : * @nints: size of integer array 74 : : * @ints: integer array 75 : : * 76 : : * This function parses a string containing a comma-separated 77 : : * list of integers, a hyphen-separated range of _positive_ integers, 78 : : * or a combination of both. The parse halts when the array is 79 : : * full, or when no more numbers can be retrieved from the 80 : : * string. 81 : : * 82 : : * Return value is the character in the string which caused 83 : : * the parse to end (typically a null terminator, if @str is 84 : : * completely parseable). 85 : : */ 86 : : 87 : 0 : char *get_options(const char *str, int nints, int *ints) 88 : : { 89 : : int res, i = 1; 90 : : 91 : 0 : while (i < nints) { 92 : 0 : res = get_option((char **)&str, ints + i); 93 : 0 : if (res == 0) 94 : : break; 95 : 0 : if (res == 3) { 96 : : int range_nums; 97 : 0 : range_nums = get_range((char **)&str, ints + i, nints - i); 98 : 0 : if (range_nums < 0) 99 : : break; 100 : : /* 101 : : * Decrement the result by one to leave out the 102 : : * last number in the range. The next iteration 103 : : * will handle the upper number in the range 104 : : */ 105 : 0 : i += (range_nums - 1); 106 : : } 107 : 0 : i++; 108 : 0 : if (res == 1) 109 : : break; 110 : : } 111 : 0 : ints[0] = i - 1; 112 : 0 : return (char *)str; 113 : : } 114 : : EXPORT_SYMBOL(get_options); 115 : : 116 : : /** 117 : : * memparse - parse a string with mem suffixes into a number 118 : : * @ptr: Where parse begins 119 : : * @retptr: (output) Optional pointer to next char after parse completes 120 : : * 121 : : * Parses a string into a number. The number stored at @ptr is 122 : : * potentially suffixed with K, M, G, T, P, E. 123 : : */ 124 : : 125 : 3 : unsigned long long memparse(const char *ptr, char **retptr) 126 : : { 127 : : char *endptr; /* local pointer to end of parsed string */ 128 : : 129 : 3 : unsigned long long ret = simple_strtoull(ptr, &endptr, 0); 130 : : 131 : 3 : switch (*endptr) { 132 : : case 'E': 133 : : case 'e': 134 : 0 : ret <<= 10; 135 : : /* fall through */ 136 : : case 'P': 137 : : case 'p': 138 : 0 : ret <<= 10; 139 : : /* fall through */ 140 : : case 'T': 141 : : case 't': 142 : 0 : ret <<= 10; 143 : : /* fall through */ 144 : : case 'G': 145 : : case 'g': 146 : 0 : ret <<= 10; 147 : : /* fall through */ 148 : : case 'M': 149 : : case 'm': 150 : 2 : ret <<= 10; 151 : : /* fall through */ 152 : : case 'K': 153 : : case 'k': 154 : 2 : ret <<= 10; 155 : 2 : endptr++; 156 : : default: 157 : : break; 158 : : } 159 : : 160 : 3 : if (retptr) 161 : 3 : *retptr = endptr; 162 : : 163 : 3 : return ret; 164 : : } 165 : : EXPORT_SYMBOL(memparse); 166 : : 167 : : /** 168 : : * parse_option_str - Parse a string and check an option is set or not 169 : : * @str: String to be parsed 170 : : * @option: option name 171 : : * 172 : : * This function parses a string containing a comma-separated list of 173 : : * strings like a=b,c. 174 : : * 175 : : * Return true if there's such option in the string, or return false. 176 : : */ 177 : 3 : bool parse_option_str(const char *str, const char *option) 178 : : { 179 : 3 : while (*str) { 180 : 0 : if (!strncmp(str, option, strlen(option))) { 181 : 0 : str += strlen(option); 182 : 0 : if (!*str || *str == ',') 183 : : return true; 184 : : } 185 : : 186 : 0 : while (*str && *str != ',') 187 : 0 : str++; 188 : : 189 : 0 : if (*str == ',') 190 : 0 : str++; 191 : : } 192 : : 193 : : return false; 194 : : } 195 : : 196 : : /* 197 : : * Parse a string to get a param value pair. 198 : : * You can use " around spaces, but can't escape ". 199 : : * Hyphens and underscores equivalent in parameter names. 200 : : */ 201 : 3 : char *next_arg(char *args, char **param, char **val) 202 : : { 203 : : unsigned int i, equals = 0; 204 : : int in_quote = 0, quoted = 0; 205 : : char *next; 206 : : 207 : 3 : if (*args == '"') { 208 : 0 : args++; 209 : : in_quote = 1; 210 : : quoted = 1; 211 : : } 212 : : 213 : 3 : for (i = 0; args[i]; i++) { 214 : 3 : if (isspace(args[i]) && !in_quote) 215 : : break; 216 : 3 : if (equals == 0) { 217 : 3 : if (args[i] == '=') 218 : : equals = i; 219 : : } 220 : 3 : if (args[i] == '"') 221 : 0 : in_quote = !in_quote; 222 : : } 223 : : 224 : 3 : *param = args; 225 : 3 : if (!equals) 226 : 3 : *val = NULL; 227 : : else { 228 : 3 : args[equals] = '\0'; 229 : 3 : *val = args + equals + 1; 230 : : 231 : : /* Don't include quotes in value. */ 232 : 3 : if (**val == '"') { 233 : 0 : (*val)++; 234 : 0 : if (args[i-1] == '"') 235 : 0 : args[i-1] = '\0'; 236 : : } 237 : : } 238 : 3 : if (quoted && args[i-1] == '"') 239 : 0 : args[i-1] = '\0'; 240 : : 241 : 3 : if (args[i]) { 242 : 3 : args[i] = '\0'; 243 : 3 : next = args + i + 1; 244 : : } else 245 : 3 : next = args + i; 246 : : 247 : : /* Chew up trailing spaces. */ 248 : 3 : return skip_spaces(next); 249 : : }