aboutsummaryrefslogtreecommitdiffstats
path: root/lib/vsprintf.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/vsprintf.c')
-rw-r--r--lib/vsprintf.c84
1 files changed, 84 insertions, 0 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index a013bbc23717..0fbd0121d91d 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
588static 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
605static 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
623static 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 */
600static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field_width, int precision, int flags) 666static 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) {