diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /lib/vsprintf.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'lib/vsprintf.c')
-rw-r--r-- | lib/vsprintf.c | 206 |
1 files changed, 49 insertions, 157 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 7af9d841c43b..4365df31a1d5 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
@@ -120,147 +120,6 @@ long long simple_strtoll(const char *cp, char **endp, unsigned int base) | |||
120 | } | 120 | } |
121 | EXPORT_SYMBOL(simple_strtoll); | 121 | EXPORT_SYMBOL(simple_strtoll); |
122 | 122 | ||
123 | /** | ||
124 | * strict_strtoul - convert a string to an unsigned long strictly | ||
125 | * @cp: The string to be converted | ||
126 | * @base: The number base to use | ||
127 | * @res: The converted result value | ||
128 | * | ||
129 | * strict_strtoul converts a string to an unsigned long only if the | ||
130 | * string is really an unsigned long string, any string containing | ||
131 | * any invalid char at the tail will be rejected and -EINVAL is returned, | ||
132 | * only a newline char at the tail is acceptible because people generally | ||
133 | * change a module parameter in the following way: | ||
134 | * | ||
135 | * echo 1024 > /sys/module/e1000/parameters/copybreak | ||
136 | * | ||
137 | * echo will append a newline to the tail. | ||
138 | * | ||
139 | * It returns 0 if conversion is successful and *res is set to the converted | ||
140 | * value, otherwise it returns -EINVAL and *res is set to 0. | ||
141 | * | ||
142 | * simple_strtoul just ignores the successive invalid characters and | ||
143 | * return the converted value of prefix part of the string. | ||
144 | */ | ||
145 | int strict_strtoul(const char *cp, unsigned int base, unsigned long *res) | ||
146 | { | ||
147 | char *tail; | ||
148 | unsigned long val; | ||
149 | |||
150 | *res = 0; | ||
151 | if (!*cp) | ||
152 | return -EINVAL; | ||
153 | |||
154 | val = simple_strtoul(cp, &tail, base); | ||
155 | if (tail == cp) | ||
156 | return -EINVAL; | ||
157 | |||
158 | if ((tail[0] == '\0') || (tail[0] == '\n' && tail[1] == '\0')) { | ||
159 | *res = val; | ||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | return -EINVAL; | ||
164 | } | ||
165 | EXPORT_SYMBOL(strict_strtoul); | ||
166 | |||
167 | /** | ||
168 | * strict_strtol - convert a string to a long strictly | ||
169 | * @cp: The string to be converted | ||
170 | * @base: The number base to use | ||
171 | * @res: The converted result value | ||
172 | * | ||
173 | * strict_strtol is similiar to strict_strtoul, but it allows the first | ||
174 | * character of a string is '-'. | ||
175 | * | ||
176 | * It returns 0 if conversion is successful and *res is set to the converted | ||
177 | * value, otherwise it returns -EINVAL and *res is set to 0. | ||
178 | */ | ||
179 | int strict_strtol(const char *cp, unsigned int base, long *res) | ||
180 | { | ||
181 | int ret; | ||
182 | if (*cp == '-') { | ||
183 | ret = strict_strtoul(cp + 1, base, (unsigned long *)res); | ||
184 | if (!ret) | ||
185 | *res = -(*res); | ||
186 | } else { | ||
187 | ret = strict_strtoul(cp, base, (unsigned long *)res); | ||
188 | } | ||
189 | |||
190 | return ret; | ||
191 | } | ||
192 | EXPORT_SYMBOL(strict_strtol); | ||
193 | |||
194 | /** | ||
195 | * strict_strtoull - convert a string to an unsigned long long strictly | ||
196 | * @cp: The string to be converted | ||
197 | * @base: The number base to use | ||
198 | * @res: The converted result value | ||
199 | * | ||
200 | * strict_strtoull converts a string to an unsigned long long only if the | ||
201 | * string is really an unsigned long long string, any string containing | ||
202 | * any invalid char at the tail will be rejected and -EINVAL is returned, | ||
203 | * only a newline char at the tail is acceptible because people generally | ||
204 | * change a module parameter in the following way: | ||
205 | * | ||
206 | * echo 1024 > /sys/module/e1000/parameters/copybreak | ||
207 | * | ||
208 | * echo will append a newline to the tail of the string. | ||
209 | * | ||
210 | * It returns 0 if conversion is successful and *res is set to the converted | ||
211 | * value, otherwise it returns -EINVAL and *res is set to 0. | ||
212 | * | ||
213 | * simple_strtoull just ignores the successive invalid characters and | ||
214 | * return the converted value of prefix part of the string. | ||
215 | */ | ||
216 | int strict_strtoull(const char *cp, unsigned int base, unsigned long long *res) | ||
217 | { | ||
218 | char *tail; | ||
219 | unsigned long long val; | ||
220 | |||
221 | *res = 0; | ||
222 | if (!*cp) | ||
223 | return -EINVAL; | ||
224 | |||
225 | val = simple_strtoull(cp, &tail, base); | ||
226 | if (tail == cp) | ||
227 | return -EINVAL; | ||
228 | if ((tail[0] == '\0') || (tail[0] == '\n' && tail[1] == '\0')) { | ||
229 | *res = val; | ||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | return -EINVAL; | ||
234 | } | ||
235 | EXPORT_SYMBOL(strict_strtoull); | ||
236 | |||
237 | /** | ||
238 | * strict_strtoll - convert a string to a long long strictly | ||
239 | * @cp: The string to be converted | ||
240 | * @base: The number base to use | ||
241 | * @res: The converted result value | ||
242 | * | ||
243 | * strict_strtoll is similiar to strict_strtoull, but it allows the first | ||
244 | * character of a string is '-'. | ||
245 | * | ||
246 | * It returns 0 if conversion is successful and *res is set to the converted | ||
247 | * value, otherwise it returns -EINVAL and *res is set to 0. | ||
248 | */ | ||
249 | int strict_strtoll(const char *cp, unsigned int base, long long *res) | ||
250 | { | ||
251 | int ret; | ||
252 | if (*cp == '-') { | ||
253 | ret = strict_strtoull(cp + 1, base, (unsigned long long *)res); | ||
254 | if (!ret) | ||
255 | *res = -(*res); | ||
256 | } else { | ||
257 | ret = strict_strtoull(cp, base, (unsigned long long *)res); | ||
258 | } | ||
259 | |||
260 | return ret; | ||
261 | } | ||
262 | EXPORT_SYMBOL(strict_strtoll); | ||
263 | |||
264 | static noinline_for_stack | 123 | static noinline_for_stack |
265 | int skip_atoi(const char **s) | 124 | int skip_atoi(const char **s) |
266 | { | 125 | { |
@@ -574,7 +433,9 @@ char *symbol_string(char *buf, char *end, void *ptr, | |||
574 | unsigned long value = (unsigned long) ptr; | 433 | unsigned long value = (unsigned long) ptr; |
575 | #ifdef CONFIG_KALLSYMS | 434 | #ifdef CONFIG_KALLSYMS |
576 | char sym[KSYM_SYMBOL_LEN]; | 435 | char sym[KSYM_SYMBOL_LEN]; |
577 | if (ext != 'f' && ext != 's') | 436 | if (ext == 'B') |
437 | sprint_backtrace(sym, value); | ||
438 | else if (ext != 'f' && ext != 's') | ||
578 | sprint_symbol(sym, value); | 439 | sprint_symbol(sym, value); |
579 | else | 440 | else |
580 | kallsyms_lookup(value, NULL, NULL, NULL, sym); | 441 | kallsyms_lookup(value, NULL, NULL, NULL, sym); |
@@ -805,6 +666,8 @@ char *ip6_compressed_string(char *p, const char *addr) | |||
805 | colonpos = i; | 666 | colonpos = i; |
806 | } | 667 | } |
807 | } | 668 | } |
669 | if (longest == 1) /* don't compress a single 0 */ | ||
670 | colonpos = -1; | ||
808 | 671 | ||
809 | /* emit address */ | 672 | /* emit address */ |
810 | for (i = 0; i < range; i++) { | 673 | for (i = 0; i < range; i++) { |
@@ -936,6 +799,8 @@ char *uuid_string(char *buf, char *end, const u8 *addr, | |||
936 | return string(buf, end, uuid, spec); | 799 | return string(buf, end, uuid, spec); |
937 | } | 800 | } |
938 | 801 | ||
802 | int kptr_restrict __read_mostly; | ||
803 | |||
939 | /* | 804 | /* |
940 | * Show a '%p' thing. A kernel extension is that the '%p' is followed | 805 | * Show a '%p' thing. A kernel extension is that the '%p' is followed |
941 | * by an extra set of alphanumeric characters that are extended format | 806 | * by an extra set of alphanumeric characters that are extended format |
@@ -947,6 +812,7 @@ char *uuid_string(char *buf, char *end, const u8 *addr, | |||
947 | * - 'f' For simple symbolic function names without offset | 812 | * - 'f' For simple symbolic function names without offset |
948 | * - 'S' For symbolic direct pointers with offset | 813 | * - 'S' For symbolic direct pointers with offset |
949 | * - 's' For symbolic direct pointers without offset | 814 | * - 's' For symbolic direct pointers without offset |
815 | * - 'B' For backtraced symbolic direct pointers with offset | ||
950 | * - 'R' For decoded struct resource, e.g., [mem 0x0-0x1f 64bit pref] | 816 | * - 'R' For decoded struct resource, e.g., [mem 0x0-0x1f 64bit pref] |
951 | * - 'r' For raw struct resource, e.g., [mem 0x0-0x1f flags 0x201] | 817 | * - 'r' For raw struct resource, e.g., [mem 0x0-0x1f flags 0x201] |
952 | * - 'M' For a 6-byte MAC address, it prints the address in the | 818 | * - 'M' For a 6-byte MAC address, it prints the address in the |
@@ -962,7 +828,7 @@ char *uuid_string(char *buf, char *end, const u8 *addr, | |||
962 | * IPv4 uses dot-separated decimal with leading 0's (010.123.045.006) | 828 | * IPv4 uses dot-separated decimal with leading 0's (010.123.045.006) |
963 | * - '[Ii]4[hnbl]' IPv4 addresses in host, network, big or little endian order | 829 | * - '[Ii]4[hnbl]' IPv4 addresses in host, network, big or little endian order |
964 | * - 'I6c' for IPv6 addresses printed as specified by | 830 | * - 'I6c' for IPv6 addresses printed as specified by |
965 | * http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-00 | 831 | * http://tools.ietf.org/html/rfc5952 |
966 | * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form | 832 | * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form |
967 | * "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" | 833 | * "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" |
968 | * Options for %pU are: | 834 | * Options for %pU are: |
@@ -979,6 +845,7 @@ char *uuid_string(char *buf, char *end, const u8 *addr, | |||
979 | * Implements a "recursive vsnprintf". | 845 | * Implements a "recursive vsnprintf". |
980 | * Do not use this feature without some mechanism to verify the | 846 | * Do not use this feature without some mechanism to verify the |
981 | * correctness of the format string and va_list arguments. | 847 | * correctness of the format string and va_list arguments. |
848 | * - 'K' For a kernel pointer that should be hidden from unprivileged users | ||
982 | * | 849 | * |
983 | * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 | 850 | * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 |
984 | * function pointers are really function descriptors, which contain a | 851 | * function pointers are really function descriptors, which contain a |
@@ -988,8 +855,15 @@ static noinline_for_stack | |||
988 | char *pointer(const char *fmt, char *buf, char *end, void *ptr, | 855 | char *pointer(const char *fmt, char *buf, char *end, void *ptr, |
989 | struct printf_spec spec) | 856 | struct printf_spec spec) |
990 | { | 857 | { |
991 | if (!ptr) | 858 | if (!ptr && *fmt != 'K') { |
859 | /* | ||
860 | * Print (null) with the same width as a pointer so it makes | ||
861 | * tabular output look nice. | ||
862 | */ | ||
863 | if (spec.field_width == -1) | ||
864 | spec.field_width = 2 * sizeof(void *); | ||
992 | return string(buf, end, "(null)", spec); | 865 | return string(buf, end, "(null)", spec); |
866 | } | ||
993 | 867 | ||
994 | switch (*fmt) { | 868 | switch (*fmt) { |
995 | case 'F': | 869 | case 'F': |
@@ -998,6 +872,7 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
998 | /* Fallthrough */ | 872 | /* Fallthrough */ |
999 | case 'S': | 873 | case 'S': |
1000 | case 's': | 874 | case 's': |
875 | case 'B': | ||
1001 | return symbol_string(buf, end, ptr, spec, *fmt); | 876 | return symbol_string(buf, end, ptr, spec, *fmt); |
1002 | case 'R': | 877 | case 'R': |
1003 | case 'r': | 878 | case 'r': |
@@ -1025,13 +900,28 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
1025 | case 'U': | 900 | case 'U': |
1026 | return uuid_string(buf, end, ptr, spec, fmt); | 901 | return uuid_string(buf, end, ptr, spec, fmt); |
1027 | case 'V': | 902 | case 'V': |
1028 | return buf + vsnprintf(buf, end - buf, | 903 | return buf + vsnprintf(buf, end > buf ? end - buf : 0, |
1029 | ((struct va_format *)ptr)->fmt, | 904 | ((struct va_format *)ptr)->fmt, |
1030 | *(((struct va_format *)ptr)->va)); | 905 | *(((struct va_format *)ptr)->va)); |
906 | case 'K': | ||
907 | /* | ||
908 | * %pK cannot be used in IRQ context because its test | ||
909 | * for CAP_SYSLOG would be meaningless. | ||
910 | */ | ||
911 | if (in_irq() || in_serving_softirq() || in_nmi()) { | ||
912 | if (spec.field_width == -1) | ||
913 | spec.field_width = 2 * sizeof(void *); | ||
914 | return string(buf, end, "pK-error", spec); | ||
915 | } | ||
916 | if (!((kptr_restrict == 0) || | ||
917 | (kptr_restrict == 1 && | ||
918 | has_capability_noaudit(current, CAP_SYSLOG)))) | ||
919 | ptr = NULL; | ||
920 | break; | ||
1031 | } | 921 | } |
1032 | spec.flags |= SMALL; | 922 | spec.flags |= SMALL; |
1033 | if (spec.field_width == -1) { | 923 | if (spec.field_width == -1) { |
1034 | spec.field_width = 2*sizeof(void *); | 924 | spec.field_width = 2 * sizeof(void *); |
1035 | spec.flags |= ZEROPAD; | 925 | spec.flags |= ZEROPAD; |
1036 | } | 926 | } |
1037 | spec.base = 16; | 927 | spec.base = 16; |
@@ -1250,6 +1140,7 @@ qualifier: | |||
1250 | * %ps output the name of a text symbol without offset | 1140 | * %ps output the name of a text symbol without offset |
1251 | * %pF output the name of a function pointer with its offset | 1141 | * %pF output the name of a function pointer with its offset |
1252 | * %pf output the name of a function pointer without its offset | 1142 | * %pf output the name of a function pointer without its offset |
1143 | * %pB output the name of a backtrace symbol with its offset | ||
1253 | * %pR output the address range in a struct resource with decoded flags | 1144 | * %pR output the address range in a struct resource with decoded flags |
1254 | * %pr output the address range in a struct resource with raw flags | 1145 | * %pr output the address range in a struct resource with raw flags |
1255 | * %pM output a 6-byte MAC address with colons | 1146 | * %pM output a 6-byte MAC address with colons |
@@ -1272,8 +1163,7 @@ qualifier: | |||
1272 | * return is greater than or equal to @size, the resulting | 1163 | * return is greater than or equal to @size, the resulting |
1273 | * string is truncated. | 1164 | * string is truncated. |
1274 | * | 1165 | * |
1275 | * Call this function if you are already dealing with a va_list. | 1166 | * If you're not already dealing with a va_list consider using snprintf(). |
1276 | * You probably want snprintf() instead. | ||
1277 | */ | 1167 | */ |
1278 | int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) | 1168 | int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) |
1279 | { | 1169 | { |
@@ -1444,11 +1334,10 @@ EXPORT_SYMBOL(vsnprintf); | |||
1444 | * @args: Arguments for the format string | 1334 | * @args: Arguments for the format string |
1445 | * | 1335 | * |
1446 | * The return value is the number of characters which have been written into | 1336 | * The return value is the number of characters which have been written into |
1447 | * the @buf not including the trailing '\0'. If @size is <= 0 the function | 1337 | * the @buf not including the trailing '\0'. If @size is == 0 the function |
1448 | * returns 0. | 1338 | * returns 0. |
1449 | * | 1339 | * |
1450 | * Call this function if you are already dealing with a va_list. | 1340 | * If you're not already dealing with a va_list consider using scnprintf(). |
1451 | * You probably want scnprintf() instead. | ||
1452 | * | 1341 | * |
1453 | * See the vsnprintf() documentation for format string extensions over C99. | 1342 | * See the vsnprintf() documentation for format string extensions over C99. |
1454 | */ | 1343 | */ |
@@ -1458,7 +1347,11 @@ int vscnprintf(char *buf, size_t size, const char *fmt, va_list args) | |||
1458 | 1347 | ||
1459 | i = vsnprintf(buf, size, fmt, args); | 1348 | i = vsnprintf(buf, size, fmt, args); |
1460 | 1349 | ||
1461 | return (i >= size) ? (size - 1) : i; | 1350 | if (likely(i < size)) |
1351 | return i; | ||
1352 | if (size != 0) | ||
1353 | return size - 1; | ||
1354 | return 0; | ||
1462 | } | 1355 | } |
1463 | EXPORT_SYMBOL(vscnprintf); | 1356 | EXPORT_SYMBOL(vscnprintf); |
1464 | 1357 | ||
@@ -1497,7 +1390,7 @@ EXPORT_SYMBOL(snprintf); | |||
1497 | * @...: Arguments for the format string | 1390 | * @...: Arguments for the format string |
1498 | * | 1391 | * |
1499 | * The return value is the number of characters written into @buf not including | 1392 | * The return value is the number of characters written into @buf not including |
1500 | * the trailing '\0'. If @size is <= 0 the function returns 0. | 1393 | * the trailing '\0'. If @size is == 0 the function returns 0. |
1501 | */ | 1394 | */ |
1502 | 1395 | ||
1503 | int scnprintf(char *buf, size_t size, const char *fmt, ...) | 1396 | int scnprintf(char *buf, size_t size, const char *fmt, ...) |
@@ -1506,10 +1399,10 @@ int scnprintf(char *buf, size_t size, const char *fmt, ...) | |||
1506 | int i; | 1399 | int i; |
1507 | 1400 | ||
1508 | va_start(args, fmt); | 1401 | va_start(args, fmt); |
1509 | i = vsnprintf(buf, size, fmt, args); | 1402 | i = vscnprintf(buf, size, fmt, args); |
1510 | va_end(args); | 1403 | va_end(args); |
1511 | 1404 | ||
1512 | return (i >= size) ? (size - 1) : i; | 1405 | return i; |
1513 | } | 1406 | } |
1514 | EXPORT_SYMBOL(scnprintf); | 1407 | EXPORT_SYMBOL(scnprintf); |
1515 | 1408 | ||
@@ -1523,8 +1416,7 @@ EXPORT_SYMBOL(scnprintf); | |||
1523 | * into @buf. Use vsnprintf() or vscnprintf() in order to avoid | 1416 | * into @buf. Use vsnprintf() or vscnprintf() in order to avoid |
1524 | * buffer overflows. | 1417 | * buffer overflows. |
1525 | * | 1418 | * |
1526 | * Call this function if you are already dealing with a va_list. | 1419 | * If you're not already dealing with a va_list consider using sprintf(). |
1527 | * You probably want sprintf() instead. | ||
1528 | * | 1420 | * |
1529 | * See the vsnprintf() documentation for format string extensions over C99. | 1421 | * See the vsnprintf() documentation for format string extensions over C99. |
1530 | */ | 1422 | */ |