aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Shevchenko <andriy.shevchenko@linux.intel.com>2014-10-13 18:55:18 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-10-13 20:18:26 -0400
commit71dca95d5cf5ece6c1bee8e625e23c16025952c7 (patch)
tree098b1a20867ef6d1b38f549f162c160610b3cbff
parentc8250381c8272a9828fdd353171727b154fbd296 (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.txt32
-rw-r--r--lib/vsprintf.c71
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
73Raw 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
73Raw buffer as a hex string: 105Raw 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
1103static noinline_for_stack 1104static noinline_for_stack
1105char *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
1160static noinline_for_stack
1104char *uuid_string(char *buf, char *end, const u8 *addr, 1161char *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