diff options
author | Andy Shevchenko <andriy.shevchenko@linux.intel.com> | 2014-10-13 18:55:18 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-13 20:18:26 -0400 |
commit | 71dca95d5cf5ece6c1bee8e625e23c16025952c7 (patch) | |
tree | 098b1a20867ef6d1b38f549f162c160610b3cbff | |
parent | c8250381c8272a9828fdd353171727b154fbd296 (diff) |
lib/vsprintf: add %*pE[achnops] format specifier
This allows user to print a given buffer as an escaped string. The
rules are applied according to an optional mix of flags provided by
additional format letters.
For example, if the given buffer is:
1b 62 20 5c 43 07 22 90 0d 5d
The result strings would be:
%*pE "\eb \C\a"\220\r]"
%*pEhp "\x1bb \C\x07"\x90\x0d]"
%*pEa "\e\142\040\\\103\a\042\220\r\135"
Please, read Documentation/printk-formats.txt and lib/string_helpers.c
kernel documentation to get further information.
[akpm@linux-foundation.org: tidy up comment layout, per Joe]
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Suggested-by: Joe Perches <joe@perches.com>
Cc: "John W . Linville" <linville@tuxdriver.com>
Cc: Johannes Berg <johannes@sipsolutions.net>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | Documentation/printk-formats.txt | 32 | ||||
-rw-r--r-- | lib/vsprintf.c | 71 |
2 files changed, 103 insertions, 0 deletions
diff --git a/Documentation/printk-formats.txt b/Documentation/printk-formats.txt index b4498218c474..5a615c14f75d 100644 --- a/Documentation/printk-formats.txt +++ b/Documentation/printk-formats.txt | |||
@@ -70,6 +70,38 @@ DMA addresses types dma_addr_t: | |||
70 | For printing a dma_addr_t type which can vary based on build options, | 70 | For printing a dma_addr_t type which can vary based on build options, |
71 | regardless of the width of the CPU data path. Passed by reference. | 71 | regardless of the width of the CPU data path. Passed by reference. |
72 | 72 | ||
73 | Raw buffer as an escaped string: | ||
74 | |||
75 | %*pE[achnops] | ||
76 | |||
77 | For printing raw buffer as an escaped string. For the following buffer | ||
78 | |||
79 | 1b 62 20 5c 43 07 22 90 0d 5d | ||
80 | |||
81 | few examples show how the conversion would be done (the result string | ||
82 | without surrounding quotes): | ||
83 | |||
84 | %*pE "\eb \C\a"\220\r]" | ||
85 | %*pEhp "\x1bb \C\x07"\x90\x0d]" | ||
86 | %*pEa "\e\142\040\\\103\a\042\220\r\135" | ||
87 | |||
88 | The conversion rules are applied according to an optional combination | ||
89 | of flags (see string_escape_mem() kernel documentation for the | ||
90 | details): | ||
91 | a - ESCAPE_ANY | ||
92 | c - ESCAPE_SPECIAL | ||
93 | h - ESCAPE_HEX | ||
94 | n - ESCAPE_NULL | ||
95 | o - ESCAPE_OCTAL | ||
96 | p - ESCAPE_NP | ||
97 | s - ESCAPE_SPACE | ||
98 | By default ESCAPE_ANY_NP is used. | ||
99 | |||
100 | ESCAPE_ANY_NP is the sane choice for many cases, in particularly for | ||
101 | printing SSIDs. | ||
102 | |||
103 | If field width is omitted the 1 byte only will be escaped. | ||
104 | |||
73 | Raw buffer as a hex string: | 105 | Raw buffer as a hex string: |
74 | %*ph 00 01 02 ... 3f | 106 | %*ph 00 01 02 ... 3f |
75 | %*phC 00:01:02: ... :3f | 107 | %*phC 00:01:02: ... :3f |
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index ba3cd0a35640..ec337f64f52d 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <asm/page.h> /* for PAGE_SIZE */ | 33 | #include <asm/page.h> /* for PAGE_SIZE */ |
34 | #include <asm/sections.h> /* for dereference_function_descriptor() */ | 34 | #include <asm/sections.h> /* for dereference_function_descriptor() */ |
35 | 35 | ||
36 | #include <linux/string_helpers.h> | ||
36 | #include "kstrtox.h" | 37 | #include "kstrtox.h" |
37 | 38 | ||
38 | /** | 39 | /** |
@@ -1101,6 +1102,62 @@ char *ip4_addr_string_sa(char *buf, char *end, const struct sockaddr_in *sa, | |||
1101 | } | 1102 | } |
1102 | 1103 | ||
1103 | static noinline_for_stack | 1104 | static noinline_for_stack |
1105 | char *escaped_string(char *buf, char *end, u8 *addr, struct printf_spec spec, | ||
1106 | const char *fmt) | ||
1107 | { | ||
1108 | bool found = true; | ||
1109 | int count = 1; | ||
1110 | unsigned int flags = 0; | ||
1111 | int len; | ||
1112 | |||
1113 | if (spec.field_width == 0) | ||
1114 | return buf; /* nothing to print */ | ||
1115 | |||
1116 | if (ZERO_OR_NULL_PTR(addr)) | ||
1117 | return string(buf, end, NULL, spec); /* NULL pointer */ | ||
1118 | |||
1119 | |||
1120 | do { | ||
1121 | switch (fmt[count++]) { | ||
1122 | case 'a': | ||
1123 | flags |= ESCAPE_ANY; | ||
1124 | break; | ||
1125 | case 'c': | ||
1126 | flags |= ESCAPE_SPECIAL; | ||
1127 | break; | ||
1128 | case 'h': | ||
1129 | flags |= ESCAPE_HEX; | ||
1130 | break; | ||
1131 | case 'n': | ||
1132 | flags |= ESCAPE_NULL; | ||
1133 | break; | ||
1134 | case 'o': | ||
1135 | flags |= ESCAPE_OCTAL; | ||
1136 | break; | ||
1137 | case 'p': | ||
1138 | flags |= ESCAPE_NP; | ||
1139 | break; | ||
1140 | case 's': | ||
1141 | flags |= ESCAPE_SPACE; | ||
1142 | break; | ||
1143 | default: | ||
1144 | found = false; | ||
1145 | break; | ||
1146 | } | ||
1147 | } while (found); | ||
1148 | |||
1149 | if (!flags) | ||
1150 | flags = ESCAPE_ANY_NP; | ||
1151 | |||
1152 | len = spec.field_width < 0 ? 1 : spec.field_width; | ||
1153 | |||
1154 | /* Ignore the error. We print as many characters as we can */ | ||
1155 | string_escape_mem(addr, len, &buf, end - buf, flags, NULL); | ||
1156 | |||
1157 | return buf; | ||
1158 | } | ||
1159 | |||
1160 | static noinline_for_stack | ||
1104 | char *uuid_string(char *buf, char *end, const u8 *addr, | 1161 | char *uuid_string(char *buf, char *end, const u8 *addr, |
1105 | struct printf_spec spec, const char *fmt) | 1162 | struct printf_spec spec, const char *fmt) |
1106 | { | 1163 | { |
@@ -1221,6 +1278,17 @@ int kptr_restrict __read_mostly; | |||
1221 | * - '[Ii][4S][hnbl]' IPv4 addresses in host, network, big or little endian order | 1278 | * - '[Ii][4S][hnbl]' IPv4 addresses in host, network, big or little endian order |
1222 | * - 'I[6S]c' for IPv6 addresses printed as specified by | 1279 | * - 'I[6S]c' for IPv6 addresses printed as specified by |
1223 | * http://tools.ietf.org/html/rfc5952 | 1280 | * http://tools.ietf.org/html/rfc5952 |
1281 | * - 'E[achnops]' For an escaped buffer, where rules are defined by combination | ||
1282 | * of the following flags (see string_escape_mem() for the | ||
1283 | * details): | ||
1284 | * a - ESCAPE_ANY | ||
1285 | * c - ESCAPE_SPECIAL | ||
1286 | * h - ESCAPE_HEX | ||
1287 | * n - ESCAPE_NULL | ||
1288 | * o - ESCAPE_OCTAL | ||
1289 | * p - ESCAPE_NP | ||
1290 | * s - ESCAPE_SPACE | ||
1291 | * By default ESCAPE_ANY_NP is used. | ||
1224 | * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form | 1292 | * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form |
1225 | * "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" | 1293 | * "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" |
1226 | * Options for %pU are: | 1294 | * Options for %pU are: |
@@ -1321,6 +1389,8 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
1321 | }} | 1389 | }} |
1322 | } | 1390 | } |
1323 | break; | 1391 | break; |
1392 | case 'E': | ||
1393 | return escaped_string(buf, end, ptr, spec, fmt); | ||
1324 | case 'U': | 1394 | case 'U': |
1325 | return uuid_string(buf, end, ptr, spec, fmt); | 1395 | return uuid_string(buf, end, ptr, spec, fmt); |
1326 | case 'V': | 1396 | case 'V': |
@@ -1633,6 +1703,7 @@ qualifier: | |||
1633 | * %piS depending on sa_family of 'struct sockaddr *' print IPv4/IPv6 address | 1703 | * %piS depending on sa_family of 'struct sockaddr *' print IPv4/IPv6 address |
1634 | * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper | 1704 | * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper |
1635 | * case. | 1705 | * case. |
1706 | * %*pE[achnops] print an escaped buffer | ||
1636 | * %*ph[CDN] a variable-length hex string with a separator (supports up to 64 | 1707 | * %*ph[CDN] a variable-length hex string with a separator (supports up to 64 |
1637 | * bytes of the input) | 1708 | * bytes of the input) |
1638 | * %n is ignored | 1709 | * %n is ignored |