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>
This commit is contained in:
Родитель
c8250381c8
Коммит
71dca95d5c
|
@ -70,6 +70,38 @@ DMA addresses types dma_addr_t:
|
|||
For printing a dma_addr_t type which can vary based on build options,
|
||||
regardless of the width of the CPU data path. Passed by reference.
|
||||
|
||||
Raw buffer as an escaped string:
|
||||
|
||||
%*pE[achnops]
|
||||
|
||||
For printing raw buffer as an escaped string. For the following buffer
|
||||
|
||||
1b 62 20 5c 43 07 22 90 0d 5d
|
||||
|
||||
few examples show how the conversion would be done (the result string
|
||||
without surrounding quotes):
|
||||
|
||||
%*pE "\eb \C\a"\220\r]"
|
||||
%*pEhp "\x1bb \C\x07"\x90\x0d]"
|
||||
%*pEa "\e\142\040\\\103\a\042\220\r\135"
|
||||
|
||||
The conversion rules are applied according to an optional combination
|
||||
of flags (see string_escape_mem() kernel documentation for the
|
||||
details):
|
||||
a - ESCAPE_ANY
|
||||
c - ESCAPE_SPECIAL
|
||||
h - ESCAPE_HEX
|
||||
n - ESCAPE_NULL
|
||||
o - ESCAPE_OCTAL
|
||||
p - ESCAPE_NP
|
||||
s - ESCAPE_SPACE
|
||||
By default ESCAPE_ANY_NP is used.
|
||||
|
||||
ESCAPE_ANY_NP is the sane choice for many cases, in particularly for
|
||||
printing SSIDs.
|
||||
|
||||
If field width is omitted the 1 byte only will be escaped.
|
||||
|
||||
Raw buffer as a hex string:
|
||||
%*ph 00 01 02 ... 3f
|
||||
%*phC 00:01:02: ... :3f
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <asm/page.h> /* for PAGE_SIZE */
|
||||
#include <asm/sections.h> /* for dereference_function_descriptor() */
|
||||
|
||||
#include <linux/string_helpers.h>
|
||||
#include "kstrtox.h"
|
||||
|
||||
/**
|
||||
|
@ -1100,6 +1101,62 @@ char *ip4_addr_string_sa(char *buf, char *end, const struct sockaddr_in *sa,
|
|||
return string(buf, end, ip4_addr, spec);
|
||||
}
|
||||
|
||||
static noinline_for_stack
|
||||
char *escaped_string(char *buf, char *end, u8 *addr, struct printf_spec spec,
|
||||
const char *fmt)
|
||||
{
|
||||
bool found = true;
|
||||
int count = 1;
|
||||
unsigned int flags = 0;
|
||||
int len;
|
||||
|
||||
if (spec.field_width == 0)
|
||||
return buf; /* nothing to print */
|
||||
|
||||
if (ZERO_OR_NULL_PTR(addr))
|
||||
return string(buf, end, NULL, spec); /* NULL pointer */
|
||||
|
||||
|
||||
do {
|
||||
switch (fmt[count++]) {
|
||||
case 'a':
|
||||
flags |= ESCAPE_ANY;
|
||||
break;
|
||||
case 'c':
|
||||
flags |= ESCAPE_SPECIAL;
|
||||
break;
|
||||
case 'h':
|
||||
flags |= ESCAPE_HEX;
|
||||
break;
|
||||
case 'n':
|
||||
flags |= ESCAPE_NULL;
|
||||
break;
|
||||
case 'o':
|
||||
flags |= ESCAPE_OCTAL;
|
||||
break;
|
||||
case 'p':
|
||||
flags |= ESCAPE_NP;
|
||||
break;
|
||||
case 's':
|
||||
flags |= ESCAPE_SPACE;
|
||||
break;
|
||||
default:
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
} while (found);
|
||||
|
||||
if (!flags)
|
||||
flags = ESCAPE_ANY_NP;
|
||||
|
||||
len = spec.field_width < 0 ? 1 : spec.field_width;
|
||||
|
||||
/* Ignore the error. We print as many characters as we can */
|
||||
string_escape_mem(addr, len, &buf, end - buf, flags, NULL);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static noinline_for_stack
|
||||
char *uuid_string(char *buf, char *end, const u8 *addr,
|
||||
struct printf_spec spec, const char *fmt)
|
||||
|
@ -1221,6 +1278,17 @@ int kptr_restrict __read_mostly;
|
|||
* - '[Ii][4S][hnbl]' IPv4 addresses in host, network, big or little endian order
|
||||
* - 'I[6S]c' for IPv6 addresses printed as specified by
|
||||
* http://tools.ietf.org/html/rfc5952
|
||||
* - 'E[achnops]' For an escaped buffer, where rules are defined by combination
|
||||
* of the following flags (see string_escape_mem() for the
|
||||
* details):
|
||||
* a - ESCAPE_ANY
|
||||
* c - ESCAPE_SPECIAL
|
||||
* h - ESCAPE_HEX
|
||||
* n - ESCAPE_NULL
|
||||
* o - ESCAPE_OCTAL
|
||||
* p - ESCAPE_NP
|
||||
* s - ESCAPE_SPACE
|
||||
* By default ESCAPE_ANY_NP is used.
|
||||
* - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form
|
||||
* "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
* Options for %pU are:
|
||||
|
@ -1321,6 +1389,8 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
|
|||
}}
|
||||
}
|
||||
break;
|
||||
case 'E':
|
||||
return escaped_string(buf, end, ptr, spec, fmt);
|
||||
case 'U':
|
||||
return uuid_string(buf, end, ptr, spec, fmt);
|
||||
case 'V':
|
||||
|
@ -1633,6 +1703,7 @@ qualifier:
|
|||
* %piS depending on sa_family of 'struct sockaddr *' print IPv4/IPv6 address
|
||||
* %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper
|
||||
* case.
|
||||
* %*pE[achnops] print an escaped buffer
|
||||
* %*ph[CDN] a variable-length hex string with a separator (supports up to 64
|
||||
* bytes of the input)
|
||||
* %n is ignored
|
||||
|
|
Загрузка…
Ссылка в новой задаче