diff options
author | Michal Marek <mmarek@suse.cz> | 2011-03-09 10:15:44 -0500 |
---|---|---|
committer | Michal Marek <mmarek@suse.cz> | 2011-03-09 10:15:44 -0500 |
commit | 2d8ad8719591fa803b0d589ed057fa46f49b7155 (patch) | |
tree | 4ae051577dad1161c91dafbf4207bb10a9dc91bb /lib/vsprintf.c | |
parent | 9b4ce7bce5f30712fd926ab4599a803314a07719 (diff) | |
parent | c56eb8fb6dccb83d9fe62fd4dc00c834de9bc470 (diff) |
Merge commit 'v2.6.38-rc1' into kbuild/packaging
Diffstat (limited to 'lib/vsprintf.c')
-rw-r--r-- | lib/vsprintf.c | 268 |
1 files changed, 187 insertions, 81 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 3b8aeec4e327..d3023df8477f 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
@@ -118,6 +118,7 @@ long long simple_strtoll(const char *cp, char **endp, unsigned int base) | |||
118 | 118 | ||
119 | return simple_strtoull(cp, endp, base); | 119 | return simple_strtoull(cp, endp, base); |
120 | } | 120 | } |
121 | EXPORT_SYMBOL(simple_strtoll); | ||
121 | 122 | ||
122 | /** | 123 | /** |
123 | * strict_strtoul - convert a string to an unsigned long strictly | 124 | * strict_strtoul - convert a string to an unsigned long strictly |
@@ -145,19 +146,16 @@ int strict_strtoul(const char *cp, unsigned int base, unsigned long *res) | |||
145 | { | 146 | { |
146 | char *tail; | 147 | char *tail; |
147 | unsigned long val; | 148 | unsigned long val; |
148 | size_t len; | ||
149 | 149 | ||
150 | *res = 0; | 150 | *res = 0; |
151 | len = strlen(cp); | 151 | if (!*cp) |
152 | if (len == 0) | ||
153 | return -EINVAL; | 152 | return -EINVAL; |
154 | 153 | ||
155 | val = simple_strtoul(cp, &tail, base); | 154 | val = simple_strtoul(cp, &tail, base); |
156 | if (tail == cp) | 155 | if (tail == cp) |
157 | return -EINVAL; | 156 | return -EINVAL; |
158 | 157 | ||
159 | if ((*tail == '\0') || | 158 | if ((tail[0] == '\0') || (tail[0] == '\n' && tail[1] == '\0')) { |
160 | ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) { | ||
161 | *res = val; | 159 | *res = val; |
162 | return 0; | 160 | return 0; |
163 | } | 161 | } |
@@ -219,18 +217,15 @@ int strict_strtoull(const char *cp, unsigned int base, unsigned long long *res) | |||
219 | { | 217 | { |
220 | char *tail; | 218 | char *tail; |
221 | unsigned long long val; | 219 | unsigned long long val; |
222 | size_t len; | ||
223 | 220 | ||
224 | *res = 0; | 221 | *res = 0; |
225 | len = strlen(cp); | 222 | if (!*cp) |
226 | if (len == 0) | ||
227 | return -EINVAL; | 223 | return -EINVAL; |
228 | 224 | ||
229 | val = simple_strtoull(cp, &tail, base); | 225 | val = simple_strtoull(cp, &tail, base); |
230 | if (tail == cp) | 226 | if (tail == cp) |
231 | return -EINVAL; | 227 | return -EINVAL; |
232 | if ((*tail == '\0') || | 228 | if ((tail[0] == '\0') || (tail[0] == '\n' && tail[1] == '\0')) { |
233 | ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) { | ||
234 | *res = val; | 229 | *res = val; |
235 | return 0; | 230 | return 0; |
236 | } | 231 | } |
@@ -266,7 +261,8 @@ int strict_strtoll(const char *cp, unsigned int base, long long *res) | |||
266 | } | 261 | } |
267 | EXPORT_SYMBOL(strict_strtoll); | 262 | EXPORT_SYMBOL(strict_strtoll); |
268 | 263 | ||
269 | static int skip_atoi(const char **s) | 264 | static noinline_for_stack |
265 | int skip_atoi(const char **s) | ||
270 | { | 266 | { |
271 | int i = 0; | 267 | int i = 0; |
272 | 268 | ||
@@ -286,7 +282,8 @@ static int skip_atoi(const char **s) | |||
286 | /* Formats correctly any integer in [0,99999]. | 282 | /* Formats correctly any integer in [0,99999]. |
287 | * Outputs from one to five digits depending on input. | 283 | * Outputs from one to five digits depending on input. |
288 | * On i386 gcc 4.1.2 -O2: ~250 bytes of code. */ | 284 | * On i386 gcc 4.1.2 -O2: ~250 bytes of code. */ |
289 | static char *put_dec_trunc(char *buf, unsigned q) | 285 | static noinline_for_stack |
286 | char *put_dec_trunc(char *buf, unsigned q) | ||
290 | { | 287 | { |
291 | unsigned d3, d2, d1, d0; | 288 | unsigned d3, d2, d1, d0; |
292 | d1 = (q>>4) & 0xf; | 289 | d1 = (q>>4) & 0xf; |
@@ -323,7 +320,8 @@ static char *put_dec_trunc(char *buf, unsigned q) | |||
323 | return buf; | 320 | return buf; |
324 | } | 321 | } |
325 | /* Same with if's removed. Always emits five digits */ | 322 | /* Same with if's removed. Always emits five digits */ |
326 | static char *put_dec_full(char *buf, unsigned q) | 323 | static noinline_for_stack |
324 | char *put_dec_full(char *buf, unsigned q) | ||
327 | { | 325 | { |
328 | /* BTW, if q is in [0,9999], 8-bit ints will be enough, */ | 326 | /* BTW, if q is in [0,9999], 8-bit ints will be enough, */ |
329 | /* but anyway, gcc produces better code with full-sized ints */ | 327 | /* but anyway, gcc produces better code with full-sized ints */ |
@@ -365,7 +363,8 @@ static char *put_dec_full(char *buf, unsigned q) | |||
365 | return buf; | 363 | return buf; |
366 | } | 364 | } |
367 | /* No inlining helps gcc to use registers better */ | 365 | /* No inlining helps gcc to use registers better */ |
368 | static noinline char *put_dec(char *buf, unsigned long long num) | 366 | static noinline_for_stack |
367 | char *put_dec(char *buf, unsigned long long num) | ||
369 | { | 368 | { |
370 | while (1) { | 369 | while (1) { |
371 | unsigned rem; | 370 | unsigned rem; |
@@ -381,8 +380,8 @@ static noinline char *put_dec(char *buf, unsigned long long num) | |||
381 | #define PLUS 4 /* show plus */ | 380 | #define PLUS 4 /* show plus */ |
382 | #define SPACE 8 /* space if plus */ | 381 | #define SPACE 8 /* space if plus */ |
383 | #define LEFT 16 /* left justified */ | 382 | #define LEFT 16 /* left justified */ |
384 | #define SMALL 32 /* Must be 32 == 0x20 */ | 383 | #define SMALL 32 /* use lowercase in hex (must be 32 == 0x20) */ |
385 | #define SPECIAL 64 /* 0x */ | 384 | #define SPECIAL 64 /* prefix hex with "0x", octal with "0" */ |
386 | 385 | ||
387 | enum format_type { | 386 | enum format_type { |
388 | FORMAT_TYPE_NONE, /* Just a string part */ | 387 | FORMAT_TYPE_NONE, /* Just a string part */ |
@@ -408,16 +407,17 @@ enum format_type { | |||
408 | }; | 407 | }; |
409 | 408 | ||
410 | struct printf_spec { | 409 | struct printf_spec { |
411 | enum format_type type; | 410 | u8 type; /* format_type enum */ |
412 | int flags; /* flags to number() */ | 411 | u8 flags; /* flags to number() */ |
413 | int field_width; /* width of output field */ | 412 | u8 base; /* number base, 8, 10 or 16 only */ |
414 | int base; | 413 | u8 qualifier; /* number qualifier, one of 'hHlLtzZ' */ |
415 | int precision; /* # of digits/chars */ | 414 | s16 field_width; /* width of output field */ |
416 | int qualifier; | 415 | s16 precision; /* # of digits/chars */ |
417 | }; | 416 | }; |
418 | 417 | ||
419 | static char *number(char *buf, char *end, unsigned long long num, | 418 | static noinline_for_stack |
420 | struct printf_spec spec) | 419 | char *number(char *buf, char *end, unsigned long long num, |
420 | struct printf_spec spec) | ||
421 | { | 421 | { |
422 | /* we are called with base 8, 10 or 16, only, thus don't need "G..." */ | 422 | /* we are called with base 8, 10 or 16, only, thus don't need "G..." */ |
423 | static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */ | 423 | static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */ |
@@ -536,7 +536,8 @@ static char *number(char *buf, char *end, unsigned long long num, | |||
536 | return buf; | 536 | return buf; |
537 | } | 537 | } |
538 | 538 | ||
539 | static char *string(char *buf, char *end, const char *s, struct printf_spec spec) | 539 | static noinline_for_stack |
540 | char *string(char *buf, char *end, const char *s, struct printf_spec spec) | ||
540 | { | 541 | { |
541 | int len, i; | 542 | int len, i; |
542 | 543 | ||
@@ -566,8 +567,9 @@ static char *string(char *buf, char *end, const char *s, struct printf_spec spec | |||
566 | return buf; | 567 | return buf; |
567 | } | 568 | } |
568 | 569 | ||
569 | static char *symbol_string(char *buf, char *end, void *ptr, | 570 | static noinline_for_stack |
570 | struct printf_spec spec, char ext) | 571 | char *symbol_string(char *buf, char *end, void *ptr, |
572 | struct printf_spec spec, char ext) | ||
571 | { | 573 | { |
572 | unsigned long value = (unsigned long) ptr; | 574 | unsigned long value = (unsigned long) ptr; |
573 | #ifdef CONFIG_KALLSYMS | 575 | #ifdef CONFIG_KALLSYMS |
@@ -587,8 +589,9 @@ static char *symbol_string(char *buf, char *end, void *ptr, | |||
587 | #endif | 589 | #endif |
588 | } | 590 | } |
589 | 591 | ||
590 | static char *resource_string(char *buf, char *end, struct resource *res, | 592 | static noinline_for_stack |
591 | struct printf_spec spec, const char *fmt) | 593 | char *resource_string(char *buf, char *end, struct resource *res, |
594 | struct printf_spec spec, const char *fmt) | ||
592 | { | 595 | { |
593 | #ifndef IO_RSRC_PRINTK_SIZE | 596 | #ifndef IO_RSRC_PRINTK_SIZE |
594 | #define IO_RSRC_PRINTK_SIZE 6 | 597 | #define IO_RSRC_PRINTK_SIZE 6 |
@@ -597,22 +600,35 @@ static char *resource_string(char *buf, char *end, struct resource *res, | |||
597 | #ifndef MEM_RSRC_PRINTK_SIZE | 600 | #ifndef MEM_RSRC_PRINTK_SIZE |
598 | #define MEM_RSRC_PRINTK_SIZE 10 | 601 | #define MEM_RSRC_PRINTK_SIZE 10 |
599 | #endif | 602 | #endif |
600 | struct printf_spec hex_spec = { | 603 | static const struct printf_spec io_spec = { |
601 | .base = 16, | 604 | .base = 16, |
605 | .field_width = IO_RSRC_PRINTK_SIZE, | ||
602 | .precision = -1, | 606 | .precision = -1, |
603 | .flags = SPECIAL | SMALL | ZEROPAD, | 607 | .flags = SPECIAL | SMALL | ZEROPAD, |
604 | }; | 608 | }; |
605 | struct printf_spec dec_spec = { | 609 | static const struct printf_spec mem_spec = { |
610 | .base = 16, | ||
611 | .field_width = MEM_RSRC_PRINTK_SIZE, | ||
612 | .precision = -1, | ||
613 | .flags = SPECIAL | SMALL | ZEROPAD, | ||
614 | }; | ||
615 | static const struct printf_spec bus_spec = { | ||
616 | .base = 16, | ||
617 | .field_width = 2, | ||
618 | .precision = -1, | ||
619 | .flags = SMALL | ZEROPAD, | ||
620 | }; | ||
621 | static const struct printf_spec dec_spec = { | ||
606 | .base = 10, | 622 | .base = 10, |
607 | .precision = -1, | 623 | .precision = -1, |
608 | .flags = 0, | 624 | .flags = 0, |
609 | }; | 625 | }; |
610 | struct printf_spec str_spec = { | 626 | static const struct printf_spec str_spec = { |
611 | .field_width = -1, | 627 | .field_width = -1, |
612 | .precision = 10, | 628 | .precision = 10, |
613 | .flags = LEFT, | 629 | .flags = LEFT, |
614 | }; | 630 | }; |
615 | struct printf_spec flag_spec = { | 631 | static const struct printf_spec flag_spec = { |
616 | .base = 16, | 632 | .base = 16, |
617 | .precision = -1, | 633 | .precision = -1, |
618 | .flags = SPECIAL | SMALL, | 634 | .flags = SPECIAL | SMALL, |
@@ -622,47 +638,48 @@ static char *resource_string(char *buf, char *end, struct resource *res, | |||
622 | * 64-bit res (sizeof==8): 20 chars in dec, 18 in hex ("0x" + 16) */ | 638 | * 64-bit res (sizeof==8): 20 chars in dec, 18 in hex ("0x" + 16) */ |
623 | #define RSRC_BUF_SIZE ((2 * sizeof(resource_size_t)) + 4) | 639 | #define RSRC_BUF_SIZE ((2 * sizeof(resource_size_t)) + 4) |
624 | #define FLAG_BUF_SIZE (2 * sizeof(res->flags)) | 640 | #define FLAG_BUF_SIZE (2 * sizeof(res->flags)) |
625 | #define DECODED_BUF_SIZE sizeof("[mem - 64bit pref disabled]") | 641 | #define DECODED_BUF_SIZE sizeof("[mem - 64bit pref window disabled]") |
626 | #define RAW_BUF_SIZE sizeof("[mem - flags 0x]") | 642 | #define RAW_BUF_SIZE sizeof("[mem - flags 0x]") |
627 | char sym[max(2*RSRC_BUF_SIZE + DECODED_BUF_SIZE, | 643 | char sym[max(2*RSRC_BUF_SIZE + DECODED_BUF_SIZE, |
628 | 2*RSRC_BUF_SIZE + FLAG_BUF_SIZE + RAW_BUF_SIZE)]; | 644 | 2*RSRC_BUF_SIZE + FLAG_BUF_SIZE + RAW_BUF_SIZE)]; |
629 | 645 | ||
630 | char *p = sym, *pend = sym + sizeof(sym); | 646 | char *p = sym, *pend = sym + sizeof(sym); |
631 | int size = -1, addr = 0; | ||
632 | int decode = (fmt[0] == 'R') ? 1 : 0; | 647 | int decode = (fmt[0] == 'R') ? 1 : 0; |
633 | 648 | const struct printf_spec *specp; | |
634 | if (res->flags & IORESOURCE_IO) { | ||
635 | size = IO_RSRC_PRINTK_SIZE; | ||
636 | addr = 1; | ||
637 | } else if (res->flags & IORESOURCE_MEM) { | ||
638 | size = MEM_RSRC_PRINTK_SIZE; | ||
639 | addr = 1; | ||
640 | } | ||
641 | 649 | ||
642 | *p++ = '['; | 650 | *p++ = '['; |
643 | if (res->flags & IORESOURCE_IO) | 651 | if (res->flags & IORESOURCE_IO) { |
644 | p = string(p, pend, "io ", str_spec); | 652 | p = string(p, pend, "io ", str_spec); |
645 | else if (res->flags & IORESOURCE_MEM) | 653 | specp = &io_spec; |
654 | } else if (res->flags & IORESOURCE_MEM) { | ||
646 | p = string(p, pend, "mem ", str_spec); | 655 | p = string(p, pend, "mem ", str_spec); |
647 | else if (res->flags & IORESOURCE_IRQ) | 656 | specp = &mem_spec; |
657 | } else if (res->flags & IORESOURCE_IRQ) { | ||
648 | p = string(p, pend, "irq ", str_spec); | 658 | p = string(p, pend, "irq ", str_spec); |
649 | else if (res->flags & IORESOURCE_DMA) | 659 | specp = &dec_spec; |
660 | } else if (res->flags & IORESOURCE_DMA) { | ||
650 | p = string(p, pend, "dma ", str_spec); | 661 | p = string(p, pend, "dma ", str_spec); |
651 | else { | 662 | specp = &dec_spec; |
663 | } else if (res->flags & IORESOURCE_BUS) { | ||
664 | p = string(p, pend, "bus ", str_spec); | ||
665 | specp = &bus_spec; | ||
666 | } else { | ||
652 | p = string(p, pend, "??? ", str_spec); | 667 | p = string(p, pend, "??? ", str_spec); |
668 | specp = &mem_spec; | ||
653 | decode = 0; | 669 | decode = 0; |
654 | } | 670 | } |
655 | hex_spec.field_width = size; | 671 | p = number(p, pend, res->start, *specp); |
656 | p = number(p, pend, res->start, addr ? hex_spec : dec_spec); | ||
657 | if (res->start != res->end) { | 672 | if (res->start != res->end) { |
658 | *p++ = '-'; | 673 | *p++ = '-'; |
659 | p = number(p, pend, res->end, addr ? hex_spec : dec_spec); | 674 | p = number(p, pend, res->end, *specp); |
660 | } | 675 | } |
661 | if (decode) { | 676 | if (decode) { |
662 | if (res->flags & IORESOURCE_MEM_64) | 677 | if (res->flags & IORESOURCE_MEM_64) |
663 | p = string(p, pend, " 64bit", str_spec); | 678 | p = string(p, pend, " 64bit", str_spec); |
664 | if (res->flags & IORESOURCE_PREFETCH) | 679 | if (res->flags & IORESOURCE_PREFETCH) |
665 | p = string(p, pend, " pref", str_spec); | 680 | p = string(p, pend, " pref", str_spec); |
681 | if (res->flags & IORESOURCE_WINDOW) | ||
682 | p = string(p, pend, " window", str_spec); | ||
666 | if (res->flags & IORESOURCE_DISABLED) | 683 | if (res->flags & IORESOURCE_DISABLED) |
667 | p = string(p, pend, " disabled", str_spec); | 684 | p = string(p, pend, " disabled", str_spec); |
668 | } else { | 685 | } else { |
@@ -675,30 +692,63 @@ static char *resource_string(char *buf, char *end, struct resource *res, | |||
675 | return string(buf, end, sym, spec); | 692 | return string(buf, end, sym, spec); |
676 | } | 693 | } |
677 | 694 | ||
678 | static char *mac_address_string(char *buf, char *end, u8 *addr, | 695 | static noinline_for_stack |
679 | struct printf_spec spec, const char *fmt) | 696 | char *mac_address_string(char *buf, char *end, u8 *addr, |
697 | struct printf_spec spec, const char *fmt) | ||
680 | { | 698 | { |
681 | char mac_addr[sizeof("xx:xx:xx:xx:xx:xx")]; | 699 | char mac_addr[sizeof("xx:xx:xx:xx:xx:xx")]; |
682 | char *p = mac_addr; | 700 | char *p = mac_addr; |
683 | int i; | 701 | int i; |
702 | char separator; | ||
703 | |||
704 | if (fmt[1] == 'F') { /* FDDI canonical format */ | ||
705 | separator = '-'; | ||
706 | } else { | ||
707 | separator = ':'; | ||
708 | } | ||
684 | 709 | ||
685 | for (i = 0; i < 6; i++) { | 710 | for (i = 0; i < 6; i++) { |
686 | p = pack_hex_byte(p, addr[i]); | 711 | p = pack_hex_byte(p, addr[i]); |
687 | if (fmt[0] == 'M' && i != 5) | 712 | if (fmt[0] == 'M' && i != 5) |
688 | *p++ = ':'; | 713 | *p++ = separator; |
689 | } | 714 | } |
690 | *p = '\0'; | 715 | *p = '\0'; |
691 | 716 | ||
692 | return string(buf, end, mac_addr, spec); | 717 | return string(buf, end, mac_addr, spec); |
693 | } | 718 | } |
694 | 719 | ||
695 | static char *ip4_string(char *p, const u8 *addr, bool leading_zeros) | 720 | static noinline_for_stack |
721 | char *ip4_string(char *p, const u8 *addr, const char *fmt) | ||
696 | { | 722 | { |
697 | int i; | 723 | int i; |
698 | 724 | bool leading_zeros = (fmt[0] == 'i'); | |
725 | int index; | ||
726 | int step; | ||
727 | |||
728 | switch (fmt[2]) { | ||
729 | case 'h': | ||
730 | #ifdef __BIG_ENDIAN | ||
731 | index = 0; | ||
732 | step = 1; | ||
733 | #else | ||
734 | index = 3; | ||
735 | step = -1; | ||
736 | #endif | ||
737 | break; | ||
738 | case 'l': | ||
739 | index = 3; | ||
740 | step = -1; | ||
741 | break; | ||
742 | case 'n': | ||
743 | case 'b': | ||
744 | default: | ||
745 | index = 0; | ||
746 | step = 1; | ||
747 | break; | ||
748 | } | ||
699 | for (i = 0; i < 4; i++) { | 749 | for (i = 0; i < 4; i++) { |
700 | char temp[3]; /* hold each IP quad in reverse order */ | 750 | char temp[3]; /* hold each IP quad in reverse order */ |
701 | int digits = put_dec_trunc(temp, addr[i]) - temp; | 751 | int digits = put_dec_trunc(temp, addr[index]) - temp; |
702 | if (leading_zeros) { | 752 | if (leading_zeros) { |
703 | if (digits < 3) | 753 | if (digits < 3) |
704 | *p++ = '0'; | 754 | *p++ = '0'; |
@@ -710,13 +760,15 @@ static char *ip4_string(char *p, const u8 *addr, bool leading_zeros) | |||
710 | *p++ = temp[digits]; | 760 | *p++ = temp[digits]; |
711 | if (i < 3) | 761 | if (i < 3) |
712 | *p++ = '.'; | 762 | *p++ = '.'; |
763 | index += step; | ||
713 | } | 764 | } |
714 | *p = '\0'; | 765 | *p = '\0'; |
715 | 766 | ||
716 | return p; | 767 | return p; |
717 | } | 768 | } |
718 | 769 | ||
719 | static char *ip6_compressed_string(char *p, const char *addr) | 770 | static noinline_for_stack |
771 | char *ip6_compressed_string(char *p, const char *addr) | ||
720 | { | 772 | { |
721 | int i, j, range; | 773 | int i, j, range; |
722 | unsigned char zerolength[8]; | 774 | unsigned char zerolength[8]; |
@@ -789,14 +841,15 @@ static char *ip6_compressed_string(char *p, const char *addr) | |||
789 | if (useIPv4) { | 841 | if (useIPv4) { |
790 | if (needcolon) | 842 | if (needcolon) |
791 | *p++ = ':'; | 843 | *p++ = ':'; |
792 | p = ip4_string(p, &in6.s6_addr[12], false); | 844 | p = ip4_string(p, &in6.s6_addr[12], "I4"); |
793 | } | 845 | } |
794 | *p = '\0'; | 846 | *p = '\0'; |
795 | 847 | ||
796 | return p; | 848 | return p; |
797 | } | 849 | } |
798 | 850 | ||
799 | static char *ip6_string(char *p, const char *addr, const char *fmt) | 851 | static noinline_for_stack |
852 | char *ip6_string(char *p, const char *addr, const char *fmt) | ||
800 | { | 853 | { |
801 | int i; | 854 | int i; |
802 | 855 | ||
@@ -811,8 +864,9 @@ static char *ip6_string(char *p, const char *addr, const char *fmt) | |||
811 | return p; | 864 | return p; |
812 | } | 865 | } |
813 | 866 | ||
814 | static char *ip6_addr_string(char *buf, char *end, const u8 *addr, | 867 | static noinline_for_stack |
815 | struct printf_spec spec, const char *fmt) | 868 | char *ip6_addr_string(char *buf, char *end, const u8 *addr, |
869 | struct printf_spec spec, const char *fmt) | ||
816 | { | 870 | { |
817 | char ip6_addr[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")]; | 871 | char ip6_addr[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")]; |
818 | 872 | ||
@@ -824,18 +878,20 @@ static char *ip6_addr_string(char *buf, char *end, const u8 *addr, | |||
824 | return string(buf, end, ip6_addr, spec); | 878 | return string(buf, end, ip6_addr, spec); |
825 | } | 879 | } |
826 | 880 | ||
827 | static char *ip4_addr_string(char *buf, char *end, const u8 *addr, | 881 | static noinline_for_stack |
828 | struct printf_spec spec, const char *fmt) | 882 | char *ip4_addr_string(char *buf, char *end, const u8 *addr, |
883 | struct printf_spec spec, const char *fmt) | ||
829 | { | 884 | { |
830 | char ip4_addr[sizeof("255.255.255.255")]; | 885 | char ip4_addr[sizeof("255.255.255.255")]; |
831 | 886 | ||
832 | ip4_string(ip4_addr, addr, fmt[0] == 'i'); | 887 | ip4_string(ip4_addr, addr, fmt); |
833 | 888 | ||
834 | return string(buf, end, ip4_addr, spec); | 889 | return string(buf, end, ip4_addr, spec); |
835 | } | 890 | } |
836 | 891 | ||
837 | static char *uuid_string(char *buf, char *end, const u8 *addr, | 892 | static noinline_for_stack |
838 | struct printf_spec spec, const char *fmt) | 893 | char *uuid_string(char *buf, char *end, const u8 *addr, |
894 | struct printf_spec spec, const char *fmt) | ||
839 | { | 895 | { |
840 | char uuid[sizeof("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")]; | 896 | char uuid[sizeof("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")]; |
841 | char *p = uuid; | 897 | char *p = uuid; |
@@ -880,6 +936,8 @@ static char *uuid_string(char *buf, char *end, const u8 *addr, | |||
880 | return string(buf, end, uuid, spec); | 936 | return string(buf, end, uuid, spec); |
881 | } | 937 | } |
882 | 938 | ||
939 | int kptr_restrict = 1; | ||
940 | |||
883 | /* | 941 | /* |
884 | * Show a '%p' thing. A kernel extension is that the '%p' is followed | 942 | * Show a '%p' thing. A kernel extension is that the '%p' is followed |
885 | * by an extra set of alphanumeric characters that are extended format | 943 | * by an extra set of alphanumeric characters that are extended format |
@@ -896,12 +954,15 @@ static char *uuid_string(char *buf, char *end, const u8 *addr, | |||
896 | * - 'M' For a 6-byte MAC address, it prints the address in the | 954 | * - 'M' For a 6-byte MAC address, it prints the address in the |
897 | * usual colon-separated hex notation | 955 | * usual colon-separated hex notation |
898 | * - 'm' For a 6-byte MAC address, it prints the hex address without colons | 956 | * - 'm' For a 6-byte MAC address, it prints the hex address without colons |
957 | * - 'MF' For a 6-byte MAC FDDI address, it prints the address | ||
958 | * with a dash-separated hex notation | ||
899 | * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way | 959 | * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way |
900 | * IPv4 uses dot-separated decimal without leading 0's (1.2.3.4) | 960 | * IPv4 uses dot-separated decimal without leading 0's (1.2.3.4) |
901 | * IPv6 uses colon separated network-order 16 bit hex with leading 0's | 961 | * IPv6 uses colon separated network-order 16 bit hex with leading 0's |
902 | * - 'i' [46] for 'raw' IPv4/IPv6 addresses | 962 | * - 'i' [46] for 'raw' IPv4/IPv6 addresses |
903 | * IPv6 omits the colons (01020304...0f) | 963 | * IPv6 omits the colons (01020304...0f) |
904 | * IPv4 uses dot-separated decimal with leading 0's (010.123.045.006) | 964 | * IPv4 uses dot-separated decimal with leading 0's (010.123.045.006) |
965 | * - '[Ii]4[hnbl]' IPv4 addresses in host, network, big or little endian order | ||
905 | * - 'I6c' for IPv6 addresses printed as specified by | 966 | * - 'I6c' for IPv6 addresses printed as specified by |
906 | * http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-00 | 967 | * http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-00 |
907 | * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form | 968 | * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form |
@@ -915,16 +976,30 @@ static char *uuid_string(char *buf, char *end, const u8 *addr, | |||
915 | * [0][1][2][3]-[4][5]-[6][7]-[8][9]-[10][11][12][13][14][15] | 976 | * [0][1][2][3]-[4][5]-[6][7]-[8][9]-[10][11][12][13][14][15] |
916 | * little endian output byte order is: | 977 | * little endian output byte order is: |
917 | * [3][2][1][0]-[5][4]-[7][6]-[8][9]-[10][11][12][13][14][15] | 978 | * [3][2][1][0]-[5][4]-[7][6]-[8][9]-[10][11][12][13][14][15] |
979 | * - 'V' For a struct va_format which contains a format string * and va_list *, | ||
980 | * call vsnprintf(->format, *->va_list). | ||
981 | * Implements a "recursive vsnprintf". | ||
982 | * Do not use this feature without some mechanism to verify the | ||
983 | * correctness of the format string and va_list arguments. | ||
984 | * - 'K' For a kernel pointer that should be hidden from unprivileged users | ||
918 | * | 985 | * |
919 | * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 | 986 | * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 |
920 | * function pointers are really function descriptors, which contain a | 987 | * function pointers are really function descriptors, which contain a |
921 | * pointer to the real address. | 988 | * pointer to the real address. |
922 | */ | 989 | */ |
923 | static char *pointer(const char *fmt, char *buf, char *end, void *ptr, | 990 | static noinline_for_stack |
924 | struct printf_spec spec) | 991 | char *pointer(const char *fmt, char *buf, char *end, void *ptr, |
992 | struct printf_spec spec) | ||
925 | { | 993 | { |
926 | if (!ptr) | 994 | if (!ptr) { |
995 | /* | ||
996 | * Print (null) with the same width as a pointer so it makes | ||
997 | * tabular output look nice. | ||
998 | */ | ||
999 | if (spec.field_width == -1) | ||
1000 | spec.field_width = 2 * sizeof(void *); | ||
927 | return string(buf, end, "(null)", spec); | 1001 | return string(buf, end, "(null)", spec); |
1002 | } | ||
928 | 1003 | ||
929 | switch (*fmt) { | 1004 | switch (*fmt) { |
930 | case 'F': | 1005 | case 'F': |
@@ -939,6 +1014,7 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
939 | return resource_string(buf, end, ptr, spec, fmt); | 1014 | return resource_string(buf, end, ptr, spec, fmt); |
940 | case 'M': /* Colon separated: 00:01:02:03:04:05 */ | 1015 | case 'M': /* Colon separated: 00:01:02:03:04:05 */ |
941 | case 'm': /* Contiguous: 000102030405 */ | 1016 | case 'm': /* Contiguous: 000102030405 */ |
1017 | /* [mM]F (FDDI, bit reversed) */ | ||
942 | return mac_address_string(buf, end, ptr, spec, fmt); | 1018 | return mac_address_string(buf, end, ptr, spec, fmt); |
943 | case 'I': /* Formatted IP supported | 1019 | case 'I': /* Formatted IP supported |
944 | * 4: 1.2.3.4 | 1020 | * 4: 1.2.3.4 |
@@ -958,10 +1034,33 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
958 | break; | 1034 | break; |
959 | case 'U': | 1035 | case 'U': |
960 | return uuid_string(buf, end, ptr, spec, fmt); | 1036 | return uuid_string(buf, end, ptr, spec, fmt); |
1037 | case 'V': | ||
1038 | return buf + vsnprintf(buf, end - buf, | ||
1039 | ((struct va_format *)ptr)->fmt, | ||
1040 | *(((struct va_format *)ptr)->va)); | ||
1041 | case 'K': | ||
1042 | /* | ||
1043 | * %pK cannot be used in IRQ context because its test | ||
1044 | * for CAP_SYSLOG would be meaningless. | ||
1045 | */ | ||
1046 | if (in_irq() || in_serving_softirq() || in_nmi()) { | ||
1047 | if (spec.field_width == -1) | ||
1048 | spec.field_width = 2 * sizeof(void *); | ||
1049 | return string(buf, end, "pK-error", spec); | ||
1050 | } else if ((kptr_restrict == 0) || | ||
1051 | (kptr_restrict == 1 && | ||
1052 | has_capability_noaudit(current, CAP_SYSLOG))) | ||
1053 | break; | ||
1054 | |||
1055 | if (spec.field_width == -1) { | ||
1056 | spec.field_width = 2 * sizeof(void *); | ||
1057 | spec.flags |= ZEROPAD; | ||
1058 | } | ||
1059 | return number(buf, end, 0, spec); | ||
961 | } | 1060 | } |
962 | spec.flags |= SMALL; | 1061 | spec.flags |= SMALL; |
963 | if (spec.field_width == -1) { | 1062 | if (spec.field_width == -1) { |
964 | spec.field_width = 2*sizeof(void *); | 1063 | spec.field_width = 2 * sizeof(void *); |
965 | spec.flags |= ZEROPAD; | 1064 | spec.flags |= ZEROPAD; |
966 | } | 1065 | } |
967 | spec.base = 16; | 1066 | spec.base = 16; |
@@ -989,7 +1088,8 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
989 | * @precision: precision of a number | 1088 | * @precision: precision of a number |
990 | * @qualifier: qualifier of a number (long, size_t, ...) | 1089 | * @qualifier: qualifier of a number (long, size_t, ...) |
991 | */ | 1090 | */ |
992 | static int format_decode(const char *fmt, struct printf_spec *spec) | 1091 | static noinline_for_stack |
1092 | int format_decode(const char *fmt, struct printf_spec *spec) | ||
993 | { | 1093 | { |
994 | const char *start = fmt; | 1094 | const char *start = fmt; |
995 | 1095 | ||
@@ -1297,7 +1397,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) | |||
1297 | break; | 1397 | break; |
1298 | 1398 | ||
1299 | case FORMAT_TYPE_NRCHARS: { | 1399 | case FORMAT_TYPE_NRCHARS: { |
1300 | int qualifier = spec.qualifier; | 1400 | u8 qualifier = spec.qualifier; |
1301 | 1401 | ||
1302 | if (qualifier == 'l') { | 1402 | if (qualifier == 'l') { |
1303 | long *ip = va_arg(args, long *); | 1403 | long *ip = va_arg(args, long *); |
@@ -1373,7 +1473,7 @@ EXPORT_SYMBOL(vsnprintf); | |||
1373 | * @args: Arguments for the format string | 1473 | * @args: Arguments for the format string |
1374 | * | 1474 | * |
1375 | * The return value is the number of characters which have been written into | 1475 | * The return value is the number of characters which have been written into |
1376 | * the @buf not including the trailing '\0'. If @size is <= 0 the function | 1476 | * the @buf not including the trailing '\0'. If @size is == 0 the function |
1377 | * returns 0. | 1477 | * returns 0. |
1378 | * | 1478 | * |
1379 | * Call this function if you are already dealing with a va_list. | 1479 | * Call this function if you are already dealing with a va_list. |
@@ -1387,7 +1487,11 @@ int vscnprintf(char *buf, size_t size, const char *fmt, va_list args) | |||
1387 | 1487 | ||
1388 | i = vsnprintf(buf, size, fmt, args); | 1488 | i = vsnprintf(buf, size, fmt, args); |
1389 | 1489 | ||
1390 | return (i >= size) ? (size - 1) : i; | 1490 | if (likely(i < size)) |
1491 | return i; | ||
1492 | if (size != 0) | ||
1493 | return size - 1; | ||
1494 | return 0; | ||
1391 | } | 1495 | } |
1392 | EXPORT_SYMBOL(vscnprintf); | 1496 | EXPORT_SYMBOL(vscnprintf); |
1393 | 1497 | ||
@@ -1426,7 +1530,7 @@ EXPORT_SYMBOL(snprintf); | |||
1426 | * @...: Arguments for the format string | 1530 | * @...: Arguments for the format string |
1427 | * | 1531 | * |
1428 | * The return value is the number of characters written into @buf not including | 1532 | * The return value is the number of characters written into @buf not including |
1429 | * the trailing '\0'. If @size is <= 0 the function returns 0. | 1533 | * the trailing '\0'. If @size is == 0 the function returns 0. |
1430 | */ | 1534 | */ |
1431 | 1535 | ||
1432 | int scnprintf(char *buf, size_t size, const char *fmt, ...) | 1536 | int scnprintf(char *buf, size_t size, const char *fmt, ...) |
@@ -1435,10 +1539,10 @@ int scnprintf(char *buf, size_t size, const char *fmt, ...) | |||
1435 | int i; | 1539 | int i; |
1436 | 1540 | ||
1437 | va_start(args, fmt); | 1541 | va_start(args, fmt); |
1438 | i = vsnprintf(buf, size, fmt, args); | 1542 | i = vscnprintf(buf, size, fmt, args); |
1439 | va_end(args); | 1543 | va_end(args); |
1440 | 1544 | ||
1441 | return (i >= size) ? (size - 1) : i; | 1545 | return i; |
1442 | } | 1546 | } |
1443 | EXPORT_SYMBOL(scnprintf); | 1547 | EXPORT_SYMBOL(scnprintf); |
1444 | 1548 | ||
@@ -1583,7 +1687,7 @@ do { \ | |||
1583 | 1687 | ||
1584 | case FORMAT_TYPE_NRCHARS: { | 1688 | case FORMAT_TYPE_NRCHARS: { |
1585 | /* skip %n 's argument */ | 1689 | /* skip %n 's argument */ |
1586 | int qualifier = spec.qualifier; | 1690 | u8 qualifier = spec.qualifier; |
1587 | void *skip_arg; | 1691 | void *skip_arg; |
1588 | if (qualifier == 'l') | 1692 | if (qualifier == 'l') |
1589 | skip_arg = va_arg(args, long *); | 1693 | skip_arg = va_arg(args, long *); |
@@ -1849,7 +1953,9 @@ int vsscanf(const char *buf, const char *fmt, va_list args) | |||
1849 | char *next; | 1953 | char *next; |
1850 | char digit; | 1954 | char digit; |
1851 | int num = 0; | 1955 | int num = 0; |
1852 | int qualifier, base, field_width; | 1956 | u8 qualifier; |
1957 | u8 base; | ||
1958 | s16 field_width; | ||
1853 | bool is_sign; | 1959 | bool is_sign; |
1854 | 1960 | ||
1855 | while (*fmt && *str) { | 1961 | while (*fmt && *str) { |
@@ -1927,7 +2033,7 @@ int vsscanf(const char *buf, const char *fmt, va_list args) | |||
1927 | { | 2033 | { |
1928 | char *s = (char *)va_arg(args, char *); | 2034 | char *s = (char *)va_arg(args, char *); |
1929 | if (field_width == -1) | 2035 | if (field_width == -1) |
1930 | field_width = INT_MAX; | 2036 | field_width = SHRT_MAX; |
1931 | /* first, skip leading white space in buffer */ | 2037 | /* first, skip leading white space in buffer */ |
1932 | str = skip_spaces(str); | 2038 | str = skip_spaces(str); |
1933 | 2039 | ||