diff options
Diffstat (limited to 'lib/vsprintf.c')
| -rw-r--r-- | lib/vsprintf.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index a013bbc2371..0fbd0121d91 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
| @@ -170,6 +170,8 @@ int strict_strtoul(const char *cp, unsigned int base, unsigned long *res) | |||
| 170 | return -EINVAL; | 170 | return -EINVAL; |
| 171 | 171 | ||
| 172 | val = simple_strtoul(cp, &tail, base); | 172 | val = simple_strtoul(cp, &tail, base); |
| 173 | if (tail == cp) | ||
| 174 | return -EINVAL; | ||
| 173 | if ((*tail == '\0') || | 175 | if ((*tail == '\0') || |
| 174 | ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) { | 176 | ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) { |
| 175 | *res = val; | 177 | *res = val; |
| @@ -241,6 +243,8 @@ int strict_strtoull(const char *cp, unsigned int base, unsigned long long *res) | |||
| 241 | return -EINVAL; | 243 | return -EINVAL; |
| 242 | 244 | ||
| 243 | val = simple_strtoull(cp, &tail, base); | 245 | val = simple_strtoull(cp, &tail, base); |
| 246 | if (tail == cp) | ||
| 247 | return -EINVAL; | ||
| 244 | if ((*tail == '\0') || | 248 | if ((*tail == '\0') || |
| 245 | ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) { | 249 | ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) { |
| 246 | *res = val; | 250 | *res = val; |
| @@ -581,6 +585,62 @@ static char *resource_string(char *buf, char *end, struct resource *res, int fie | |||
| 581 | return string(buf, end, sym, field_width, precision, flags); | 585 | return string(buf, end, sym, field_width, precision, flags); |
| 582 | } | 586 | } |
| 583 | 587 | ||
| 588 | static char *mac_address_string(char *buf, char *end, u8 *addr, int field_width, | ||
| 589 | int precision, int flags) | ||
| 590 | { | ||
| 591 | char mac_addr[6 * 3]; /* (6 * 2 hex digits), 5 colons and trailing zero */ | ||
| 592 | char *p = mac_addr; | ||
| 593 | int i; | ||
| 594 | |||
| 595 | for (i = 0; i < 6; i++) { | ||
| 596 | p = pack_hex_byte(p, addr[i]); | ||
| 597 | if (!(flags & SPECIAL) && i != 5) | ||
| 598 | *p++ = ':'; | ||
| 599 | } | ||
| 600 | *p = '\0'; | ||
| 601 | |||
| 602 | return string(buf, end, mac_addr, field_width, precision, flags & ~SPECIAL); | ||
| 603 | } | ||
| 604 | |||
| 605 | static char *ip6_addr_string(char *buf, char *end, u8 *addr, int field_width, | ||
| 606 | int precision, int flags) | ||
| 607 | { | ||
| 608 | char ip6_addr[8 * 5]; /* (8 * 4 hex digits), 7 colons and trailing zero */ | ||
| 609 | char *p = ip6_addr; | ||
| 610 | int i; | ||
| 611 | |||
| 612 | for (i = 0; i < 8; i++) { | ||
| 613 | p = pack_hex_byte(p, addr[2 * i]); | ||
| 614 | p = pack_hex_byte(p, addr[2 * i + 1]); | ||
| 615 | if (!(flags & SPECIAL) && i != 7) | ||
| 616 | *p++ = ':'; | ||
| 617 | } | ||
| 618 | *p = '\0'; | ||
| 619 | |||
| 620 | return string(buf, end, ip6_addr, field_width, precision, flags & ~SPECIAL); | ||
| 621 | } | ||
| 622 | |||
| 623 | static char *ip4_addr_string(char *buf, char *end, u8 *addr, int field_width, | ||
| 624 | int precision, int flags) | ||
| 625 | { | ||
| 626 | char ip4_addr[4 * 4]; /* (4 * 3 decimal digits), 3 dots and trailing zero */ | ||
| 627 | char temp[3]; /* hold each IP quad in reverse order */ | ||
| 628 | char *p = ip4_addr; | ||
| 629 | int i, digits; | ||
| 630 | |||
| 631 | for (i = 0; i < 4; i++) { | ||
| 632 | digits = put_dec_trunc(temp, addr[i]) - temp; | ||
| 633 | /* reverse the digits in the quad */ | ||
| 634 | while (digits--) | ||
| 635 | *p++ = temp[digits]; | ||
| 636 | if (i != 3) | ||
| 637 | *p++ = '.'; | ||
| 638 | } | ||
| 639 | *p = '\0'; | ||
| 640 | |||
| 641 | return string(buf, end, ip4_addr, field_width, precision, flags & ~SPECIAL); | ||
| 642 | } | ||
| 643 | |||
| 584 | /* | 644 | /* |
| 585 | * Show a '%p' thing. A kernel extension is that the '%p' is followed | 645 | * Show a '%p' thing. A kernel extension is that the '%p' is followed |
| 586 | * by an extra set of alphanumeric characters that are extended format | 646 | * by an extra set of alphanumeric characters that are extended format |
| @@ -592,6 +652,12 @@ static char *resource_string(char *buf, char *end, struct resource *res, int fie | |||
| 592 | * - 'S' For symbolic direct pointers | 652 | * - 'S' For symbolic direct pointers |
| 593 | * - 'R' For a struct resource pointer, it prints the range of | 653 | * - 'R' For a struct resource pointer, it prints the range of |
| 594 | * addresses (not the name nor the flags) | 654 | * addresses (not the name nor the flags) |
| 655 | * - 'M' For a 6-byte MAC address, it prints the address in the | ||
| 656 | * usual colon-separated hex notation | ||
| 657 | * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way (dot-separated | ||
| 658 | * decimal for v4 and colon separated network-order 16 bit hex for v6) | ||
| 659 | * - 'i' [46] for 'raw' IPv4/IPv6 addresses, IPv6 omits the colons, IPv4 is | ||
| 660 | * currently the same | ||
| 595 | * | 661 | * |
| 596 | * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 | 662 | * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 |
| 597 | * function pointers are really function descriptors, which contain a | 663 | * function pointers are really function descriptors, which contain a |
| @@ -599,6 +665,9 @@ static char *resource_string(char *buf, char *end, struct resource *res, int fie | |||
| 599 | */ | 665 | */ |
| 600 | static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field_width, int precision, int flags) | 666 | static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field_width, int precision, int flags) |
| 601 | { | 667 | { |
| 668 | if (!ptr) | ||
| 669 | return string(buf, end, "(null)", field_width, precision, flags); | ||
| 670 | |||
| 602 | switch (*fmt) { | 671 | switch (*fmt) { |
| 603 | case 'F': | 672 | case 'F': |
| 604 | ptr = dereference_function_descriptor(ptr); | 673 | ptr = dereference_function_descriptor(ptr); |
| @@ -607,6 +676,21 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field | |||
| 607 | return symbol_string(buf, end, ptr, field_width, precision, flags); | 676 | return symbol_string(buf, end, ptr, field_width, precision, flags); |
| 608 | case 'R': | 677 | case 'R': |
| 609 | return resource_string(buf, end, ptr, field_width, precision, flags); | 678 | return resource_string(buf, end, ptr, field_width, precision, flags); |
| 679 | case 'm': | ||
| 680 | flags |= SPECIAL; | ||
| 681 | /* Fallthrough */ | ||
| 682 | case 'M': | ||
| 683 | return mac_address_string(buf, end, ptr, field_width, precision, flags); | ||
| 684 | case 'i': | ||
| 685 | flags |= SPECIAL; | ||
| 686 | /* Fallthrough */ | ||
| 687 | case 'I': | ||
| 688 | if (fmt[1] == '6') | ||
| 689 | return ip6_addr_string(buf, end, ptr, field_width, precision, flags); | ||
| 690 | if (fmt[1] == '4') | ||
| 691 | return ip4_addr_string(buf, end, ptr, field_width, precision, flags); | ||
| 692 | flags &= ~SPECIAL; | ||
| 693 | break; | ||
| 610 | } | 694 | } |
| 611 | flags |= SMALL; | 695 | flags |= SMALL; |
| 612 | if (field_width == -1) { | 696 | if (field_width == -1) { |
