mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-04-11 14:18:00 +07:00
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:
parent
c8250381c8
commit
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,
|
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.
|
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:
|
Raw buffer as a hex string:
|
||||||
%*ph 00 01 02 ... 3f
|
%*ph 00 01 02 ... 3f
|
||||||
%*phC 00:01:02: ... :3f
|
%*phC 00:01:02: ... :3f
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include <asm/page.h> /* for PAGE_SIZE */
|
#include <asm/page.h> /* for PAGE_SIZE */
|
||||||
#include <asm/sections.h> /* for dereference_function_descriptor() */
|
#include <asm/sections.h> /* for dereference_function_descriptor() */
|
||||||
|
|
||||||
|
#include <linux/string_helpers.h>
|
||||||
#include "kstrtox.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);
|
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
|
static noinline_for_stack
|
||||||
char *uuid_string(char *buf, char *end, const u8 *addr,
|
char *uuid_string(char *buf, char *end, const u8 *addr,
|
||||||
struct printf_spec spec, const char *fmt)
|
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
|
* - '[Ii][4S][hnbl]' IPv4 addresses in host, network, big or little endian order
|
||||||
* - 'I[6S]c' for IPv6 addresses printed as specified by
|
* - 'I[6S]c' for IPv6 addresses printed as specified by
|
||||||
* http://tools.ietf.org/html/rfc5952
|
* 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
|
* - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form
|
||||||
* "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
* "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||||
* Options for %pU are:
|
* Options for %pU are:
|
||||||
@ -1321,6 +1389,8 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
|
|||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'E':
|
||||||
|
return escaped_string(buf, end, ptr, spec, fmt);
|
||||||
case 'U':
|
case 'U':
|
||||||
return uuid_string(buf, end, ptr, spec, fmt);
|
return uuid_string(buf, end, ptr, spec, fmt);
|
||||||
case 'V':
|
case 'V':
|
||||||
@ -1633,6 +1703,7 @@ int format_decode(const char *fmt, struct printf_spec *spec)
|
|||||||
* %piS depending on sa_family of 'struct sockaddr *' print IPv4/IPv6 address
|
* %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
|
* %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper
|
||||||
* case.
|
* case.
|
||||||
|
* %*pE[achnops] print an escaped buffer
|
||||||
* %*ph[CDN] a variable-length hex string with a separator (supports up to 64
|
* %*ph[CDN] a variable-length hex string with a separator (supports up to 64
|
||||||
* bytes of the input)
|
* bytes of the input)
|
||||||
* %n is ignored
|
* %n is ignored
|
||||||
|
Loading…
Reference in New Issue
Block a user