diff options
| author | Thomas Gleixner <tglx@linutronix.de> | 2013-07-12 06:34:42 -0400 |
|---|---|---|
| committer | Thomas Gleixner <tglx@linutronix.de> | 2013-07-12 06:34:42 -0400 |
| commit | f2006e27396f55276f24434f56e208d86e7f9908 (patch) | |
| tree | 71896db916d33888b4286f80117d3cac0da40e6d /lib/vsprintf.c | |
| parent | e399eb56a6110e13f97e644658648602e2b08de7 (diff) | |
| parent | 9903883f1dd6e86f286b7bfa6e4b423f98c1cd9e (diff) | |
Merge branch 'linus' into timers/urgent
Get upstream changes so we can apply fixes against them
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'lib/vsprintf.c')
| -rw-r--r-- | lib/vsprintf.c | 126 |
1 files changed, 123 insertions, 3 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index e149c6416384..739a36366b79 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
| @@ -670,7 +670,7 @@ static noinline_for_stack | |||
| 670 | char *hex_string(char *buf, char *end, u8 *addr, struct printf_spec spec, | 670 | char *hex_string(char *buf, char *end, u8 *addr, struct printf_spec spec, |
| 671 | const char *fmt) | 671 | const char *fmt) |
| 672 | { | 672 | { |
| 673 | int i, len = 1; /* if we pass '%ph[CDN]', field witdh remains | 673 | int i, len = 1; /* if we pass '%ph[CDN]', field width remains |
| 674 | negative value, fallback to the default */ | 674 | negative value, fallback to the default */ |
| 675 | char separator; | 675 | char separator; |
| 676 | 676 | ||
| @@ -923,6 +923,103 @@ char *ip4_addr_string(char *buf, char *end, const u8 *addr, | |||
| 923 | } | 923 | } |
| 924 | 924 | ||
| 925 | static noinline_for_stack | 925 | static noinline_for_stack |
| 926 | char *ip6_addr_string_sa(char *buf, char *end, const struct sockaddr_in6 *sa, | ||
| 927 | struct printf_spec spec, const char *fmt) | ||
| 928 | { | ||
| 929 | bool have_p = false, have_s = false, have_f = false, have_c = false; | ||
| 930 | char ip6_addr[sizeof("[xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255]") + | ||
| 931 | sizeof(":12345") + sizeof("/123456789") + | ||
| 932 | sizeof("%1234567890")]; | ||
| 933 | char *p = ip6_addr, *pend = ip6_addr + sizeof(ip6_addr); | ||
| 934 | const u8 *addr = (const u8 *) &sa->sin6_addr; | ||
| 935 | char fmt6[2] = { fmt[0], '6' }; | ||
| 936 | u8 off = 0; | ||
| 937 | |||
| 938 | fmt++; | ||
| 939 | while (isalpha(*++fmt)) { | ||
| 940 | switch (*fmt) { | ||
| 941 | case 'p': | ||
| 942 | have_p = true; | ||
| 943 | break; | ||
| 944 | case 'f': | ||
| 945 | have_f = true; | ||
| 946 | break; | ||
| 947 | case 's': | ||
| 948 | have_s = true; | ||
| 949 | break; | ||
| 950 | case 'c': | ||
| 951 | have_c = true; | ||
| 952 | break; | ||
| 953 | } | ||
| 954 | } | ||
| 955 | |||
| 956 | if (have_p || have_s || have_f) { | ||
| 957 | *p = '['; | ||
| 958 | off = 1; | ||
| 959 | } | ||
| 960 | |||
| 961 | if (fmt6[0] == 'I' && have_c) | ||
| 962 | p = ip6_compressed_string(ip6_addr + off, addr); | ||
| 963 | else | ||
| 964 | p = ip6_string(ip6_addr + off, addr, fmt6); | ||
| 965 | |||
| 966 | if (have_p || have_s || have_f) | ||
| 967 | *p++ = ']'; | ||
| 968 | |||
| 969 | if (have_p) { | ||
| 970 | *p++ = ':'; | ||
| 971 | p = number(p, pend, ntohs(sa->sin6_port), spec); | ||
| 972 | } | ||
| 973 | if (have_f) { | ||
| 974 | *p++ = '/'; | ||
| 975 | p = number(p, pend, ntohl(sa->sin6_flowinfo & | ||
| 976 | IPV6_FLOWINFO_MASK), spec); | ||
| 977 | } | ||
| 978 | if (have_s) { | ||
| 979 | *p++ = '%'; | ||
| 980 | p = number(p, pend, sa->sin6_scope_id, spec); | ||
| 981 | } | ||
| 982 | *p = '\0'; | ||
| 983 | |||
| 984 | return string(buf, end, ip6_addr, spec); | ||
| 985 | } | ||
| 986 | |||
| 987 | static noinline_for_stack | ||
| 988 | char *ip4_addr_string_sa(char *buf, char *end, const struct sockaddr_in *sa, | ||
| 989 | struct printf_spec spec, const char *fmt) | ||
| 990 | { | ||
| 991 | bool have_p = false; | ||
| 992 | char *p, ip4_addr[sizeof("255.255.255.255") + sizeof(":12345")]; | ||
| 993 | char *pend = ip4_addr + sizeof(ip4_addr); | ||
| 994 | const u8 *addr = (const u8 *) &sa->sin_addr.s_addr; | ||
| 995 | char fmt4[3] = { fmt[0], '4', 0 }; | ||
| 996 | |||
| 997 | fmt++; | ||
| 998 | while (isalpha(*++fmt)) { | ||
| 999 | switch (*fmt) { | ||
| 1000 | case 'p': | ||
| 1001 | have_p = true; | ||
| 1002 | break; | ||
| 1003 | case 'h': | ||
| 1004 | case 'l': | ||
| 1005 | case 'n': | ||
| 1006 | case 'b': | ||
| 1007 | fmt4[2] = *fmt; | ||
| 1008 | break; | ||
| 1009 | } | ||
| 1010 | } | ||
| 1011 | |||
| 1012 | p = ip4_string(ip4_addr, addr, fmt4); | ||
| 1013 | if (have_p) { | ||
| 1014 | *p++ = ':'; | ||
| 1015 | p = number(p, pend, ntohs(sa->sin_port), spec); | ||
| 1016 | } | ||
| 1017 | *p = '\0'; | ||
| 1018 | |||
| 1019 | return string(buf, end, ip4_addr, spec); | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | static noinline_for_stack | ||
| 926 | char *uuid_string(char *buf, char *end, const u8 *addr, | 1023 | char *uuid_string(char *buf, char *end, const u8 *addr, |
| 927 | struct printf_spec spec, const char *fmt) | 1024 | struct printf_spec spec, const char *fmt) |
| 928 | { | 1025 | { |
| @@ -1007,11 +1104,17 @@ int kptr_restrict __read_mostly; | |||
| 1007 | * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way | 1104 | * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way |
| 1008 | * IPv4 uses dot-separated decimal without leading 0's (1.2.3.4) | 1105 | * IPv4 uses dot-separated decimal without leading 0's (1.2.3.4) |
| 1009 | * IPv6 uses colon separated network-order 16 bit hex with leading 0's | 1106 | * IPv6 uses colon separated network-order 16 bit hex with leading 0's |
| 1107 | * [S][pfs] | ||
| 1108 | * Generic IPv4/IPv6 address (struct sockaddr *) that falls back to | ||
| 1109 | * [4] or [6] and is able to print port [p], flowinfo [f], scope [s] | ||
| 1010 | * - 'i' [46] for 'raw' IPv4/IPv6 addresses | 1110 | * - 'i' [46] for 'raw' IPv4/IPv6 addresses |
| 1011 | * IPv6 omits the colons (01020304...0f) | 1111 | * IPv6 omits the colons (01020304...0f) |
| 1012 | * IPv4 uses dot-separated decimal with leading 0's (010.123.045.006) | 1112 | * IPv4 uses dot-separated decimal with leading 0's (010.123.045.006) |
| 1013 | * - '[Ii]4[hnbl]' IPv4 addresses in host, network, big or little endian order | 1113 | * [S][pfs] |
| 1014 | * - 'I6c' for IPv6 addresses printed as specified by | 1114 | * Generic IPv4/IPv6 address (struct sockaddr *) that falls back to |
| 1115 | * [4] or [6] and is able to print port [p], flowinfo [f], scope [s] | ||
| 1116 | * - '[Ii][4S][hnbl]' IPv4 addresses in host, network, big or little endian order | ||
| 1117 | * - 'I[6S]c' for IPv6 addresses printed as specified by | ||
| 1015 | * http://tools.ietf.org/html/rfc5952 | 1118 | * http://tools.ietf.org/html/rfc5952 |
| 1016 | * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form | 1119 | * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form |
| 1017 | * "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" | 1120 | * "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" |
| @@ -1093,6 +1196,21 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
| 1093 | return ip6_addr_string(buf, end, ptr, spec, fmt); | 1196 | return ip6_addr_string(buf, end, ptr, spec, fmt); |
| 1094 | case '4': | 1197 | case '4': |
| 1095 | return ip4_addr_string(buf, end, ptr, spec, fmt); | 1198 | return ip4_addr_string(buf, end, ptr, spec, fmt); |
| 1199 | case 'S': { | ||
| 1200 | const union { | ||
| 1201 | struct sockaddr raw; | ||
| 1202 | struct sockaddr_in v4; | ||
| 1203 | struct sockaddr_in6 v6; | ||
| 1204 | } *sa = ptr; | ||
| 1205 | |||
| 1206 | switch (sa->raw.sa_family) { | ||
| 1207 | case AF_INET: | ||
| 1208 | return ip4_addr_string_sa(buf, end, &sa->v4, spec, fmt); | ||
| 1209 | case AF_INET6: | ||
| 1210 | return ip6_addr_string_sa(buf, end, &sa->v6, spec, fmt); | ||
| 1211 | default: | ||
| 1212 | return string(buf, end, "(invalid address)", spec); | ||
| 1213 | }} | ||
| 1096 | } | 1214 | } |
| 1097 | break; | 1215 | break; |
| 1098 | case 'U': | 1216 | case 'U': |
| @@ -1370,6 +1488,8 @@ qualifier: | |||
| 1370 | * %pI6 print an IPv6 address with colons | 1488 | * %pI6 print an IPv6 address with colons |
| 1371 | * %pi6 print an IPv6 address without colons | 1489 | * %pi6 print an IPv6 address without colons |
| 1372 | * %pI6c print an IPv6 address as specified by RFC 5952 | 1490 | * %pI6c print an IPv6 address as specified by RFC 5952 |
| 1491 | * %pIS depending on sa_family of 'struct sockaddr *' print IPv4/IPv6 address | ||
| 1492 | * %piS depending on sa_family of 'struct sockaddr *' print IPv4/IPv6 address | ||
| 1373 | * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper | 1493 | * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper |
| 1374 | * case. | 1494 | * case. |
| 1375 | * %*ph[CDN] a variable-length hex string with a separator (supports up to 64 | 1495 | * %*ph[CDN] a variable-length hex string with a separator (supports up to 64 |
