^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * linux/lib/vsprintf.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 1991, 1992 Linus Torvalds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Wirzenius wrote this portably, Torvalds fucked it up :-)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Fri Jul 13 2001 Crutcher Dunnavant <crutcher+kernel@datastacks.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * - changed to provide snprintf and vsnprintf functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * So Feb 1 16:51:32 CET 2004 Juergen Quade <quade@hsnr.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * - scnprintf and vscnprintf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <stdarg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/build_bug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/clk-provider.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/errname.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/module.h> /* for KSYM_SYMBOL_LEN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/kallsyms.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/math64.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/dcache.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/cred.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/rtc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/uuid.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <net/addrconf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/siphash.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <linux/compiler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <linux/property.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #ifdef CONFIG_BLOCK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <linux/blkdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include "../mm/internal.h" /* For the trace_print_flags arrays */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include <asm/page.h> /* for PAGE_SIZE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #include <asm/byteorder.h> /* cpu_to_le16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #include <linux/string_helpers.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #include "kstrtox.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static unsigned long long simple_strntoull(const char *startp, size_t max_chars,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) char **endp, unsigned int base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) const char *cp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) unsigned long long result = 0ULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) size_t prefix_chars;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) unsigned int rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) cp = _parse_integer_fixup_radix(startp, &base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) prefix_chars = cp - startp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (prefix_chars < max_chars) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) rv = _parse_integer_limit(cp, base, &result, max_chars - prefix_chars);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) /* FIXME */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) cp += (rv & ~KSTRTOX_OVERFLOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /* Field too short for prefix + digit, skip over without converting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) cp = startp + max_chars;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (endp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) *endp = (char *)cp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * simple_strtoull - convert a string to an unsigned long long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * @cp: The start of the string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * @endp: A pointer to the end of the parsed string will be placed here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * @base: The number base to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * This function has caveats. Please use kstrtoull instead.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return simple_strntoull(cp, INT_MAX, endp, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) EXPORT_SYMBOL(simple_strtoull);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * simple_strtoul - convert a string to an unsigned long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * @cp: The start of the string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * @endp: A pointer to the end of the parsed string will be placed here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * @base: The number base to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * This function has caveats. Please use kstrtoul instead.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return simple_strtoull(cp, endp, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) EXPORT_SYMBOL(simple_strtoul);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * simple_strtol - convert a string to a signed long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * @cp: The start of the string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * @endp: A pointer to the end of the parsed string will be placed here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * @base: The number base to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * This function has caveats. Please use kstrtol instead.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) long simple_strtol(const char *cp, char **endp, unsigned int base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (*cp == '-')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return -simple_strtoul(cp + 1, endp, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return simple_strtoul(cp, endp, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) EXPORT_SYMBOL(simple_strtol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static long long simple_strntoll(const char *cp, size_t max_chars, char **endp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) unsigned int base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * simple_strntoull() safely handles receiving max_chars==0 in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * case cp[0] == '-' && max_chars == 1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * If max_chars == 0 we can drop through and pass it to simple_strntoull()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * and the content of *cp is irrelevant.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (*cp == '-' && max_chars > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return -simple_strntoull(cp + 1, max_chars - 1, endp, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return simple_strntoull(cp, max_chars, endp, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * simple_strtoll - convert a string to a signed long long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * @cp: The start of the string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * @endp: A pointer to the end of the parsed string will be placed here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * @base: The number base to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * This function has caveats. Please use kstrtoll instead.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) long long simple_strtoll(const char *cp, char **endp, unsigned int base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return simple_strntoll(cp, INT_MAX, endp, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) EXPORT_SYMBOL(simple_strtoll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) int skip_atoi(const char **s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) i = i*10 + *((*s)++) - '0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) } while (isdigit(**s));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * Decimal conversion is by far the most typical, and is used for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * /proc and /sys data. This directly impacts e.g. top performance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * with many processes running. We optimize it for speed by emitting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * two characters at a time, using a 200 byte lookup table. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * roughly halves the number of multiplications compared to computing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * the digits one at a time. Implementation strongly inspired by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * previous version, which in turn used ideas described at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * <http://www.cs.uiowa.edu/~jones/bcd/divide.html> (with permission
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * from the author, Douglas W. Jones).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * It turns out there is precisely one 26 bit fixed-point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * approximation a of 64/100 for which x/100 == (x * (u64)a) >> 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * holds for all x in [0, 10^8-1], namely a = 0x28f5c29. The actual
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * range happens to be somewhat larger (x <= 1073741898), but that's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * irrelevant for our purpose.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * For dividing a number in the range [10^4, 10^6-1] by 100, we still
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * need a 32x32->64 bit multiply, so we simply use the same constant.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * For dividing a number in the range [100, 10^4-1] by 100, there are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) * several options. The simplest is (x * 0x147b) >> 19, which is valid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) * for all x <= 43698.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) static const u16 decpair[100] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) #define _(x) (__force u16) cpu_to_le16(((x % 10) | ((x / 10) << 8)) + 0x3030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) _( 0), _( 1), _( 2), _( 3), _( 4), _( 5), _( 6), _( 7), _( 8), _( 9),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) _(10), _(11), _(12), _(13), _(14), _(15), _(16), _(17), _(18), _(19),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) _(20), _(21), _(22), _(23), _(24), _(25), _(26), _(27), _(28), _(29),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) _(30), _(31), _(32), _(33), _(34), _(35), _(36), _(37), _(38), _(39),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) _(40), _(41), _(42), _(43), _(44), _(45), _(46), _(47), _(48), _(49),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) _(50), _(51), _(52), _(53), _(54), _(55), _(56), _(57), _(58), _(59),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) _(60), _(61), _(62), _(63), _(64), _(65), _(66), _(67), _(68), _(69),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) _(70), _(71), _(72), _(73), _(74), _(75), _(76), _(77), _(78), _(79),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) _(80), _(81), _(82), _(83), _(84), _(85), _(86), _(87), _(88), _(89),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) _(90), _(91), _(92), _(93), _(94), _(95), _(96), _(97), _(98), _(99),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) #undef _
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * This will print a single '0' even if r == 0, since we would
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * immediately jump to out_r where two 0s would be written but only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * one of them accounted for in buf. This is needed by ip4_string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * below. All other callers pass a non-zero value of r.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) char *put_dec_trunc8(char *buf, unsigned r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) unsigned q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) /* 1 <= r < 10^8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (r < 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) goto out_r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) /* 100 <= r < 10^8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) q = (r * (u64)0x28f5c29) >> 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) *((u16 *)buf) = decpair[r - 100*q];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) buf += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) /* 1 <= q < 10^6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (q < 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) goto out_q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) /* 100 <= q < 10^6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) r = (q * (u64)0x28f5c29) >> 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) *((u16 *)buf) = decpair[q - 100*r];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) buf += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) /* 1 <= r < 10^4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (r < 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) goto out_r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) /* 100 <= r < 10^4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) q = (r * 0x147b) >> 19;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) *((u16 *)buf) = decpair[r - 100*q];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) buf += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) out_q:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) /* 1 <= q < 100 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) r = q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) out_r:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) /* 1 <= r < 100 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) *((u16 *)buf) = decpair[r];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) buf += r < 10 ? 1 : 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) #if BITS_PER_LONG == 64 && BITS_PER_LONG_LONG == 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) char *put_dec_full8(char *buf, unsigned r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) unsigned q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) /* 0 <= r < 10^8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) q = (r * (u64)0x28f5c29) >> 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) *((u16 *)buf) = decpair[r - 100*q];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) buf += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) /* 0 <= q < 10^6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) r = (q * (u64)0x28f5c29) >> 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) *((u16 *)buf) = decpair[q - 100*r];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) buf += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /* 0 <= r < 10^4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) q = (r * 0x147b) >> 19;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) *((u16 *)buf) = decpair[r - 100*q];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) buf += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) /* 0 <= q < 100 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) *((u16 *)buf) = decpair[q];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) buf += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) char *put_dec(char *buf, unsigned long long n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (n >= 100*1000*1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) buf = put_dec_full8(buf, do_div(n, 100*1000*1000));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) /* 1 <= n <= 1.6e11 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (n >= 100*1000*1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) buf = put_dec_full8(buf, do_div(n, 100*1000*1000));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) /* 1 <= n < 1e8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) return put_dec_trunc8(buf, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) #elif BITS_PER_LONG == 32 && BITS_PER_LONG_LONG == 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) put_dec_full4(char *buf, unsigned r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) unsigned q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) /* 0 <= r < 10^4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) q = (r * 0x147b) >> 19;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) *((u16 *)buf) = decpair[r - 100*q];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) buf += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) /* 0 <= q < 100 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) *((u16 *)buf) = decpair[q];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) * Call put_dec_full4 on x % 10000, return x / 10000.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) * The approximation x/10000 == (x * 0x346DC5D7) >> 43
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) * holds for all x < 1,128,869,999. The largest value this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) * helper will ever be asked to convert is 1,125,520,955.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) * (second call in the put_dec code, assuming n is all-ones).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) unsigned put_dec_helper4(char *buf, unsigned x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) uint32_t q = (x * (uint64_t)0x346DC5D7) >> 43;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) put_dec_full4(buf, x - q * 10000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) return q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) /* Based on code by Douglas W. Jones found at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) * <http://www.cs.uiowa.edu/~jones/bcd/decimal.html#sixtyfour>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) * (with permission from the author).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) * Performs no 64-bit division and hence should be fast on 32-bit machines.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) char *put_dec(char *buf, unsigned long long n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) uint32_t d3, d2, d1, q, h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (n < 100*1000*1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) return put_dec_trunc8(buf, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) d1 = ((uint32_t)n >> 16); /* implicit "& 0xffff" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) h = (n >> 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) d2 = (h ) & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) d3 = (h >> 16); /* implicit "& 0xffff" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) /* n = 2^48 d3 + 2^32 d2 + 2^16 d1 + d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) = 281_4749_7671_0656 d3 + 42_9496_7296 d2 + 6_5536 d1 + d0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) q = 656 * d3 + 7296 * d2 + 5536 * d1 + ((uint32_t)n & 0xffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) q = put_dec_helper4(buf, q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) q += 7671 * d3 + 9496 * d2 + 6 * d1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) q = put_dec_helper4(buf+4, q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) q += 4749 * d3 + 42 * d2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) q = put_dec_helper4(buf+8, q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) q += 281 * d3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) buf += 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (q)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) buf = put_dec_trunc8(buf, q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) else while (buf[-1] == '0')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) --buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) * Convert passed number to decimal string.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) * Returns the length of string. On buffer overflow, returns 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) * If speed is not important, use snprintf(). It's easy to read the code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) int num_to_str(char *buf, int size, unsigned long long num, unsigned int width)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) /* put_dec requires 2-byte alignment of the buffer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) char tmp[sizeof(num) * 3] __aligned(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) int idx, len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) /* put_dec() may work incorrectly for num = 0 (generate "", not "0") */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) if (num <= 9) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) tmp[0] = '0' + num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) len = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) len = put_dec(tmp, num) - tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (len > size || width > size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) if (width > len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) width = width - len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) for (idx = 0; idx < width; idx++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) buf[idx] = ' ';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) width = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) for (idx = 0; idx < len; ++idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) buf[idx + width] = tmp[len - idx - 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) return len + width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) #define SIGN 1 /* unsigned/signed, must be 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) #define LEFT 2 /* left justified */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) #define PLUS 4 /* show plus */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) #define SPACE 8 /* space if plus */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) #define ZEROPAD 16 /* pad with zero, must be 16 == '0' - ' ' */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) #define SMALL 32 /* use lowercase in hex (must be 32 == 0x20) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) #define SPECIAL 64 /* prefix hex with "0x", octal with "0" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) static_assert(ZEROPAD == ('0' - ' '));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) static_assert(SMALL == ' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) enum format_type {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) FORMAT_TYPE_NONE, /* Just a string part */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) FORMAT_TYPE_WIDTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) FORMAT_TYPE_PRECISION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) FORMAT_TYPE_CHAR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) FORMAT_TYPE_STR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) FORMAT_TYPE_PTR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) FORMAT_TYPE_PERCENT_CHAR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) FORMAT_TYPE_INVALID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) FORMAT_TYPE_LONG_LONG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) FORMAT_TYPE_ULONG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) FORMAT_TYPE_LONG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) FORMAT_TYPE_UBYTE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) FORMAT_TYPE_BYTE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) FORMAT_TYPE_USHORT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) FORMAT_TYPE_SHORT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) FORMAT_TYPE_UINT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) FORMAT_TYPE_INT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) FORMAT_TYPE_SIZE_T,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) FORMAT_TYPE_PTRDIFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) struct printf_spec {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) unsigned int type:8; /* format_type enum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) signed int field_width:24; /* width of output field */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) unsigned int flags:8; /* flags to number() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) unsigned int base:8; /* number base, 8, 10 or 16 only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) signed int precision:16; /* # of digits/chars */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) static_assert(sizeof(struct printf_spec) == 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) #define FIELD_WIDTH_MAX ((1 << 23) - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) #define PRECISION_MAX ((1 << 15) - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) char *number(char *buf, char *end, unsigned long long num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) struct printf_spec spec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) /* put_dec requires 2-byte alignment of the buffer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) char tmp[3 * sizeof(num)] __aligned(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) char sign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) char locase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) int need_pfx = ((spec.flags & SPECIAL) && spec.base != 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) bool is_zero = num == 0LL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) int field_width = spec.field_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) int precision = spec.precision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) /* locase = 0 or 0x20. ORing digits or letters with 'locase'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) * produces same digits or (maybe lowercased) letters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) locase = (spec.flags & SMALL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) if (spec.flags & LEFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) spec.flags &= ~ZEROPAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) sign = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) if (spec.flags & SIGN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if ((signed long long)num < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) sign = '-';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) num = -(signed long long)num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) field_width--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) } else if (spec.flags & PLUS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) sign = '+';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) field_width--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) } else if (spec.flags & SPACE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) sign = ' ';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) field_width--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) if (need_pfx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (spec.base == 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) field_width -= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) else if (!is_zero)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) field_width--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) /* generate full string in tmp[], in reverse order */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) if (num < spec.base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) tmp[i++] = hex_asc_upper[num] | locase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) else if (spec.base != 10) { /* 8 or 16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) int mask = spec.base - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) int shift = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) if (spec.base == 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) shift = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) tmp[i++] = (hex_asc_upper[((unsigned char)num) & mask] | locase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) num >>= shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) } while (num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) } else { /* base 10 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) i = put_dec(tmp, num) - tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) /* printing 100 using %2d gives "100", not "00" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) if (i > precision)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) precision = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) /* leading space padding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) field_width -= precision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) if (!(spec.flags & (ZEROPAD | LEFT))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) while (--field_width >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (buf < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) *buf = ' ';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) ++buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) /* sign */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) if (sign) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) if (buf < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) *buf = sign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) ++buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) /* "0x" / "0" prefix */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (need_pfx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) if (spec.base == 16 || !is_zero) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) if (buf < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) *buf = '0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) ++buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if (spec.base == 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (buf < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) *buf = ('X' | locase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) ++buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) /* zero or space padding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) if (!(spec.flags & LEFT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) char c = ' ' + (spec.flags & ZEROPAD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) while (--field_width >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) if (buf < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) *buf = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) ++buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) /* hmm even more zero padding? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) while (i <= --precision) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) if (buf < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) *buf = '0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) ++buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) /* actual digits of result */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) while (--i >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (buf < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) *buf = tmp[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) ++buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) /* trailing space padding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) while (--field_width >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) if (buf < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) *buf = ' ';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) ++buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) char *special_hex_number(char *buf, char *end, unsigned long long num, int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) struct printf_spec spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) spec.type = FORMAT_TYPE_PTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) spec.field_width = 2 + 2 * size; /* 0x + hex */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) spec.flags = SPECIAL | SMALL | ZEROPAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) spec.base = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) spec.precision = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) return number(buf, end, num, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) static void move_right(char *buf, char *end, unsigned len, unsigned spaces)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) size_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) if (buf >= end) /* nowhere to put anything */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) size = end - buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) if (size <= spaces) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) memset(buf, ' ', size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) if (len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) if (len > size - spaces)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) len = size - spaces;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) memmove(buf + spaces, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) memset(buf, ' ', spaces);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) * Handle field width padding for a string.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) * @buf: current buffer position
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) * @n: length of string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) * @end: end of output buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) * @spec: for field width and flags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) * Returns: new buffer position after padding.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) char *widen_string(char *buf, int n, char *end, struct printf_spec spec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) unsigned spaces;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (likely(n >= spec.field_width))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) /* we want to pad the sucker */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) spaces = spec.field_width - n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) if (!(spec.flags & LEFT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) move_right(buf - n, end, n, spaces);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) return buf + spaces;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) while (spaces--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) if (buf < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) *buf = ' ';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) ++buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) /* Handle string from a well known address. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) static char *string_nocheck(char *buf, char *end, const char *s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) struct printf_spec spec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) int len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) int lim = spec.precision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) while (lim--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) char c = *s++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) if (!c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) if (buf < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) *buf = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) ++buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) ++len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) return widen_string(buf, len, end, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) static char *err_ptr(char *buf, char *end, void *ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) struct printf_spec spec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) int err = PTR_ERR(ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) const char *sym = errname(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) if (sym)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) return string_nocheck(buf, end, sym, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) * Somebody passed ERR_PTR(-1234) or some other non-existing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) * Efoo - or perhaps CONFIG_SYMBOLIC_ERRNAME=n. Fall back to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) * printing it as its decimal representation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) spec.flags |= SIGN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) spec.base = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) return number(buf, end, err, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) /* Be careful: error messages must fit into the given buffer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) static char *error_string(char *buf, char *end, const char *s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) struct printf_spec spec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) * Hard limit to avoid a completely insane messages. It actually
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) * works pretty well because most error messages are in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) * the many pointer format modifiers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) if (spec.precision == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) spec.precision = 2 * sizeof(void *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) return string_nocheck(buf, end, s, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) * Do not call any complex external code here. Nested printk()/vsprintf()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) * might cause infinite loops. Failures might break printk() and would
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) * be hard to debug.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) static const char *check_pointer_msg(const void *ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) if (!ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) return "(null)";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) if ((unsigned long)ptr < PAGE_SIZE || IS_ERR_VALUE(ptr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) return "(efault)";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) static int check_pointer(char **buf, char *end, const void *ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) struct printf_spec spec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) const char *err_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) err_msg = check_pointer_msg(ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) if (err_msg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) *buf = error_string(*buf, end, err_msg, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) char *string(char *buf, char *end, const char *s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) struct printf_spec spec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) if (check_pointer(&buf, end, s, spec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) return string_nocheck(buf, end, s, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) static char *pointer_string(char *buf, char *end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) const void *ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) struct printf_spec spec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) spec.base = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) spec.flags |= SMALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (spec.field_width == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) spec.field_width = 2 * sizeof(ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) spec.flags |= ZEROPAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) return number(buf, end, (unsigned long int)ptr, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) /* Make pointers available for printing early in the boot sequence. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) static int debug_boot_weak_hash __ro_after_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) static int __init debug_boot_weak_hash_enable(char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) debug_boot_weak_hash = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) pr_info("debug_boot_weak_hash enabled\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) early_param("debug_boot_weak_hash", debug_boot_weak_hash_enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) static DEFINE_STATIC_KEY_TRUE(not_filled_random_ptr_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) static siphash_key_t ptr_key __read_mostly;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) static void enable_ptr_key_workfn(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) get_random_bytes(&ptr_key, sizeof(ptr_key));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) /* Needs to run from preemptible context */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) static_branch_disable(¬_filled_random_ptr_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) static DECLARE_WORK(enable_ptr_key_work, enable_ptr_key_workfn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) static void fill_random_ptr_key(struct random_ready_callback *unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) /* This may be in an interrupt handler. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) queue_work(system_unbound_wq, &enable_ptr_key_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) static struct random_ready_callback random_ready = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) .func = fill_random_ptr_key
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) static int __init initialize_ptr_random(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) int key_size = sizeof(ptr_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) /* Use hw RNG if available. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) if (get_random_bytes_arch(&ptr_key, key_size) == key_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) static_branch_disable(¬_filled_random_ptr_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) ret = add_random_ready_callback(&random_ready);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) } else if (ret == -EALREADY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) /* This is in preemptible context */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) enable_ptr_key_workfn(&enable_ptr_key_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) early_initcall(initialize_ptr_random);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) /* Maps a pointer to a 32 bit unique identifier. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) static inline int __ptr_to_hashval(const void *ptr, unsigned long *hashval_out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) unsigned long hashval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) if (static_branch_unlikely(¬_filled_random_ptr_key))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) #ifdef CONFIG_64BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) hashval = (unsigned long)siphash_1u64((u64)ptr, &ptr_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) * Mask off the first 32 bits, this makes explicit that we have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) * modified the address (and 32 bits is plenty for a unique ID).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) hashval = hashval & 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) hashval = (unsigned long)siphash_1u32((u32)ptr, &ptr_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) *hashval_out = hashval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) int ptr_to_hashval(const void *ptr, unsigned long *hashval_out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) return __ptr_to_hashval(ptr, hashval_out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) static char *ptr_to_id(char *buf, char *end, const void *ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) struct printf_spec spec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) const char *str = sizeof(ptr) == 8 ? "(____ptrval____)" : "(ptrval)";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) unsigned long hashval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) * Print the real pointer value for NULL and error pointers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) * as they are not actual addresses.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) if (IS_ERR_OR_NULL(ptr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) return pointer_string(buf, end, ptr, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) /* When debugging early boot use non-cryptographically secure hash. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) if (unlikely(debug_boot_weak_hash)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) hashval = hash_long((unsigned long)ptr, 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) return pointer_string(buf, end, (const void *)hashval, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) ret = __ptr_to_hashval(ptr, &hashval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) spec.field_width = 2 * sizeof(ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) /* string length must be less than default_width */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) return error_string(buf, end, str, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) return pointer_string(buf, end, (const void *)hashval, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) int kptr_restrict __read_mostly;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) char *restricted_pointer(char *buf, char *end, const void *ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) struct printf_spec spec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) switch (kptr_restrict) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) /* Handle as %p, hash and do _not_ leak addresses. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) return ptr_to_id(buf, end, ptr, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) case 1: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) const struct cred *cred;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) * kptr_restrict==1 cannot be used in IRQ context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) * because its test for CAP_SYSLOG would be meaningless.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) if (in_irq() || in_serving_softirq() || in_nmi()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) if (spec.field_width == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) spec.field_width = 2 * sizeof(ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) return error_string(buf, end, "pK-error", spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) * Only print the real pointer value if the current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) * process has CAP_SYSLOG and is running with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) * same credentials it started with. This is because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) * access to files is checked at open() time, but %pK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) * checks permission at read() time. We don't want to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) * leak pointer values if a binary opens a file using
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) * %pK and then elevates privileges before reading it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) cred = current_cred();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) if (!has_capability_noaudit(current, CAP_SYSLOG) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) !uid_eq(cred->euid, cred->uid) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) !gid_eq(cred->egid, cred->gid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) ptr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) /* Always print 0's for %pK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) ptr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) return pointer_string(buf, end, ptr, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) char *dentry_name(char *buf, char *end, const struct dentry *d, struct printf_spec spec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) const char *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) const char *array[4], *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) const struct dentry *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) int depth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) int i, n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) switch (fmt[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) case '2': case '3': case '4':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) depth = fmt[1] - '0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) depth = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) for (i = 0; i < depth; i++, d = p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) if (check_pointer(&buf, end, d, spec)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) p = READ_ONCE(d->d_parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) array[i] = READ_ONCE(d->d_name.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) if (p == d) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) if (i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) array[i] = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) s = array[--i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) for (n = 0; n != spec.precision; n++, buf++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) char c = *s++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) if (!c) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) if (!i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) c = '/';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) s = array[--i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) if (buf < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) *buf = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) return widen_string(buf, n, end, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) char *file_dentry_name(char *buf, char *end, const struct file *f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) struct printf_spec spec, const char *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) if (check_pointer(&buf, end, f, spec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) return dentry_name(buf, end, f->f_path.dentry, spec, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) #ifdef CONFIG_BLOCK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) char *bdev_name(char *buf, char *end, struct block_device *bdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) struct printf_spec spec, const char *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) struct gendisk *hd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) if (check_pointer(&buf, end, bdev, spec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) hd = bdev->bd_disk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) buf = string(buf, end, hd->disk_name, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) if (bdev->bd_partno) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) if (isdigit(hd->disk_name[strlen(hd->disk_name)-1])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) if (buf < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) *buf = 'p';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) buf++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) buf = number(buf, end, bdev->bd_partno, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) char *symbol_string(char *buf, char *end, void *ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) struct printf_spec spec, const char *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) unsigned long value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) #ifdef CONFIG_KALLSYMS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) char sym[KSYM_SYMBOL_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) if (fmt[1] == 'R')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) ptr = __builtin_extract_return_addr(ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) value = (unsigned long)ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) #ifdef CONFIG_KALLSYMS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) if (*fmt == 'B')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) sprint_backtrace(sym, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) else if (*fmt != 's')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) sprint_symbol(sym, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) sprint_symbol_no_offset(sym, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) return string_nocheck(buf, end, sym, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) return special_hex_number(buf, end, value, sizeof(void *));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) static const struct printf_spec default_str_spec = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) .field_width = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) .precision = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) static const struct printf_spec default_flag_spec = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) .base = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) .precision = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) .flags = SPECIAL | SMALL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) static const struct printf_spec default_dec_spec = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) .base = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) .precision = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) static const struct printf_spec default_dec02_spec = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) .base = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) .field_width = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) .precision = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) .flags = ZEROPAD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) static const struct printf_spec default_dec04_spec = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) .base = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) .field_width = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) .precision = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) .flags = ZEROPAD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) char *resource_string(char *buf, char *end, struct resource *res,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) struct printf_spec spec, const char *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) #ifndef IO_RSRC_PRINTK_SIZE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) #define IO_RSRC_PRINTK_SIZE 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) #ifndef MEM_RSRC_PRINTK_SIZE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) #define MEM_RSRC_PRINTK_SIZE 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) static const struct printf_spec io_spec = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) .base = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) .field_width = IO_RSRC_PRINTK_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) .precision = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) .flags = SPECIAL | SMALL | ZEROPAD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) static const struct printf_spec mem_spec = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) .base = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) .field_width = MEM_RSRC_PRINTK_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) .precision = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) .flags = SPECIAL | SMALL | ZEROPAD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) static const struct printf_spec bus_spec = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) .base = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) .field_width = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) .precision = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) .flags = SMALL | ZEROPAD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) static const struct printf_spec str_spec = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) .field_width = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) .precision = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) .flags = LEFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) /* 32-bit res (sizeof==4): 10 chars in dec, 10 in hex ("0x" + 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) * 64-bit res (sizeof==8): 20 chars in dec, 18 in hex ("0x" + 16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) #define RSRC_BUF_SIZE ((2 * sizeof(resource_size_t)) + 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) #define FLAG_BUF_SIZE (2 * sizeof(res->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) #define DECODED_BUF_SIZE sizeof("[mem - 64bit pref window disabled]")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) #define RAW_BUF_SIZE sizeof("[mem - flags 0x]")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) char sym[max(2*RSRC_BUF_SIZE + DECODED_BUF_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) 2*RSRC_BUF_SIZE + FLAG_BUF_SIZE + RAW_BUF_SIZE)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) char *p = sym, *pend = sym + sizeof(sym);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) int decode = (fmt[0] == 'R') ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) const struct printf_spec *specp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) if (check_pointer(&buf, end, res, spec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) *p++ = '[';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) if (res->flags & IORESOURCE_IO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) p = string_nocheck(p, pend, "io ", str_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) specp = &io_spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) } else if (res->flags & IORESOURCE_MEM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) p = string_nocheck(p, pend, "mem ", str_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) specp = &mem_spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) } else if (res->flags & IORESOURCE_IRQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) p = string_nocheck(p, pend, "irq ", str_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) specp = &default_dec_spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) } else if (res->flags & IORESOURCE_DMA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) p = string_nocheck(p, pend, "dma ", str_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) specp = &default_dec_spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) } else if (res->flags & IORESOURCE_BUS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) p = string_nocheck(p, pend, "bus ", str_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) specp = &bus_spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) p = string_nocheck(p, pend, "??? ", str_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) specp = &mem_spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) decode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) if (decode && res->flags & IORESOURCE_UNSET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) p = string_nocheck(p, pend, "size ", str_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) p = number(p, pend, resource_size(res), *specp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) p = number(p, pend, res->start, *specp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) if (res->start != res->end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) *p++ = '-';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) p = number(p, pend, res->end, *specp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) if (decode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) if (res->flags & IORESOURCE_MEM_64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) p = string_nocheck(p, pend, " 64bit", str_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) if (res->flags & IORESOURCE_PREFETCH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) p = string_nocheck(p, pend, " pref", str_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) if (res->flags & IORESOURCE_WINDOW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) p = string_nocheck(p, pend, " window", str_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) if (res->flags & IORESOURCE_DISABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) p = string_nocheck(p, pend, " disabled", str_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) p = string_nocheck(p, pend, " flags ", str_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) p = number(p, pend, res->flags, default_flag_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) *p++ = ']';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) *p = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) return string_nocheck(buf, end, sym, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) char *hex_string(char *buf, char *end, u8 *addr, struct printf_spec spec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) const char *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) int i, len = 1; /* if we pass '%ph[CDN]', field width remains
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) negative value, fallback to the default */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) char separator;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) if (spec.field_width == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) /* nothing to print */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) if (check_pointer(&buf, end, addr, spec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) switch (fmt[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) case 'C':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) separator = ':';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) case 'D':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) separator = '-';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) case 'N':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) separator = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) separator = ' ';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) if (spec.field_width > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) len = min_t(int, spec.field_width, 64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) for (i = 0; i < len; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) if (buf < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) *buf = hex_asc_hi(addr[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) ++buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) if (buf < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) *buf = hex_asc_lo(addr[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) ++buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) if (separator && i != len - 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) if (buf < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) *buf = separator;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) ++buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) char *bitmap_string(char *buf, char *end, unsigned long *bitmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) struct printf_spec spec, const char *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) const int CHUNKSZ = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) int nr_bits = max_t(int, spec.field_width, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) int i, chunksz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) bool first = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) if (check_pointer(&buf, end, bitmap, spec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) /* reused to print numbers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) spec = (struct printf_spec){ .flags = SMALL | ZEROPAD, .base = 16 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) chunksz = nr_bits & (CHUNKSZ - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) if (chunksz == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) chunksz = CHUNKSZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) i = ALIGN(nr_bits, CHUNKSZ) - CHUNKSZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) for (; i >= 0; i -= CHUNKSZ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) u32 chunkmask, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) int word, bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) chunkmask = ((1ULL << chunksz) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) word = i / BITS_PER_LONG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) bit = i % BITS_PER_LONG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) val = (bitmap[word] >> bit) & chunkmask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) if (!first) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) if (buf < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) *buf = ',';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) buf++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) first = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) spec.field_width = DIV_ROUND_UP(chunksz, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) buf = number(buf, end, val, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) chunksz = CHUNKSZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) char *bitmap_list_string(char *buf, char *end, unsigned long *bitmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) struct printf_spec spec, const char *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) int nr_bits = max_t(int, spec.field_width, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) /* current bit is 'cur', most recently seen range is [rbot, rtop] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) int cur, rbot, rtop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) bool first = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) if (check_pointer(&buf, end, bitmap, spec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) rbot = cur = find_first_bit(bitmap, nr_bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) while (cur < nr_bits) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) rtop = cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) cur = find_next_bit(bitmap, nr_bits, cur + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) if (cur < nr_bits && cur <= rtop + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) if (!first) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) if (buf < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) *buf = ',';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) buf++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) first = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) buf = number(buf, end, rbot, default_dec_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) if (rbot < rtop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) if (buf < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) *buf = '-';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) buf++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) buf = number(buf, end, rtop, default_dec_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) rbot = cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) char *mac_address_string(char *buf, char *end, u8 *addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) struct printf_spec spec, const char *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) char mac_addr[sizeof("xx:xx:xx:xx:xx:xx")];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) char *p = mac_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) char separator;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) bool reversed = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) if (check_pointer(&buf, end, addr, spec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) switch (fmt[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) case 'F':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) separator = '-';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) case 'R':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) reversed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) /* fall through */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) separator = ':';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) for (i = 0; i < 6; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) if (reversed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) p = hex_byte_pack(p, addr[5 - i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) p = hex_byte_pack(p, addr[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) if (fmt[0] == 'M' && i != 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) *p++ = separator;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) *p = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) return string_nocheck(buf, end, mac_addr, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) char *ip4_string(char *p, const u8 *addr, const char *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) bool leading_zeros = (fmt[0] == 'i');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) int step;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) switch (fmt[2]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) case 'h':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) #ifdef __BIG_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) step = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) index = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) step = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) case 'l':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) index = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) step = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) case 'n':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) case 'b':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) step = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) char temp[4] __aligned(2); /* hold each IP quad in reverse order */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) int digits = put_dec_trunc8(temp, addr[index]) - temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) if (leading_zeros) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) if (digits < 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) *p++ = '0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) if (digits < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) *p++ = '0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) /* reverse the digits in the quad */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) while (digits--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) *p++ = temp[digits];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) if (i < 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) *p++ = '.';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) index += step;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) *p = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) return p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) char *ip6_compressed_string(char *p, const char *addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) int i, j, range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) unsigned char zerolength[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) int longest = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) int colonpos = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) u16 word;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) u8 hi, lo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) bool needcolon = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) bool useIPv4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) struct in6_addr in6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) memcpy(&in6, addr, sizeof(struct in6_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) useIPv4 = ipv6_addr_v4mapped(&in6) || ipv6_addr_is_isatap(&in6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) memset(zerolength, 0, sizeof(zerolength));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) if (useIPv4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) range = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) range = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) /* find position of longest 0 run */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) for (i = 0; i < range; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) for (j = i; j < range; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) if (in6.s6_addr16[j] != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) zerolength[i]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) for (i = 0; i < range; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) if (zerolength[i] > longest) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) longest = zerolength[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) colonpos = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) if (longest == 1) /* don't compress a single 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) colonpos = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) /* emit address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) for (i = 0; i < range; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) if (i == colonpos) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) if (needcolon || i == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) *p++ = ':';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) *p++ = ':';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) needcolon = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) i += longest - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) if (needcolon) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) *p++ = ':';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) needcolon = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) /* hex u16 without leading 0s */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) word = ntohs(in6.s6_addr16[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) hi = word >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) lo = word & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) if (hi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) if (hi > 0x0f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) p = hex_byte_pack(p, hi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) *p++ = hex_asc_lo(hi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) p = hex_byte_pack(p, lo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) else if (lo > 0x0f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) p = hex_byte_pack(p, lo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) *p++ = hex_asc_lo(lo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) needcolon = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) if (useIPv4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) if (needcolon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) *p++ = ':';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) p = ip4_string(p, &in6.s6_addr[12], "I4");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) *p = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) return p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) char *ip6_string(char *p, const char *addr, const char *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) for (i = 0; i < 8; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) p = hex_byte_pack(p, *addr++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) p = hex_byte_pack(p, *addr++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) if (fmt[0] == 'I' && i != 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) *p++ = ':';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) *p = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) return p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) char *ip6_addr_string(char *buf, char *end, const u8 *addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) struct printf_spec spec, const char *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) char ip6_addr[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) if (fmt[0] == 'I' && fmt[2] == 'c')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) ip6_compressed_string(ip6_addr, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) ip6_string(ip6_addr, addr, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) return string_nocheck(buf, end, ip6_addr, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) char *ip4_addr_string(char *buf, char *end, const u8 *addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) struct printf_spec spec, const char *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) char ip4_addr[sizeof("255.255.255.255")];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) ip4_string(ip4_addr, addr, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) return string_nocheck(buf, end, ip4_addr, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) char *ip6_addr_string_sa(char *buf, char *end, const struct sockaddr_in6 *sa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) struct printf_spec spec, const char *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) bool have_p = false, have_s = false, have_f = false, have_c = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) char ip6_addr[sizeof("[xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255]") +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) sizeof(":12345") + sizeof("/123456789") +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) sizeof("%1234567890")];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) char *p = ip6_addr, *pend = ip6_addr + sizeof(ip6_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) const u8 *addr = (const u8 *) &sa->sin6_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) char fmt6[2] = { fmt[0], '6' };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) u8 off = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) fmt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) while (isalpha(*++fmt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) switch (*fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) case 'p':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) have_p = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) case 'f':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) have_f = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) case 's':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) have_s = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) case 'c':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) have_c = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) if (have_p || have_s || have_f) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) *p = '[';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) off = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) if (fmt6[0] == 'I' && have_c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) p = ip6_compressed_string(ip6_addr + off, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) p = ip6_string(ip6_addr + off, addr, fmt6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) if (have_p || have_s || have_f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) *p++ = ']';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) if (have_p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) *p++ = ':';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) p = number(p, pend, ntohs(sa->sin6_port), spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) if (have_f) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) *p++ = '/';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) p = number(p, pend, ntohl(sa->sin6_flowinfo &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) IPV6_FLOWINFO_MASK), spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) if (have_s) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) *p++ = '%';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) p = number(p, pend, sa->sin6_scope_id, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) *p = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) return string_nocheck(buf, end, ip6_addr, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) char *ip4_addr_string_sa(char *buf, char *end, const struct sockaddr_in *sa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) struct printf_spec spec, const char *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) bool have_p = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) char *p, ip4_addr[sizeof("255.255.255.255") + sizeof(":12345")];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) char *pend = ip4_addr + sizeof(ip4_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) const u8 *addr = (const u8 *) &sa->sin_addr.s_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) char fmt4[3] = { fmt[0], '4', 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) fmt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) while (isalpha(*++fmt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) switch (*fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) case 'p':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) have_p = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) case 'h':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) case 'l':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) case 'n':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) case 'b':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) fmt4[2] = *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) p = ip4_string(ip4_addr, addr, fmt4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) if (have_p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) *p++ = ':';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) p = number(p, pend, ntohs(sa->sin_port), spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) *p = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) return string_nocheck(buf, end, ip4_addr, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) char *ip_addr_string(char *buf, char *end, const void *ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) struct printf_spec spec, const char *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) char *err_fmt_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) if (check_pointer(&buf, end, ptr, spec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) switch (fmt[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) case '6':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) return ip6_addr_string(buf, end, ptr, spec, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) case '4':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) return ip4_addr_string(buf, end, ptr, spec, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) case 'S': {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) const union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) struct sockaddr raw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) struct sockaddr_in v4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) struct sockaddr_in6 v6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) } *sa = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) switch (sa->raw.sa_family) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) case AF_INET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) return ip4_addr_string_sa(buf, end, &sa->v4, spec, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) case AF_INET6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) return ip6_addr_string_sa(buf, end, &sa->v6, spec, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) return error_string(buf, end, "(einval)", spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) }}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) err_fmt_msg = fmt[0] == 'i' ? "(%pi?)" : "(%pI?)";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) return error_string(buf, end, err_fmt_msg, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) char *escaped_string(char *buf, char *end, u8 *addr, struct printf_spec spec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) const char *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) bool found = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) int count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) unsigned int flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) if (spec.field_width == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) return buf; /* nothing to print */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) if (check_pointer(&buf, end, addr, spec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) switch (fmt[count++]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) case 'a':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) flags |= ESCAPE_ANY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) case 'c':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) flags |= ESCAPE_SPECIAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) case 'h':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) flags |= ESCAPE_HEX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) case 'n':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) flags |= ESCAPE_NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) case 'o':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) flags |= ESCAPE_OCTAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) case 'p':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) flags |= ESCAPE_NP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) case 's':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) flags |= ESCAPE_SPACE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) found = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) } while (found);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) if (!flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) flags = ESCAPE_ANY_NP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) len = spec.field_width < 0 ? 1 : spec.field_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) * string_escape_mem() writes as many characters as it can to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) * the given buffer, and returns the total size of the output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) * had the buffer been big enough.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) buf += string_escape_mem(addr, len, buf, buf < end ? end - buf : 0, flags, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) static char *va_format(char *buf, char *end, struct va_format *va_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) struct printf_spec spec, const char *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) va_list va;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) if (check_pointer(&buf, end, va_fmt, spec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) va_copy(va, *va_fmt->va);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) buf += vsnprintf(buf, end > buf ? end - buf : 0, va_fmt->fmt, va);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) va_end(va);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) char *uuid_string(char *buf, char *end, const u8 *addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) struct printf_spec spec, const char *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) char uuid[UUID_STRING_LEN + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) char *p = uuid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) const u8 *index = uuid_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) bool uc = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) if (check_pointer(&buf, end, addr, spec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) switch (*(++fmt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) case 'L':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) uc = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) /* fall through */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) case 'l':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) index = guid_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) case 'B':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) uc = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) for (i = 0; i < 16; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) if (uc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) p = hex_byte_pack_upper(p, addr[index[i]]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) p = hex_byte_pack(p, addr[index[i]]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) switch (i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) case 7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) case 9:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) *p++ = '-';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) *p = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) return string_nocheck(buf, end, uuid, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) char *netdev_bits(char *buf, char *end, const void *addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) struct printf_spec spec, const char *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) unsigned long long num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) if (check_pointer(&buf, end, addr, spec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) switch (fmt[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) case 'F':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) num = *(const netdev_features_t *)addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) size = sizeof(netdev_features_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) return error_string(buf, end, "(%pN?)", spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) return special_hex_number(buf, end, num, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) char *address_val(char *buf, char *end, const void *addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) struct printf_spec spec, const char *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) unsigned long long num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) if (check_pointer(&buf, end, addr, spec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) switch (fmt[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) case 'd':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) num = *(const dma_addr_t *)addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) size = sizeof(dma_addr_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) case 'p':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) num = *(const phys_addr_t *)addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) size = sizeof(phys_addr_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) return special_hex_number(buf, end, num, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) char *date_str(char *buf, char *end, const struct rtc_time *tm, bool r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) int year = tm->tm_year + (r ? 0 : 1900);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) int mon = tm->tm_mon + (r ? 0 : 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) buf = number(buf, end, year, default_dec04_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) if (buf < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) *buf = '-';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) buf++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) buf = number(buf, end, mon, default_dec02_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) if (buf < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) *buf = '-';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) buf++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) return number(buf, end, tm->tm_mday, default_dec02_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) char *time_str(char *buf, char *end, const struct rtc_time *tm, bool r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) buf = number(buf, end, tm->tm_hour, default_dec02_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) if (buf < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) *buf = ':';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) buf++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) buf = number(buf, end, tm->tm_min, default_dec02_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) if (buf < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) *buf = ':';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) buf++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) return number(buf, end, tm->tm_sec, default_dec02_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) char *rtc_str(char *buf, char *end, const struct rtc_time *tm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) struct printf_spec spec, const char *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) bool have_t = true, have_d = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) bool raw = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) int count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) if (check_pointer(&buf, end, tm, spec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) switch (fmt[count]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) case 'd':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) have_t = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) case 't':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) have_d = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) raw = fmt[count] == 'r';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) if (have_d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) buf = date_str(buf, end, tm, raw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) if (have_d && have_t) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) /* Respect ISO 8601 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) if (buf < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) *buf = 'T';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) buf++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) if (have_t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) buf = time_str(buf, end, tm, raw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) char *time64_str(char *buf, char *end, const time64_t time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) struct printf_spec spec, const char *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) struct rtc_time rtc_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) struct tm tm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) time64_to_tm(time, 0, &tm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) rtc_time.tm_sec = tm.tm_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) rtc_time.tm_min = tm.tm_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) rtc_time.tm_hour = tm.tm_hour;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) rtc_time.tm_mday = tm.tm_mday;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) rtc_time.tm_mon = tm.tm_mon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) rtc_time.tm_year = tm.tm_year;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) rtc_time.tm_wday = tm.tm_wday;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) rtc_time.tm_yday = tm.tm_yday;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) rtc_time.tm_isdst = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) return rtc_str(buf, end, &rtc_time, spec, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) char *time_and_date(char *buf, char *end, void *ptr, struct printf_spec spec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) const char *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) switch (fmt[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) case 'R':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) return rtc_str(buf, end, (const struct rtc_time *)ptr, spec, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) case 'T':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) return time64_str(buf, end, *(const time64_t *)ptr, spec, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) return error_string(buf, end, "(%pt?)", spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) char *clock(char *buf, char *end, struct clk *clk, struct printf_spec spec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) const char *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) if (!IS_ENABLED(CONFIG_HAVE_CLK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) return error_string(buf, end, "(%pC?)", spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) if (check_pointer(&buf, end, clk, spec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) switch (fmt[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) case 'n':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) #ifdef CONFIG_COMMON_CLK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) return string(buf, end, __clk_get_name(clk), spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) return ptr_to_id(buf, end, clk, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) char *format_flags(char *buf, char *end, unsigned long flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) const struct trace_print_flags *names)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) unsigned long mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) for ( ; flags && names->name; names++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) mask = names->mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) if ((flags & mask) != mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) buf = string(buf, end, names->name, default_str_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) flags &= ~mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) if (flags) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) if (buf < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) *buf = '|';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) buf++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) if (flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) buf = number(buf, end, flags, default_flag_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) char *flags_string(char *buf, char *end, void *flags_ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) struct printf_spec spec, const char *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) const struct trace_print_flags *names;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) if (check_pointer(&buf, end, flags_ptr, spec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) switch (fmt[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) case 'p':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) flags = *(unsigned long *)flags_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) /* Remove zone id */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) flags &= (1UL << NR_PAGEFLAGS) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) names = pageflag_names;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) case 'v':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) flags = *(unsigned long *)flags_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) names = vmaflag_names;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) case 'g':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) flags = (__force unsigned long)(*(gfp_t *)flags_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) names = gfpflag_names;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) return error_string(buf, end, "(%pG?)", spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) return format_flags(buf, end, flags, names);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) char *fwnode_full_name_string(struct fwnode_handle *fwnode, char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) char *end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) int depth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) /* Loop starting from the root node to the current node. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) for (depth = fwnode_count_parents(fwnode); depth >= 0; depth--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) struct fwnode_handle *__fwnode =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) fwnode_get_nth_parent(fwnode, depth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) buf = string(buf, end, fwnode_get_name_prefix(__fwnode),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) default_str_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) buf = string(buf, end, fwnode_get_name(__fwnode),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) default_str_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) fwnode_handle_put(__fwnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) char *device_node_string(char *buf, char *end, struct device_node *dn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) struct printf_spec spec, const char *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) char tbuf[sizeof("xxxx") + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) const char *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) char *buf_start = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) bool has_mult, pass;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) struct printf_spec str_spec = spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) str_spec.field_width = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) if (fmt[0] != 'F')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) return error_string(buf, end, "(%pO?)", spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) if (!IS_ENABLED(CONFIG_OF))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) return error_string(buf, end, "(%pOF?)", spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) if (check_pointer(&buf, end, dn, spec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) /* simple case without anything any more format specifiers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) fmt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) if (fmt[0] == '\0' || strcspn(fmt,"fnpPFcC") > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) fmt = "f";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) for (pass = false; strspn(fmt,"fnpPFcC"); fmt++, pass = true) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) int precision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) if (pass) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) if (buf < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) *buf = ':';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) buf++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) switch (*fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) case 'f': /* full_name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) buf = fwnode_full_name_string(of_fwnode_handle(dn), buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) case 'n': /* name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) p = fwnode_get_name(of_fwnode_handle(dn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) precision = str_spec.precision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) str_spec.precision = strchrnul(p, '@') - p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) buf = string(buf, end, p, str_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) str_spec.precision = precision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) case 'p': /* phandle */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) buf = number(buf, end, (unsigned int)dn->phandle, default_dec_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) case 'P': /* path-spec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) p = fwnode_get_name(of_fwnode_handle(dn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) if (!p[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) p = "/";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) buf = string(buf, end, p, str_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) case 'F': /* flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) tbuf[0] = of_node_check_flag(dn, OF_DYNAMIC) ? 'D' : '-';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) tbuf[1] = of_node_check_flag(dn, OF_DETACHED) ? 'd' : '-';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) tbuf[2] = of_node_check_flag(dn, OF_POPULATED) ? 'P' : '-';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) tbuf[3] = of_node_check_flag(dn, OF_POPULATED_BUS) ? 'B' : '-';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) tbuf[4] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) buf = string_nocheck(buf, end, tbuf, str_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) case 'c': /* major compatible string */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) ret = of_property_read_string(dn, "compatible", &p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) buf = string(buf, end, p, str_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) case 'C': /* full compatible string */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) has_mult = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) of_property_for_each_string(dn, "compatible", prop, p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) if (has_mult)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) buf = string_nocheck(buf, end, ",", str_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) buf = string_nocheck(buf, end, "\"", str_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) buf = string(buf, end, p, str_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) buf = string_nocheck(buf, end, "\"", str_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) has_mult = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) return widen_string(buf, buf - buf_start, end, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) char *fwnode_string(char *buf, char *end, struct fwnode_handle *fwnode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) struct printf_spec spec, const char *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) struct printf_spec str_spec = spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) char *buf_start = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) str_spec.field_width = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) if (*fmt != 'w')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) return error_string(buf, end, "(%pf?)", spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) if (check_pointer(&buf, end, fwnode, spec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) fmt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) switch (*fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) case 'P': /* name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) buf = string(buf, end, fwnode_get_name(fwnode), str_spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) case 'f': /* full_name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) buf = fwnode_full_name_string(fwnode, buf, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) return widen_string(buf, buf - buf_start, end, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) /* Disable pointer hashing if requested */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) bool no_hash_pointers __ro_after_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) EXPORT_SYMBOL_GPL(no_hash_pointers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) static int __init no_hash_pointers_enable(char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) no_hash_pointers = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) pr_warn("**********************************************************\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) pr_warn("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) pr_warn("** **\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) pr_warn("** This system shows unhashed kernel memory addresses **\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) pr_warn("** via the console, logs, and other interfaces. This **\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) pr_warn("** might reduce the security of your system. **\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) pr_warn("** **\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) pr_warn("** If you see this message and you are not debugging **\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) pr_warn("** the kernel, report this immediately to your system **\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) pr_warn("** administrator! **\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) pr_warn("** **\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) pr_warn("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) pr_warn("**********************************************************\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) early_param("no_hash_pointers", no_hash_pointers_enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) * Show a '%p' thing. A kernel extension is that the '%p' is followed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) * by an extra set of alphanumeric characters that are extended format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) * specifiers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) * Please update scripts/checkpatch.pl when adding/removing conversion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) * characters. (Search for "check for vsprintf extension").
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) * Right now we handle:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) * - 'S' For symbolic direct pointers (or function descriptors) with offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) * - 's' For symbolic direct pointers (or function descriptors) without offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) * - '[Ss]R' as above with __builtin_extract_return_addr() translation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) * - '[Ff]' %pf and %pF were obsoleted and later removed in favor of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) * %ps and %pS. Be careful when re-using these specifiers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) * - 'B' For backtraced symbolic direct pointers with offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) * - 'R' For decoded struct resource, e.g., [mem 0x0-0x1f 64bit pref]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) * - 'r' For raw struct resource, e.g., [mem 0x0-0x1f flags 0x201]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) * - 'b[l]' For a bitmap, the number of bits is determined by the field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) * width which must be explicitly specified either as part of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) * format string '%32b[l]' or through '%*b[l]', [l] selects
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) * range-list format instead of hex format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) * - 'M' For a 6-byte MAC address, it prints the address in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) * usual colon-separated hex notation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) * - 'm' For a 6-byte MAC address, it prints the hex address without colons
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) * - 'MF' For a 6-byte MAC FDDI address, it prints the address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) * with a dash-separated hex notation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) * - '[mM]R' For a 6-byte MAC address, Reverse order (Bluetooth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) * IPv4 uses dot-separated decimal without leading 0's (1.2.3.4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) * IPv6 uses colon separated network-order 16 bit hex with leading 0's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) * [S][pfs]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) * Generic IPv4/IPv6 address (struct sockaddr *) that falls back to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) * [4] or [6] and is able to print port [p], flowinfo [f], scope [s]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) * - 'i' [46] for 'raw' IPv4/IPv6 addresses
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) * IPv6 omits the colons (01020304...0f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) * IPv4 uses dot-separated decimal with leading 0's (010.123.045.006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) * [S][pfs]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) * Generic IPv4/IPv6 address (struct sockaddr *) that falls back to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) * [4] or [6] and is able to print port [p], flowinfo [f], scope [s]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) * - '[Ii][4S][hnbl]' IPv4 addresses in host, network, big or little endian order
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) * - 'I[6S]c' for IPv6 addresses printed as specified by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) * https://tools.ietf.org/html/rfc5952
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) * - 'E[achnops]' For an escaped buffer, where rules are defined by combination
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) * of the following flags (see string_escape_mem() for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) * details):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) * a - ESCAPE_ANY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) * c - ESCAPE_SPECIAL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) * h - ESCAPE_HEX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) * n - ESCAPE_NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) * o - ESCAPE_OCTAL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) * p - ESCAPE_NP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) * s - ESCAPE_SPACE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) * By default ESCAPE_ANY_NP is used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) * "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) * Options for %pU are:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) * b big endian lower case hex (default)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) * B big endian UPPER case hex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) * l little endian lower case hex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) * L little endian UPPER case hex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) * big endian output byte order is:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) * [0][1][2][3]-[4][5]-[6][7]-[8][9]-[10][11][12][13][14][15]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) * little endian output byte order is:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) * [3][2][1][0]-[5][4]-[7][6]-[8][9]-[10][11][12][13][14][15]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) * - 'V' For a struct va_format which contains a format string * and va_list *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) * call vsnprintf(->format, *->va_list).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) * Implements a "recursive vsnprintf".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) * Do not use this feature without some mechanism to verify the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) * correctness of the format string and va_list arguments.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) * - 'K' For a kernel pointer that should be hidden from unprivileged users
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) * - 'NF' For a netdev_features_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) * - 'h[CDN]' For a variable-length buffer, it prints it as a hex string with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) * a certain separator (' ' by default):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) * C colon
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) * D dash
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) * N no separator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) * The maximum supported length is 64 bytes of the input. Consider
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) * to use print_hex_dump() for the larger input.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) * - 'a[pd]' For address types [p] phys_addr_t, [d] dma_addr_t and derivatives
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) * (default assumed to be phys_addr_t, passed by reference)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) * - 'd[234]' For a dentry name (optionally 2-4 last components)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) * - 'D[234]' Same as 'd' but for a struct file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) * - 'g' For block_device name (gendisk + partition number)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) * - 't[RT][dt][r]' For time and date as represented by:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) * R struct rtc_time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) * T time64_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) * - 'C' For a clock, it prints the name (Common Clock Framework) or address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) * (legacy clock framework) of the clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) * - 'Cn' For a clock, it prints the name (Common Clock Framework) or address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) * (legacy clock framework) of the clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) * - 'G' For flags to be printed as a collection of symbolic strings that would
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) * construct the specific value. Supported flags given by option:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) * p page flags (see struct page) given as pointer to unsigned long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) * g gfp flags (GFP_* and __GFP_*) given as pointer to gfp_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) * v vma flags (VM_*) given as pointer to unsigned long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) * - 'OF[fnpPcCF]' For a device tree object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) * Without any optional arguments prints the full_name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) * f device node full_name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) * n device node name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) * p device node phandle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) * P device node path spec (name + @unit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) * F device node flags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) * c major compatible string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) * C full compatible string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) * - 'fw[fP]' For a firmware node (struct fwnode_handle) pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) * Without an option prints the full name of the node
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) * f full name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) * P node name, including a possible unit address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) * - 'x' For printing the address. Equivalent to "%lx".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) * - '[ku]s' For a BPF/tracing related format specifier, e.g. used out of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) * bpf_trace_printk() where [ku] prefix specifies either kernel (k)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) * or user (u) memory to probe, and:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) * s a string, equivalent to "%s" on direct vsnprintf() use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) * ** When making changes please also update:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) * Documentation/core-api/printk-formats.rst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) * Note: The default behaviour (unadorned %p) is to hash the address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) * rendering it useful as a unique identifier.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) char *pointer(const char *fmt, char *buf, char *end, void *ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) struct printf_spec spec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) switch (*fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) case 'S':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) case 's':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) ptr = dereference_symbol_descriptor(ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) /* fall through */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) case 'B':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) return symbol_string(buf, end, ptr, spec, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) case 'R':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) case 'r':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) return resource_string(buf, end, ptr, spec, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) case 'h':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) return hex_string(buf, end, ptr, spec, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) case 'b':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) switch (fmt[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) case 'l':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) return bitmap_list_string(buf, end, ptr, spec, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) return bitmap_string(buf, end, ptr, spec, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) case 'M': /* Colon separated: 00:01:02:03:04:05 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) case 'm': /* Contiguous: 000102030405 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) /* [mM]F (FDDI) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) /* [mM]R (Reverse order; Bluetooth) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) return mac_address_string(buf, end, ptr, spec, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) case 'I': /* Formatted IP supported
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) * 4: 1.2.3.4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) * 6: 0001:0203:...:0708
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) * 6c: 1::708 or 1::1.2.3.4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) case 'i': /* Contiguous:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) * 4: 001.002.003.004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) * 6: 000102...0f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) return ip_addr_string(buf, end, ptr, spec, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) case 'E':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) return escaped_string(buf, end, ptr, spec, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) case 'U':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) return uuid_string(buf, end, ptr, spec, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) case 'V':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) return va_format(buf, end, ptr, spec, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) case 'K':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) return restricted_pointer(buf, end, ptr, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) case 'N':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) return netdev_bits(buf, end, ptr, spec, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) case 'a':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) return address_val(buf, end, ptr, spec, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) case 'd':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) return dentry_name(buf, end, ptr, spec, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) case 't':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) return time_and_date(buf, end, ptr, spec, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) case 'C':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) return clock(buf, end, ptr, spec, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) case 'D':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) return file_dentry_name(buf, end, ptr, spec, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) #ifdef CONFIG_BLOCK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) case 'g':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) return bdev_name(buf, end, ptr, spec, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) case 'G':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) return flags_string(buf, end, ptr, spec, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) case 'O':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) return device_node_string(buf, end, ptr, spec, fmt + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) case 'f':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) return fwnode_string(buf, end, ptr, spec, fmt + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) case 'x':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) return pointer_string(buf, end, ptr, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) case 'e':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) /* %pe with a non-ERR_PTR gets treated as plain %p */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) if (!IS_ERR(ptr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) return err_ptr(buf, end, ptr, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) case 'u':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) case 'k':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) switch (fmt[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) case 's':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) return string(buf, end, ptr, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) return error_string(buf, end, "(einval)", spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) * default is to _not_ leak addresses, so hash before printing,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) * unless no_hash_pointers is specified on the command line.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) if (unlikely(no_hash_pointers))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) return pointer_string(buf, end, ptr, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) return ptr_to_id(buf, end, ptr, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) * Helper function to decode printf style format.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) * Each call decode a token from the format and return the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) * number of characters read (or likely the delta where it wants
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) * to go on the next call).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) * The decoded token is returned through the parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) * 'h', 'l', or 'L' for integer fields
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) * 'z' support added 23/7/1999 S.H.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) * 'z' changed to 'Z' --davidm 1/25/99
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) * 'Z' changed to 'z' --adobriyan 2017-01-25
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) * 't' added for ptrdiff_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) * @fmt: the format string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) * @type of the token returned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) * @flags: various flags such as +, -, # tokens..
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) * @field_width: overwritten width
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) * @base: base of the number (octal, hex, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) * @precision: precision of a number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) * @qualifier: qualifier of a number (long, size_t, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383) static noinline_for_stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) int format_decode(const char *fmt, struct printf_spec *spec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) const char *start = fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) char qualifier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) /* we finished early by reading the field width */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) if (spec->type == FORMAT_TYPE_WIDTH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) if (spec->field_width < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) spec->field_width = -spec->field_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) spec->flags |= LEFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) spec->type = FORMAT_TYPE_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) goto precision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) /* we finished early by reading the precision */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) if (spec->type == FORMAT_TYPE_PRECISION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) if (spec->precision < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) spec->precision = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404) spec->type = FORMAT_TYPE_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) goto qualifier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) /* By default */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) spec->type = FORMAT_TYPE_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) for (; *fmt ; ++fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) if (*fmt == '%')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) /* Return the current non-format string */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417) if (fmt != start || !*fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418) return fmt - start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) /* Process flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) spec->flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) while (1) { /* this also skips first '%' */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) bool found = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426) ++fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) switch (*fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) case '-': spec->flags |= LEFT; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) case '+': spec->flags |= PLUS; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) case ' ': spec->flags |= SPACE; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) case '#': spec->flags |= SPECIAL; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) case '0': spec->flags |= ZEROPAD; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) default: found = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) if (!found)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) /* get field width */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) spec->field_width = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) if (isdigit(*fmt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445) spec->field_width = skip_atoi(&fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) else if (*fmt == '*') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) /* it's the next argument */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) spec->type = FORMAT_TYPE_WIDTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) return ++fmt - start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) precision:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453) /* get the precision */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454) spec->precision = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455) if (*fmt == '.') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) ++fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457) if (isdigit(*fmt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458) spec->precision = skip_atoi(&fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) if (spec->precision < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) spec->precision = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461) } else if (*fmt == '*') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) /* it's the next argument */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) spec->type = FORMAT_TYPE_PRECISION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464) return ++fmt - start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468) qualifier:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469) /* get the conversion qualifier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470) qualifier = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471) if (*fmt == 'h' || _tolower(*fmt) == 'l' ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472) *fmt == 'z' || *fmt == 't') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473) qualifier = *fmt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474) if (unlikely(qualifier == *fmt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475) if (qualifier == 'l') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476) qualifier = 'L';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) ++fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478) } else if (qualifier == 'h') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479) qualifier = 'H';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480) ++fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) /* default base */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486) spec->base = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487) switch (*fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488) case 'c':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) spec->type = FORMAT_TYPE_CHAR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) return ++fmt - start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) case 's':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493) spec->type = FORMAT_TYPE_STR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) return ++fmt - start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496) case 'p':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497) spec->type = FORMAT_TYPE_PTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498) return ++fmt - start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500) case '%':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) spec->type = FORMAT_TYPE_PERCENT_CHAR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502) return ++fmt - start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504) /* integer number formats - set up the flags and "break" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505) case 'o':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506) spec->base = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) case 'x':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510) spec->flags |= SMALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) /* fall through */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513) case 'X':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514) spec->base = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517) case 'd':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518) case 'i':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519) spec->flags |= SIGN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) case 'u':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) case 'n':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525) * Since %n poses a greater security risk than
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526) * utility, treat it as any other invalid or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527) * unsupported format specifier.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529) /* fall through */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532) WARN_ONCE(1, "Please remove unsupported %%%c in format string\n", *fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533) spec->type = FORMAT_TYPE_INVALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534) return fmt - start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537) if (qualifier == 'L')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538) spec->type = FORMAT_TYPE_LONG_LONG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539) else if (qualifier == 'l') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540) BUILD_BUG_ON(FORMAT_TYPE_ULONG + SIGN != FORMAT_TYPE_LONG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541) spec->type = FORMAT_TYPE_ULONG + (spec->flags & SIGN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542) } else if (qualifier == 'z') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543) spec->type = FORMAT_TYPE_SIZE_T;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) } else if (qualifier == 't') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545) spec->type = FORMAT_TYPE_PTRDIFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546) } else if (qualifier == 'H') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547) BUILD_BUG_ON(FORMAT_TYPE_UBYTE + SIGN != FORMAT_TYPE_BYTE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548) spec->type = FORMAT_TYPE_UBYTE + (spec->flags & SIGN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549) } else if (qualifier == 'h') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) BUILD_BUG_ON(FORMAT_TYPE_USHORT + SIGN != FORMAT_TYPE_SHORT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551) spec->type = FORMAT_TYPE_USHORT + (spec->flags & SIGN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) BUILD_BUG_ON(FORMAT_TYPE_UINT + SIGN != FORMAT_TYPE_INT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554) spec->type = FORMAT_TYPE_UINT + (spec->flags & SIGN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557) return ++fmt - start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) set_field_width(struct printf_spec *spec, int width)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563) spec->field_width = width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) if (WARN_ONCE(spec->field_width != width, "field width %d too large", width)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565) spec->field_width = clamp(width, -FIELD_WIDTH_MAX, FIELD_WIDTH_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) set_precision(struct printf_spec *spec, int prec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572) spec->precision = prec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573) if (WARN_ONCE(spec->precision != prec, "precision %d too large", prec)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574) spec->precision = clamp(prec, 0, PRECISION_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579) * vsnprintf - Format a string and place it in a buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580) * @buf: The buffer to place the result into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) * @size: The size of the buffer, including the trailing null space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582) * @fmt: The format string to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583) * @args: Arguments for the format string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585) * This function generally follows C99 vsnprintf, but has some
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586) * extensions and a few limitations:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588) * - ``%n`` is unsupported
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589) * - ``%p*`` is handled by pointer()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591) * See pointer() or Documentation/core-api/printk-formats.rst for more
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592) * extensive description.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594) * **Please update the documentation in both places when making changes**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) * The return value is the number of characters which would
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597) * be generated for the given input, excluding the trailing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598) * '\0', as per ISO C99. If you want to have the exact
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599) * number of characters written into @buf as return value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600) * (not including the trailing '\0'), use vscnprintf(). If the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601) * return is greater than or equal to @size, the resulting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) * string is truncated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604) * If you're not already dealing with a va_list consider using snprintf().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606) int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608) unsigned long long num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609) char *str, *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610) struct printf_spec spec = {0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612) /* Reject out-of-range values early. Large positive sizes are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) used for unknown buffer sizes. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) if (WARN_ON_ONCE(size > INT_MAX))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617) str = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618) end = buf + size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620) /* Make sure end is always >= buf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621) if (end < buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622) end = ((void *)-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623) size = end - buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) while (*fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627) const char *old_fmt = fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) int read = format_decode(fmt, &spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630) fmt += read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632) switch (spec.type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633) case FORMAT_TYPE_NONE: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634) int copy = read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635) if (str < end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636) if (copy > end - str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637) copy = end - str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638) memcpy(str, old_fmt, copy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640) str += read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644) case FORMAT_TYPE_WIDTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645) set_field_width(&spec, va_arg(args, int));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648) case FORMAT_TYPE_PRECISION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649) set_precision(&spec, va_arg(args, int));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652) case FORMAT_TYPE_CHAR: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653) char c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655) if (!(spec.flags & LEFT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656) while (--spec.field_width > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657) if (str < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658) *str = ' ';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659) ++str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663) c = (unsigned char) va_arg(args, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664) if (str < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665) *str = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666) ++str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667) while (--spec.field_width > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2668) if (str < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2669) *str = ' ';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2670) ++str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2672) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2675) case FORMAT_TYPE_STR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2676) str = string(str, end, va_arg(args, char *), spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2677) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2679) case FORMAT_TYPE_PTR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2680) str = pointer(fmt, str, end, va_arg(args, void *),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2681) spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2682) while (isalnum(*fmt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2683) fmt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2684) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2686) case FORMAT_TYPE_PERCENT_CHAR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2687) if (str < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2688) *str = '%';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2689) ++str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2690) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2692) case FORMAT_TYPE_INVALID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2693) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2694) * Presumably the arguments passed gcc's type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2695) * checking, but there is no safe or sane way
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2696) * for us to continue parsing the format and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2697) * fetching from the va_list; the remaining
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2698) * specifiers and arguments would be out of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2699) * sync.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2700) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2701) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2703) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2704) switch (spec.type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2705) case FORMAT_TYPE_LONG_LONG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2706) num = va_arg(args, long long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2707) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2708) case FORMAT_TYPE_ULONG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2709) num = va_arg(args, unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2710) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2711) case FORMAT_TYPE_LONG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2712) num = va_arg(args, long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2713) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2714) case FORMAT_TYPE_SIZE_T:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2715) if (spec.flags & SIGN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2716) num = va_arg(args, ssize_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2717) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2718) num = va_arg(args, size_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2719) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2720) case FORMAT_TYPE_PTRDIFF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2721) num = va_arg(args, ptrdiff_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2722) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2723) case FORMAT_TYPE_UBYTE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2724) num = (unsigned char) va_arg(args, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2725) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2726) case FORMAT_TYPE_BYTE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2727) num = (signed char) va_arg(args, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2728) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2729) case FORMAT_TYPE_USHORT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2730) num = (unsigned short) va_arg(args, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2731) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2732) case FORMAT_TYPE_SHORT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2733) num = (short) va_arg(args, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2734) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2735) case FORMAT_TYPE_INT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2736) num = (int) va_arg(args, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2737) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2738) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2739) num = va_arg(args, unsigned int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2742) str = number(str, end, num, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2746) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2747) if (size > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2748) if (str < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2749) *str = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2750) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2751) end[-1] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2754) /* the trailing null byte doesn't count towards the total */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2755) return str-buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2757) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2758) EXPORT_SYMBOL(vsnprintf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2760) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2761) * vscnprintf - Format a string and place it in a buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2762) * @buf: The buffer to place the result into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2763) * @size: The size of the buffer, including the trailing null space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2764) * @fmt: The format string to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2765) * @args: Arguments for the format string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2766) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2767) * The return value is the number of characters which have been written into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2768) * the @buf not including the trailing '\0'. If @size is == 0 the function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2769) * returns 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2770) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2771) * If you're not already dealing with a va_list consider using scnprintf().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2772) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2773) * See the vsnprintf() documentation for format string extensions over C99.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2774) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2775) int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2776) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2777) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2779) i = vsnprintf(buf, size, fmt, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2781) if (likely(i < size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2782) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2783) if (size != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2784) return size - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2785) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2787) EXPORT_SYMBOL(vscnprintf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2789) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2790) * snprintf - Format a string and place it in a buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2791) * @buf: The buffer to place the result into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2792) * @size: The size of the buffer, including the trailing null space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2793) * @fmt: The format string to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2794) * @...: Arguments for the format string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2795) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2796) * The return value is the number of characters which would be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2797) * generated for the given input, excluding the trailing null,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2798) * as per ISO C99. If the return is greater than or equal to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2799) * @size, the resulting string is truncated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2800) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2801) * See the vsnprintf() documentation for format string extensions over C99.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2802) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2803) int snprintf(char *buf, size_t size, const char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2804) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2805) va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2806) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2808) va_start(args, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2809) i = vsnprintf(buf, size, fmt, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2810) va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2812) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2813) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2814) EXPORT_SYMBOL(snprintf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2816) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2817) * scnprintf - Format a string and place it in a buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2818) * @buf: The buffer to place the result into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2819) * @size: The size of the buffer, including the trailing null space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2820) * @fmt: The format string to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2821) * @...: Arguments for the format string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2822) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2823) * The return value is the number of characters written into @buf not including
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2824) * the trailing '\0'. If @size is == 0 the function returns 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2825) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2827) int scnprintf(char *buf, size_t size, const char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2828) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2829) va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2830) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2832) va_start(args, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2833) i = vscnprintf(buf, size, fmt, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2834) va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2836) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2837) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2838) EXPORT_SYMBOL(scnprintf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2840) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2841) * vsprintf - Format a string and place it in a buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2842) * @buf: The buffer to place the result into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2843) * @fmt: The format string to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2844) * @args: Arguments for the format string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2845) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2846) * The function returns the number of characters written
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2847) * into @buf. Use vsnprintf() or vscnprintf() in order to avoid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2848) * buffer overflows.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2849) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2850) * If you're not already dealing with a va_list consider using sprintf().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2851) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2852) * See the vsnprintf() documentation for format string extensions over C99.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2853) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2854) int vsprintf(char *buf, const char *fmt, va_list args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2855) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2856) return vsnprintf(buf, INT_MAX, fmt, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2857) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2858) EXPORT_SYMBOL(vsprintf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2860) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2861) * sprintf - Format a string and place it in a buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2862) * @buf: The buffer to place the result into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2863) * @fmt: The format string to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2864) * @...: Arguments for the format string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2865) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2866) * The function returns the number of characters written
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2867) * into @buf. Use snprintf() or scnprintf() in order to avoid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2868) * buffer overflows.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2869) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2870) * See the vsnprintf() documentation for format string extensions over C99.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2871) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2872) int sprintf(char *buf, const char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2873) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2874) va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2875) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2877) va_start(args, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2878) i = vsnprintf(buf, INT_MAX, fmt, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2879) va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2881) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2882) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2883) EXPORT_SYMBOL(sprintf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2885) #ifdef CONFIG_BINARY_PRINTF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2886) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2887) * bprintf service:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2888) * vbin_printf() - VA arguments to binary data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2889) * bstr_printf() - Binary data to text string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2890) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2892) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2893) * vbin_printf - Parse a format string and place args' binary value in a buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2894) * @bin_buf: The buffer to place args' binary value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2895) * @size: The size of the buffer(by words(32bits), not characters)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2896) * @fmt: The format string to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2897) * @args: Arguments for the format string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2898) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2899) * The format follows C99 vsnprintf, except %n is ignored, and its argument
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2900) * is skipped.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2901) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2902) * The return value is the number of words(32bits) which would be generated for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2903) * the given input.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2904) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2905) * NOTE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2906) * If the return value is greater than @size, the resulting bin_buf is NOT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2907) * valid for bstr_printf().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2908) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2909) int vbin_printf(u32 *bin_buf, size_t size, const char *fmt, va_list args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2910) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2911) struct printf_spec spec = {0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2912) char *str, *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2913) int width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2915) str = (char *)bin_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2916) end = (char *)(bin_buf + size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2918) #define save_arg(type) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2919) ({ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2920) unsigned long long value; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2921) if (sizeof(type) == 8) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2922) unsigned long long val8; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2923) str = PTR_ALIGN(str, sizeof(u32)); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2924) val8 = va_arg(args, unsigned long long); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2925) if (str + sizeof(type) <= end) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2926) *(u32 *)str = *(u32 *)&val8; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2927) *(u32 *)(str + 4) = *((u32 *)&val8 + 1); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2928) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2929) value = val8; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2930) } else { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2931) unsigned int val4; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2932) str = PTR_ALIGN(str, sizeof(type)); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2933) val4 = va_arg(args, int); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2934) if (str + sizeof(type) <= end) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2935) *(typeof(type) *)str = (type)(long)val4; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2936) value = (unsigned long long)val4; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2937) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2938) str += sizeof(type); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2939) value; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2940) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2942) while (*fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2943) int read = format_decode(fmt, &spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2945) fmt += read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2947) switch (spec.type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2948) case FORMAT_TYPE_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2949) case FORMAT_TYPE_PERCENT_CHAR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2950) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2951) case FORMAT_TYPE_INVALID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2952) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2954) case FORMAT_TYPE_WIDTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2955) case FORMAT_TYPE_PRECISION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2956) width = (int)save_arg(int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2957) /* Pointers may require the width */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2958) if (*fmt == 'p')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2959) set_field_width(&spec, width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2960) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2962) case FORMAT_TYPE_CHAR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2963) save_arg(char);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2964) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2966) case FORMAT_TYPE_STR: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2967) const char *save_str = va_arg(args, char *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2968) const char *err_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2969) size_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2971) err_msg = check_pointer_msg(save_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2972) if (err_msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2973) save_str = err_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2975) len = strlen(save_str) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2976) if (str + len < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2977) memcpy(str, save_str, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2978) str += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2979) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2982) case FORMAT_TYPE_PTR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2983) /* Dereferenced pointers must be done now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2984) switch (*fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2985) /* Dereference of functions is still OK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2986) case 'S':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2987) case 's':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2988) case 'x':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2989) case 'K':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2990) case 'e':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2991) save_arg(void *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2992) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2993) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2994) if (!isalnum(*fmt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2995) save_arg(void *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2996) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2998) str = pointer(fmt, str, end, va_arg(args, void *),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2999) spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3000) if (str + 1 < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3001) *str++ = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3002) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3003) end[-1] = '\0'; /* Must be nul terminated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3004) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3005) /* skip all alphanumeric pointer suffixes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3006) while (isalnum(*fmt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3007) fmt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3008) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3010) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3011) switch (spec.type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3013) case FORMAT_TYPE_LONG_LONG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3014) save_arg(long long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3015) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3016) case FORMAT_TYPE_ULONG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3017) case FORMAT_TYPE_LONG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3018) save_arg(unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3019) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3020) case FORMAT_TYPE_SIZE_T:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3021) save_arg(size_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3022) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3023) case FORMAT_TYPE_PTRDIFF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3024) save_arg(ptrdiff_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3025) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3026) case FORMAT_TYPE_UBYTE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3027) case FORMAT_TYPE_BYTE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3028) save_arg(char);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3029) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3030) case FORMAT_TYPE_USHORT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3031) case FORMAT_TYPE_SHORT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3032) save_arg(short);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3033) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3034) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3035) save_arg(int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3036) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3037) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3038) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3040) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3041) return (u32 *)(PTR_ALIGN(str, sizeof(u32))) - bin_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3042) #undef save_arg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3043) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3044) EXPORT_SYMBOL_GPL(vbin_printf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3046) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3047) * bstr_printf - Format a string from binary arguments and place it in a buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3048) * @buf: The buffer to place the result into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3049) * @size: The size of the buffer, including the trailing null space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3050) * @fmt: The format string to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3051) * @bin_buf: Binary arguments for the format string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3052) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3053) * This function like C99 vsnprintf, but the difference is that vsnprintf gets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3054) * arguments from stack, and bstr_printf gets arguments from @bin_buf which is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3055) * a binary buffer that generated by vbin_printf.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3056) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3057) * The format follows C99 vsnprintf, but has some extensions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3058) * see vsnprintf comment for details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3059) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3060) * The return value is the number of characters which would
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3061) * be generated for the given input, excluding the trailing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3062) * '\0', as per ISO C99. If you want to have the exact
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3063) * number of characters written into @buf as return value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3064) * (not including the trailing '\0'), use vscnprintf(). If the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3065) * return is greater than or equal to @size, the resulting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3066) * string is truncated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3067) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3068) int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3069) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3070) struct printf_spec spec = {0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3071) char *str, *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3072) const char *args = (const char *)bin_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3074) if (WARN_ON_ONCE(size > INT_MAX))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3075) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3077) str = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3078) end = buf + size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3080) #define get_arg(type) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3081) ({ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3082) typeof(type) value; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3083) if (sizeof(type) == 8) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3084) args = PTR_ALIGN(args, sizeof(u32)); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3085) *(u32 *)&value = *(u32 *)args; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3086) *((u32 *)&value + 1) = *(u32 *)(args + 4); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3087) } else { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3088) args = PTR_ALIGN(args, sizeof(type)); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3089) value = *(typeof(type) *)args; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3090) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3091) args += sizeof(type); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3092) value; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3093) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3095) /* Make sure end is always >= buf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3096) if (end < buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3097) end = ((void *)-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3098) size = end - buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3099) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3101) while (*fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3102) const char *old_fmt = fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3103) int read = format_decode(fmt, &spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3105) fmt += read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3107) switch (spec.type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3108) case FORMAT_TYPE_NONE: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3109) int copy = read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3110) if (str < end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3111) if (copy > end - str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3112) copy = end - str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3113) memcpy(str, old_fmt, copy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3115) str += read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3116) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3119) case FORMAT_TYPE_WIDTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3120) set_field_width(&spec, get_arg(int));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3121) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3123) case FORMAT_TYPE_PRECISION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3124) set_precision(&spec, get_arg(int));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3125) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3127) case FORMAT_TYPE_CHAR: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3128) char c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3130) if (!(spec.flags & LEFT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3131) while (--spec.field_width > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3132) if (str < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3133) *str = ' ';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3134) ++str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3137) c = (unsigned char) get_arg(char);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3138) if (str < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3139) *str = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3140) ++str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3141) while (--spec.field_width > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3142) if (str < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3143) *str = ' ';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3144) ++str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3146) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3149) case FORMAT_TYPE_STR: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3150) const char *str_arg = args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3151) args += strlen(str_arg) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3152) str = string(str, end, (char *)str_arg, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3153) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3156) case FORMAT_TYPE_PTR: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3157) bool process = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3158) int copy, len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3159) /* Non function dereferences were already done */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3160) switch (*fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3161) case 'S':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3162) case 's':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3163) case 'x':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3164) case 'K':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3165) case 'e':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3166) process = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3167) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3168) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3169) if (!isalnum(*fmt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3170) process = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3171) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3173) /* Pointer dereference was already processed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3174) if (str < end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3175) len = copy = strlen(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3176) if (copy > end - str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3177) copy = end - str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3178) memcpy(str, args, copy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3179) str += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3180) args += len + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3183) if (process)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3184) str = pointer(fmt, str, end, get_arg(void *), spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3186) while (isalnum(*fmt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3187) fmt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3188) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3191) case FORMAT_TYPE_PERCENT_CHAR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3192) if (str < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3193) *str = '%';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3194) ++str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3195) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3197) case FORMAT_TYPE_INVALID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3198) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3200) default: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3201) unsigned long long num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3203) switch (spec.type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3205) case FORMAT_TYPE_LONG_LONG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3206) num = get_arg(long long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3207) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3208) case FORMAT_TYPE_ULONG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3209) case FORMAT_TYPE_LONG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3210) num = get_arg(unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3211) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3212) case FORMAT_TYPE_SIZE_T:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3213) num = get_arg(size_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3214) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3215) case FORMAT_TYPE_PTRDIFF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3216) num = get_arg(ptrdiff_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3217) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3218) case FORMAT_TYPE_UBYTE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3219) num = get_arg(unsigned char);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3220) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3221) case FORMAT_TYPE_BYTE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3222) num = get_arg(signed char);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3223) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3224) case FORMAT_TYPE_USHORT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3225) num = get_arg(unsigned short);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3226) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3227) case FORMAT_TYPE_SHORT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3228) num = get_arg(short);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3229) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3230) case FORMAT_TYPE_UINT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3231) num = get_arg(unsigned int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3232) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3233) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3234) num = get_arg(int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3237) str = number(str, end, num, spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3238) } /* default: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3239) } /* switch(spec.type) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3240) } /* while(*fmt) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3242) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3243) if (size > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3244) if (str < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3245) *str = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3246) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3247) end[-1] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3250) #undef get_arg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3252) /* the trailing null byte doesn't count towards the total */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3253) return str - buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3255) EXPORT_SYMBOL_GPL(bstr_printf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3257) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3258) * bprintf - Parse a format string and place args' binary value in a buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3259) * @bin_buf: The buffer to place args' binary value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3260) * @size: The size of the buffer(by words(32bits), not characters)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3261) * @fmt: The format string to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3262) * @...: Arguments for the format string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3263) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3264) * The function returns the number of words(u32) written
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3265) * into @bin_buf.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3266) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3267) int bprintf(u32 *bin_buf, size_t size, const char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3269) va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3270) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3272) va_start(args, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3273) ret = vbin_printf(bin_buf, size, fmt, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3274) va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3276) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3278) EXPORT_SYMBOL_GPL(bprintf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3280) #endif /* CONFIG_BINARY_PRINTF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3282) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3283) * vsscanf - Unformat a buffer into a list of arguments
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3284) * @buf: input buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3285) * @fmt: format of buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3286) * @args: arguments
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3287) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3288) int vsscanf(const char *buf, const char *fmt, va_list args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3290) const char *str = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3291) char *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3292) char digit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3293) int num = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3294) u8 qualifier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3295) unsigned int base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3296) union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3297) long long s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3298) unsigned long long u;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3299) } val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3300) s16 field_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3301) bool is_sign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3303) while (*fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3304) /* skip any white space in format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3305) /* white space in format matchs any amount of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3306) * white space, including none, in the input.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3307) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3308) if (isspace(*fmt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3309) fmt = skip_spaces(++fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3310) str = skip_spaces(str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3313) /* anything that is not a conversion must match exactly */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3314) if (*fmt != '%' && *fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3315) if (*fmt++ != *str++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3316) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3317) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3320) if (!*fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3321) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3322) ++fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3324) /* skip this conversion.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3325) * advance both strings to next white space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3326) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3327) if (*fmt == '*') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3328) if (!*str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3329) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3330) while (!isspace(*fmt) && *fmt != '%' && *fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3331) /* '%*[' not yet supported, invalid format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3332) if (*fmt == '[')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3333) return num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3334) fmt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3336) while (!isspace(*str) && *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3337) str++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3338) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3341) /* get field width */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3342) field_width = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3343) if (isdigit(*fmt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3344) field_width = skip_atoi(&fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3345) if (field_width <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3346) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3349) /* get conversion qualifier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3350) qualifier = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3351) if (*fmt == 'h' || _tolower(*fmt) == 'l' ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3352) *fmt == 'z') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3353) qualifier = *fmt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3354) if (unlikely(qualifier == *fmt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3355) if (qualifier == 'h') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3356) qualifier = 'H';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3357) fmt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3358) } else if (qualifier == 'l') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3359) qualifier = 'L';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3360) fmt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3365) if (!*fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3366) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3368) if (*fmt == 'n') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3369) /* return number of characters read so far */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3370) *va_arg(args, int *) = str - buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3371) ++fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3372) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3375) if (!*str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3376) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3378) base = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3379) is_sign = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3381) switch (*fmt++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3382) case 'c':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3384) char *s = (char *)va_arg(args, char*);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3385) if (field_width == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3386) field_width = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3387) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3388) *s++ = *str++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3389) } while (--field_width > 0 && *str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3390) num++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3392) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3393) case 's':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3394) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3395) char *s = (char *)va_arg(args, char *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3396) if (field_width == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3397) field_width = SHRT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3398) /* first, skip leading white space in buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3399) str = skip_spaces(str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3401) /* now copy until next white space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3402) while (*str && !isspace(*str) && field_width--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3403) *s++ = *str++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3404) *s = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3405) num++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3407) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3408) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3409) * Warning: This implementation of the '[' conversion specifier
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3410) * deviates from its glibc counterpart in the following ways:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3411) * (1) It does NOT support ranges i.e. '-' is NOT a special
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3412) * character
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3413) * (2) It cannot match the closing bracket ']' itself
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3414) * (3) A field width is required
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3415) * (4) '%*[' (discard matching input) is currently not supported
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3416) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3417) * Example usage:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3418) * ret = sscanf("00:0a:95","%2[^:]:%2[^:]:%2[^:]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3419) * buf1, buf2, buf3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3420) * if (ret < 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3421) * // etc..
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3422) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3423) case '[':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3424) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3425) char *s = (char *)va_arg(args, char *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3426) DECLARE_BITMAP(set, 256) = {0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3427) unsigned int len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3428) bool negate = (*fmt == '^');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3430) /* field width is required */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3431) if (field_width == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3432) return num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3434) if (negate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3435) ++fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3437) for ( ; *fmt && *fmt != ']'; ++fmt, ++len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3438) set_bit((u8)*fmt, set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3440) /* no ']' or no character set found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3441) if (!*fmt || !len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3442) return num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3443) ++fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3445) if (negate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3446) bitmap_complement(set, set, 256);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3447) /* exclude null '\0' byte */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3448) clear_bit(0, set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3451) /* match must be non-empty */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3452) if (!test_bit((u8)*str, set))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3453) return num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3455) while (test_bit((u8)*str, set) && field_width--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3456) *s++ = *str++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3457) *s = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3458) ++num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3460) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3461) case 'o':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3462) base = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3463) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3464) case 'x':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3465) case 'X':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3466) base = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3467) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3468) case 'i':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3469) base = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3470) /* fall through */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3471) case 'd':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3472) is_sign = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3473) /* fall through */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3474) case 'u':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3475) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3476) case '%':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3477) /* looking for '%' in str */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3478) if (*str++ != '%')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3479) return num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3480) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3481) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3482) /* invalid format; stop here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3483) return num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3486) /* have some sort of integer conversion.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3487) * first, skip white space in buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3488) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3489) str = skip_spaces(str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3491) digit = *str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3492) if (is_sign && digit == '-')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3493) digit = *(str + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3495) if (!digit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3496) || (base == 16 && !isxdigit(digit))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3497) || (base == 10 && !isdigit(digit))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3498) || (base == 8 && (!isdigit(digit) || digit > '7'))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3499) || (base == 0 && !isdigit(digit)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3500) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3502) if (is_sign)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3503) val.s = simple_strntoll(str,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3504) field_width >= 0 ? field_width : INT_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3505) &next, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3506) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3507) val.u = simple_strntoull(str,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3508) field_width >= 0 ? field_width : INT_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3509) &next, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3511) switch (qualifier) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3512) case 'H': /* that's 'hh' in format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3513) if (is_sign)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3514) *va_arg(args, signed char *) = val.s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3515) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3516) *va_arg(args, unsigned char *) = val.u;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3517) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3518) case 'h':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3519) if (is_sign)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3520) *va_arg(args, short *) = val.s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3521) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3522) *va_arg(args, unsigned short *) = val.u;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3523) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3524) case 'l':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3525) if (is_sign)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3526) *va_arg(args, long *) = val.s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3527) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3528) *va_arg(args, unsigned long *) = val.u;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3529) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3530) case 'L':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3531) if (is_sign)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3532) *va_arg(args, long long *) = val.s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3533) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3534) *va_arg(args, unsigned long long *) = val.u;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3535) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3536) case 'z':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3537) *va_arg(args, size_t *) = val.u;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3538) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3539) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3540) if (is_sign)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3541) *va_arg(args, int *) = val.s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3542) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3543) *va_arg(args, unsigned int *) = val.u;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3544) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3546) num++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3548) if (!next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3549) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3550) str = next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3553) return num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3555) EXPORT_SYMBOL(vsscanf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3557) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3558) * sscanf - Unformat a buffer into a list of arguments
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3559) * @buf: input buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3560) * @fmt: formatting of buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3561) * @...: resulting arguments
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3562) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3563) int sscanf(const char *buf, const char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3564) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3565) va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3566) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3568) va_start(args, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3569) i = vsscanf(buf, fmt, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3570) va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3572) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3574) EXPORT_SYMBOL(sscanf);