blob: 30e1bc22105cf15254600446f89d5e04d8ebc9d8 [file] [log] [blame]
Thomas Gleixner457c8992019-05-19 13:08:55 +01001// SPDX-License-Identifier: GPL-2.0-only
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/*
3 * linux/lib/vsprintf.c
4 *
5 * Copyright (C) 1991, 1992 Linus Torvalds
6 */
7
8/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
9/*
10 * Wirzenius wrote this portably, Torvalds fucked it up :-)
11 */
12
André Goddard Rosa7b9186f2009-12-14 18:00:57 -080013/*
Linus Torvalds1da177e2005-04-16 15:20:36 -070014 * Fri Jul 13 2001 Crutcher Dunnavant <crutcher+kernel@datastacks.com>
15 * - changed to provide snprintf and vsnprintf functions
16 * So Feb 1 16:51:32 CET 2004 Juergen Quade <quade@hsnr.de>
17 * - scnprintf and vscnprintf
18 */
19
20#include <stdarg.h>
Rasmus Villemoesef27ac12019-03-07 16:27:03 -080021#include <linux/build_bug.h>
Stephen Boyd0d1d7a52015-06-19 15:00:46 -070022#include <linux/clk.h>
Geert Uytterhoeven900cca22015-04-15 16:17:20 -070023#include <linux/clk-provider.h>
Rasmus Villemoes57f56772019-10-15 21:07:05 +020024#include <linux/errname.h>
Paul Gortmaker8bc3bcc2011-11-16 21:29:17 -050025#include <linux/module.h> /* for KSYM_SYMBOL_LEN */
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/types.h>
27#include <linux/string.h>
28#include <linux/ctype.h>
29#include <linux/kernel.h>
Linus Torvalds0fe1ef22008-07-06 16:43:12 -070030#include <linux/kallsyms.h>
Jan Beulich53809752012-12-17 16:01:31 -080031#include <linux/math64.h>
Linus Torvalds0fe1ef22008-07-06 16:43:12 -070032#include <linux/uaccess.h>
Linus Torvalds332d2e72008-10-20 15:07:34 +110033#include <linux/ioport.h>
Al Viro4b6ccca2013-09-03 12:00:44 -040034#include <linux/dcache.h>
Ryan Mallon312b4e22013-11-12 15:08:51 -080035#include <linux/cred.h>
Andy Shevchenko4d42c442018-12-04 23:23:11 +020036#include <linux/rtc.h>
Andy Shevchenko7daac5b2020-04-15 20:00:44 +030037#include <linux/time.h>
Andy Shevchenko2b1b0d62016-05-20 17:01:04 -070038#include <linux/uuid.h>
Pantelis Antoniouce4fecf2015-01-21 19:06:14 +020039#include <linux/of.h>
Joe Perches8a27f7c2009-08-17 12:29:44 +000040#include <net/addrconf.h>
Tobin C. Hardingad67b742017-11-01 15:32:23 +110041#include <linux/siphash.h>
42#include <linux/compiler.h>
Sakari Ailusa92eb762019-10-03 15:32:16 +030043#include <linux/property.h>
Dmitry Monakhov1031bc52015-04-13 16:31:35 +040044#ifdef CONFIG_BLOCK
45#include <linux/blkdev.h>
46#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070047
Vlastimil Babkaedf14cd2016-03-15 14:55:56 -070048#include "../mm/internal.h" /* For the trace_print_flags arrays */
49
Tim Schmielau4e57b682005-10-30 15:03:48 -080050#include <asm/page.h> /* for PAGE_SIZE */
Rasmus Villemoes7c43d9a2015-04-16 12:43:22 -070051#include <asm/byteorder.h> /* cpu_to_le16 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070052
Andy Shevchenko71dca952014-10-13 15:55:18 -070053#include <linux/string_helpers.h>
Alexey Dobriyan1dff46d2011-10-31 17:12:28 -070054#include "kstrtox.h"
Harvey Harrisonaa46a632008-10-16 13:40:34 -070055
Linus Torvalds1da177e2005-04-16 15:20:36 -070056/**
Linus Torvalds1da177e2005-04-16 15:20:36 -070057 * simple_strtoull - convert a string to an unsigned long long
58 * @cp: The start of the string
59 * @endp: A pointer to the end of the parsed string will be placed here
60 * @base: The number base to use
Eldad Zack462e4712012-12-17 16:03:05 -080061 *
Andy Shevchenkoe8cc2b92020-02-21 10:57:23 +020062 * This function has caveats. Please use kstrtoull instead.
Linus Torvalds1da177e2005-04-16 15:20:36 -070063 */
Alexey Dobriyanad65dce2021-06-30 18:56:04 -070064noinline
Harvey Harrison22d27052008-10-16 13:40:35 -070065unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070066{
Alexey Dobriyan1dff46d2011-10-31 17:12:28 -070067 unsigned long long result;
68 unsigned int rv;
Linus Torvalds1da177e2005-04-16 15:20:36 -070069
Alexey Dobriyan1dff46d2011-10-31 17:12:28 -070070 cp = _parse_integer_fixup_radix(cp, &base);
71 rv = _parse_integer(cp, base, &result);
72 /* FIXME */
73 cp += (rv & ~KSTRTOX_OVERFLOW);
Harvey Harrisonaa46a632008-10-16 13:40:34 -070074
Linus Torvalds1da177e2005-04-16 15:20:36 -070075 if (endp)
76 *endp = (char *)cp;
André Goddard Rosa7b9186f2009-12-14 18:00:57 -080077
Linus Torvalds1da177e2005-04-16 15:20:36 -070078 return result;
79}
Linus Torvalds1da177e2005-04-16 15:20:36 -070080EXPORT_SYMBOL(simple_strtoull);
81
82/**
André Goddard Rosa922ac252009-12-14 18:01:01 -080083 * simple_strtoul - convert a string to an unsigned long
84 * @cp: The start of the string
85 * @endp: A pointer to the end of the parsed string will be placed here
86 * @base: The number base to use
Eldad Zack462e4712012-12-17 16:03:05 -080087 *
Andy Shevchenkoe8cc2b92020-02-21 10:57:23 +020088 * This function has caveats. Please use kstrtoul instead.
André Goddard Rosa922ac252009-12-14 18:01:01 -080089 */
90unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base)
91{
92 return simple_strtoull(cp, endp, base);
93}
94EXPORT_SYMBOL(simple_strtoul);
95
96/**
97 * simple_strtol - convert a string to a signed long
98 * @cp: The start of the string
99 * @endp: A pointer to the end of the parsed string will be placed here
100 * @base: The number base to use
Eldad Zack462e4712012-12-17 16:03:05 -0800101 *
Andy Shevchenkoe8cc2b92020-02-21 10:57:23 +0200102 * This function has caveats. Please use kstrtol instead.
André Goddard Rosa922ac252009-12-14 18:01:01 -0800103 */
104long simple_strtol(const char *cp, char **endp, unsigned int base)
105{
106 if (*cp == '-')
107 return -simple_strtoul(cp + 1, endp, base);
108
109 return simple_strtoul(cp, endp, base);
110}
111EXPORT_SYMBOL(simple_strtol);
112
113/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114 * simple_strtoll - convert a string to a signed long long
115 * @cp: The start of the string
116 * @endp: A pointer to the end of the parsed string will be placed here
117 * @base: The number base to use
Eldad Zack462e4712012-12-17 16:03:05 -0800118 *
Andy Shevchenkoe8cc2b92020-02-21 10:57:23 +0200119 * This function has caveats. Please use kstrtoll instead.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120 */
Harvey Harrison22d27052008-10-16 13:40:35 -0700121long long simple_strtoll(const char *cp, char **endp, unsigned int base)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122{
André Goddard Rosa7b9186f2009-12-14 18:00:57 -0800123 if (*cp == '-')
Harvey Harrison22d27052008-10-16 13:40:35 -0700124 return -simple_strtoull(cp + 1, endp, base);
André Goddard Rosa7b9186f2009-12-14 18:00:57 -0800125
Harvey Harrison22d27052008-10-16 13:40:35 -0700126 return simple_strtoull(cp, endp, base);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127}
Hans Verkuil98d5ce02010-04-23 13:18:04 -0400128EXPORT_SYMBOL(simple_strtoll);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129
Joe Perchescf3b4292010-05-24 14:33:16 -0700130static noinline_for_stack
131int skip_atoi(const char **s)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132{
André Goddard Rosa7b9186f2009-12-14 18:00:57 -0800133 int i = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134
Rasmus Villemoes43e5b662015-02-12 15:01:42 -0800135 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136 i = i*10 + *((*s)++) - '0';
Rasmus Villemoes43e5b662015-02-12 15:01:42 -0800137 } while (isdigit(**s));
André Goddard Rosa7b9186f2009-12-14 18:00:57 -0800138
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139 return i;
140}
141
Rasmus Villemoes7c43d9a2015-04-16 12:43:22 -0700142/*
143 * Decimal conversion is by far the most typical, and is used for
144 * /proc and /sys data. This directly impacts e.g. top performance
145 * with many processes running. We optimize it for speed by emitting
146 * two characters at a time, using a 200 byte lookup table. This
147 * roughly halves the number of multiplications compared to computing
148 * the digits one at a time. Implementation strongly inspired by the
149 * previous version, which in turn used ideas described at
150 * <http://www.cs.uiowa.edu/~jones/bcd/divide.html> (with permission
151 * from the author, Douglas W. Jones).
152 *
153 * It turns out there is precisely one 26 bit fixed-point
154 * approximation a of 64/100 for which x/100 == (x * (u64)a) >> 32
155 * holds for all x in [0, 10^8-1], namely a = 0x28f5c29. The actual
156 * range happens to be somewhat larger (x <= 1073741898), but that's
157 * irrelevant for our purpose.
158 *
159 * For dividing a number in the range [10^4, 10^6-1] by 100, we still
160 * need a 32x32->64 bit multiply, so we simply use the same constant.
161 *
162 * For dividing a number in the range [100, 10^4-1] by 100, there are
163 * several options. The simplest is (x * 0x147b) >> 19, which is valid
164 * for all x <= 43698.
Denys Vlasenko133fd9f2012-05-31 16:26:08 -0700165 */
Denis Vlasenko4277eed2007-07-15 23:41:56 -0700166
Rasmus Villemoes7c43d9a2015-04-16 12:43:22 -0700167static const u16 decpair[100] = {
168#define _(x) (__force u16) cpu_to_le16(((x % 10) | ((x / 10) << 8)) + 0x3030)
169 _( 0), _( 1), _( 2), _( 3), _( 4), _( 5), _( 6), _( 7), _( 8), _( 9),
170 _(10), _(11), _(12), _(13), _(14), _(15), _(16), _(17), _(18), _(19),
171 _(20), _(21), _(22), _(23), _(24), _(25), _(26), _(27), _(28), _(29),
172 _(30), _(31), _(32), _(33), _(34), _(35), _(36), _(37), _(38), _(39),
173 _(40), _(41), _(42), _(43), _(44), _(45), _(46), _(47), _(48), _(49),
174 _(50), _(51), _(52), _(53), _(54), _(55), _(56), _(57), _(58), _(59),
175 _(60), _(61), _(62), _(63), _(64), _(65), _(66), _(67), _(68), _(69),
176 _(70), _(71), _(72), _(73), _(74), _(75), _(76), _(77), _(78), _(79),
177 _(80), _(81), _(82), _(83), _(84), _(85), _(86), _(87), _(88), _(89),
178 _(90), _(91), _(92), _(93), _(94), _(95), _(96), _(97), _(98), _(99),
179#undef _
180};
Denis Vlasenko4277eed2007-07-15 23:41:56 -0700181
Rasmus Villemoes7c43d9a2015-04-16 12:43:22 -0700182/*
183 * This will print a single '0' even if r == 0, since we would
Rasmus Villemoes675cf532015-04-16 12:43:42 -0700184 * immediately jump to out_r where two 0s would be written but only
185 * one of them accounted for in buf. This is needed by ip4_string
186 * below. All other callers pass a non-zero value of r.
Rasmus Villemoes7c43d9a2015-04-16 12:43:22 -0700187*/
Denys Vlasenko133fd9f2012-05-31 16:26:08 -0700188static noinline_for_stack
189char *put_dec_trunc8(char *buf, unsigned r)
190{
191 unsigned q;
Denis Vlasenko4277eed2007-07-15 23:41:56 -0700192
Rasmus Villemoes7c43d9a2015-04-16 12:43:22 -0700193 /* 1 <= r < 10^8 */
194 if (r < 100)
195 goto out_r;
George Spelvincb239d02012-10-04 17:12:30 -0700196
Rasmus Villemoes7c43d9a2015-04-16 12:43:22 -0700197 /* 100 <= r < 10^8 */
198 q = (r * (u64)0x28f5c29) >> 32;
199 *((u16 *)buf) = decpair[r - 100*q];
200 buf += 2;
201
202 /* 1 <= q < 10^6 */
203 if (q < 100)
204 goto out_q;
205
206 /* 100 <= q < 10^6 */
207 r = (q * (u64)0x28f5c29) >> 32;
208 *((u16 *)buf) = decpair[q - 100*r];
209 buf += 2;
210
211 /* 1 <= r < 10^4 */
212 if (r < 100)
213 goto out_r;
214
215 /* 100 <= r < 10^4 */
216 q = (r * 0x147b) >> 19;
217 *((u16 *)buf) = decpair[r - 100*q];
218 buf += 2;
219out_q:
220 /* 1 <= q < 100 */
221 r = q;
222out_r:
223 /* 1 <= r < 100 */
224 *((u16 *)buf) = decpair[r];
Rasmus Villemoes675cf532015-04-16 12:43:42 -0700225 buf += r < 10 ? 1 : 2;
Denys Vlasenko133fd9f2012-05-31 16:26:08 -0700226 return buf;
227}
228
Rasmus Villemoes7c43d9a2015-04-16 12:43:22 -0700229#if BITS_PER_LONG == 64 && BITS_PER_LONG_LONG == 64
230static noinline_for_stack
231char *put_dec_full8(char *buf, unsigned r)
232{
233 unsigned q;
Denys Vlasenko133fd9f2012-05-31 16:26:08 -0700234
Rasmus Villemoes7c43d9a2015-04-16 12:43:22 -0700235 /* 0 <= r < 10^8 */
236 q = (r * (u64)0x28f5c29) >> 32;
237 *((u16 *)buf) = decpair[r - 100*q];
238 buf += 2;
Denys Vlasenko133fd9f2012-05-31 16:26:08 -0700239
Rasmus Villemoes7c43d9a2015-04-16 12:43:22 -0700240 /* 0 <= q < 10^6 */
241 r = (q * (u64)0x28f5c29) >> 32;
242 *((u16 *)buf) = decpair[q - 100*r];
243 buf += 2;
Denys Vlasenko133fd9f2012-05-31 16:26:08 -0700244
Rasmus Villemoes7c43d9a2015-04-16 12:43:22 -0700245 /* 0 <= r < 10^4 */
246 q = (r * 0x147b) >> 19;
247 *((u16 *)buf) = decpair[r - 100*q];
248 buf += 2;
249
250 /* 0 <= q < 100 */
251 *((u16 *)buf) = decpair[q];
252 buf += 2;
253 return buf;
254}
255
256static noinline_for_stack
Denys Vlasenko133fd9f2012-05-31 16:26:08 -0700257char *put_dec(char *buf, unsigned long long n)
258{
Rasmus Villemoes7c43d9a2015-04-16 12:43:22 -0700259 if (n >= 100*1000*1000)
260 buf = put_dec_full8(buf, do_div(n, 100*1000*1000));
261 /* 1 <= n <= 1.6e11 */
262 if (n >= 100*1000*1000)
263 buf = put_dec_full8(buf, do_div(n, 100*1000*1000));
264 /* 1 <= n < 1e8 */
Denys Vlasenko133fd9f2012-05-31 16:26:08 -0700265 return put_dec_trunc8(buf, n);
266}
267
Rasmus Villemoes7c43d9a2015-04-16 12:43:22 -0700268#elif BITS_PER_LONG == 32 && BITS_PER_LONG_LONG == 64
Denys Vlasenko133fd9f2012-05-31 16:26:08 -0700269
Rasmus Villemoes7c43d9a2015-04-16 12:43:22 -0700270static void
271put_dec_full4(char *buf, unsigned r)
Denys Vlasenko133fd9f2012-05-31 16:26:08 -0700272{
Rasmus Villemoes7c43d9a2015-04-16 12:43:22 -0700273 unsigned q;
274
275 /* 0 <= r < 10^4 */
276 q = (r * 0x147b) >> 19;
277 *((u16 *)buf) = decpair[r - 100*q];
278 buf += 2;
279 /* 0 <= q < 100 */
280 *((u16 *)buf) = decpair[q];
George Spelvin23591722012-10-04 17:12:29 -0700281}
282
283/*
284 * Call put_dec_full4 on x % 10000, return x / 10000.
285 * The approximation x/10000 == (x * 0x346DC5D7) >> 43
286 * holds for all x < 1,128,869,999. The largest value this
287 * helper will ever be asked to convert is 1,125,520,955.
Rasmus Villemoes7c43d9a2015-04-16 12:43:22 -0700288 * (second call in the put_dec code, assuming n is all-ones).
George Spelvin23591722012-10-04 17:12:29 -0700289 */
Rasmus Villemoes7c43d9a2015-04-16 12:43:22 -0700290static noinline_for_stack
George Spelvin23591722012-10-04 17:12:29 -0700291unsigned put_dec_helper4(char *buf, unsigned x)
292{
293 uint32_t q = (x * (uint64_t)0x346DC5D7) >> 43;
294
295 put_dec_full4(buf, x - q * 10000);
296 return q;
Denys Vlasenko133fd9f2012-05-31 16:26:08 -0700297}
298
299/* Based on code by Douglas W. Jones found at
300 * <http://www.cs.uiowa.edu/~jones/bcd/decimal.html#sixtyfour>
301 * (with permission from the author).
302 * Performs no 64-bit division and hence should be fast on 32-bit machines.
303 */
304static
305char *put_dec(char *buf, unsigned long long n)
306{
307 uint32_t d3, d2, d1, q, h;
308
309 if (n < 100*1000*1000)
310 return put_dec_trunc8(buf, n);
311
312 d1 = ((uint32_t)n >> 16); /* implicit "& 0xffff" */
313 h = (n >> 32);
314 d2 = (h ) & 0xffff;
315 d3 = (h >> 16); /* implicit "& 0xffff" */
316
Rasmus Villemoes7c43d9a2015-04-16 12:43:22 -0700317 /* n = 2^48 d3 + 2^32 d2 + 2^16 d1 + d0
318 = 281_4749_7671_0656 d3 + 42_9496_7296 d2 + 6_5536 d1 + d0 */
Denys Vlasenko133fd9f2012-05-31 16:26:08 -0700319 q = 656 * d3 + 7296 * d2 + 5536 * d1 + ((uint32_t)n & 0xffff);
George Spelvin23591722012-10-04 17:12:29 -0700320 q = put_dec_helper4(buf, q);
Denys Vlasenko133fd9f2012-05-31 16:26:08 -0700321
George Spelvin23591722012-10-04 17:12:29 -0700322 q += 7671 * d3 + 9496 * d2 + 6 * d1;
323 q = put_dec_helper4(buf+4, q);
Denys Vlasenko133fd9f2012-05-31 16:26:08 -0700324
George Spelvin23591722012-10-04 17:12:29 -0700325 q += 4749 * d3 + 42 * d2;
326 q = put_dec_helper4(buf+8, q);
Denys Vlasenko133fd9f2012-05-31 16:26:08 -0700327
George Spelvin23591722012-10-04 17:12:29 -0700328 q += 281 * d3;
329 buf += 12;
330 if (q)
331 buf = put_dec_trunc8(buf, q);
332 else while (buf[-1] == '0')
Denys Vlasenko133fd9f2012-05-31 16:26:08 -0700333 --buf;
André Goddard Rosa7b9186f2009-12-14 18:00:57 -0800334
Denis Vlasenko4277eed2007-07-15 23:41:56 -0700335 return buf;
336}
Denys Vlasenko133fd9f2012-05-31 16:26:08 -0700337
338#endif
Denis Vlasenko4277eed2007-07-15 23:41:56 -0700339
KAMEZAWA Hiroyuki1ac101a2012-03-23 15:02:54 -0700340/*
341 * Convert passed number to decimal string.
342 * Returns the length of string. On buffer overflow, returns 0.
343 *
344 * If speed is not important, use snprintf(). It's easy to read the code.
345 */
Andrei Vagind1be35c2018-04-10 16:31:16 -0700346int num_to_str(char *buf, int size, unsigned long long num, unsigned int width)
KAMEZAWA Hiroyuki1ac101a2012-03-23 15:02:54 -0700347{
Rasmus Villemoes7c43d9a2015-04-16 12:43:22 -0700348 /* put_dec requires 2-byte alignment of the buffer. */
349 char tmp[sizeof(num) * 3] __aligned(2);
KAMEZAWA Hiroyuki1ac101a2012-03-23 15:02:54 -0700350 int idx, len;
351
Denys Vlasenko133fd9f2012-05-31 16:26:08 -0700352 /* put_dec() may work incorrectly for num = 0 (generate "", not "0") */
353 if (num <= 9) {
354 tmp[0] = '0' + num;
355 len = 1;
356 } else {
357 len = put_dec(tmp, num) - tmp;
358 }
KAMEZAWA Hiroyuki1ac101a2012-03-23 15:02:54 -0700359
Andrei Vagind1be35c2018-04-10 16:31:16 -0700360 if (len > size || width > size)
KAMEZAWA Hiroyuki1ac101a2012-03-23 15:02:54 -0700361 return 0;
Andrei Vagind1be35c2018-04-10 16:31:16 -0700362
363 if (width > len) {
364 width = width - len;
365 for (idx = 0; idx < width; idx++)
366 buf[idx] = ' ';
367 } else {
368 width = 0;
369 }
370
KAMEZAWA Hiroyuki1ac101a2012-03-23 15:02:54 -0700371 for (idx = 0; idx < len; ++idx)
Andrei Vagind1be35c2018-04-10 16:31:16 -0700372 buf[idx + width] = tmp[len - idx - 1];
373
374 return len + width;
KAMEZAWA Hiroyuki1ac101a2012-03-23 15:02:54 -0700375}
376
Rasmus Villemoes51be17d2015-04-15 16:17:02 -0700377#define SIGN 1 /* unsigned/signed, must be 1 */
Rasmus Villemoesd1c1b122015-04-15 16:17:11 -0700378#define LEFT 2 /* left justified */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379#define PLUS 4 /* show plus */
380#define SPACE 8 /* space if plus */
Rasmus Villemoesd1c1b122015-04-15 16:17:11 -0700381#define ZEROPAD 16 /* pad with zero, must be 16 == '0' - ' ' */
Bjorn Helgaasb89dc5d2010-03-05 10:47:31 -0700382#define SMALL 32 /* use lowercase in hex (must be 32 == 0x20) */
383#define SPECIAL 64 /* prefix hex with "0x", octal with "0" */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384
Andy Shevchenkob8866902020-07-31 21:08:22 +0300385static_assert(ZEROPAD == ('0' - ' '));
386static_assert(SMALL == ' ');
387
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +0100388enum format_type {
389 FORMAT_TYPE_NONE, /* Just a string part */
Vegard Nossumed681a92009-03-14 12:08:50 +0100390 FORMAT_TYPE_WIDTH,
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +0100391 FORMAT_TYPE_PRECISION,
392 FORMAT_TYPE_CHAR,
393 FORMAT_TYPE_STR,
394 FORMAT_TYPE_PTR,
395 FORMAT_TYPE_PERCENT_CHAR,
396 FORMAT_TYPE_INVALID,
397 FORMAT_TYPE_LONG_LONG,
398 FORMAT_TYPE_ULONG,
399 FORMAT_TYPE_LONG,
Zhaoleia4e94ef2009-03-27 17:07:05 +0800400 FORMAT_TYPE_UBYTE,
401 FORMAT_TYPE_BYTE,
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +0100402 FORMAT_TYPE_USHORT,
403 FORMAT_TYPE_SHORT,
404 FORMAT_TYPE_UINT,
405 FORMAT_TYPE_INT,
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +0100406 FORMAT_TYPE_SIZE_T,
407 FORMAT_TYPE_PTRDIFF
408};
409
410struct printf_spec {
Rasmus Villemoesd0484192016-01-15 16:58:37 -0800411 unsigned int type:8; /* format_type enum */
412 signed int field_width:24; /* width of output field */
413 unsigned int flags:8; /* flags to number() */
414 unsigned int base:8; /* number base, 8, 10 or 16 only */
415 signed int precision:16; /* # of digits/chars */
416} __packed;
Rasmus Villemoesef27ac12019-03-07 16:27:03 -0800417static_assert(sizeof(struct printf_spec) == 8);
418
Rasmus Villemoes4d72ba02016-01-15 16:58:44 -0800419#define FIELD_WIDTH_MAX ((1 << 23) - 1)
420#define PRECISION_MAX ((1 << 15) - 1)
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +0100421
Joe Perchescf3b4292010-05-24 14:33:16 -0700422static noinline_for_stack
423char *number(char *buf, char *end, unsigned long long num,
424 struct printf_spec spec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425{
Rasmus Villemoes7c43d9a2015-04-16 12:43:22 -0700426 /* put_dec requires 2-byte alignment of the buffer. */
427 char tmp[3 * sizeof(num)] __aligned(2);
Denys Vlasenko9b706ae2008-02-09 23:24:09 +0100428 char sign;
429 char locase;
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +0100430 int need_pfx = ((spec.flags & SPECIAL) && spec.base != 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 int i;
Pierre Carrier7c203422012-05-29 15:07:35 -0700432 bool is_zero = num == 0LL;
Rasmus Villemoes1c7a8e62016-01-15 16:58:41 -0800433 int field_width = spec.field_width;
434 int precision = spec.precision;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435
Denys Vlasenko9b706ae2008-02-09 23:24:09 +0100436 /* locase = 0 or 0x20. ORing digits or letters with 'locase'
437 * produces same digits or (maybe lowercased) letters */
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +0100438 locase = (spec.flags & SMALL);
439 if (spec.flags & LEFT)
440 spec.flags &= ~ZEROPAD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 sign = 0;
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +0100442 if (spec.flags & SIGN) {
André Goddard Rosa7b9186f2009-12-14 18:00:57 -0800443 if ((signed long long)num < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 sign = '-';
André Goddard Rosa7b9186f2009-12-14 18:00:57 -0800445 num = -(signed long long)num;
Rasmus Villemoes1c7a8e62016-01-15 16:58:41 -0800446 field_width--;
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +0100447 } else if (spec.flags & PLUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 sign = '+';
Rasmus Villemoes1c7a8e62016-01-15 16:58:41 -0800449 field_width--;
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +0100450 } else if (spec.flags & SPACE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 sign = ' ';
Rasmus Villemoes1c7a8e62016-01-15 16:58:41 -0800452 field_width--;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453 }
454 }
Denis Vlasenkob39a7342007-07-15 23:41:54 -0700455 if (need_pfx) {
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +0100456 if (spec.base == 16)
Rasmus Villemoes1c7a8e62016-01-15 16:58:41 -0800457 field_width -= 2;
Pierre Carrier7c203422012-05-29 15:07:35 -0700458 else if (!is_zero)
Rasmus Villemoes1c7a8e62016-01-15 16:58:41 -0800459 field_width--;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 }
Denis Vlasenkob39a7342007-07-15 23:41:54 -0700461
462 /* generate full string in tmp[], in reverse order */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463 i = 0;
Denys Vlasenko133fd9f2012-05-31 16:26:08 -0700464 if (num < spec.base)
Rasmus Villemoes3ea8d442015-04-15 16:17:08 -0700465 tmp[i++] = hex_asc_upper[num] | locase;
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +0100466 else if (spec.base != 10) { /* 8 or 16 */
467 int mask = spec.base - 1;
Denis Vlasenkob39a7342007-07-15 23:41:54 -0700468 int shift = 3;
André Goddard Rosa7b9186f2009-12-14 18:00:57 -0800469
470 if (spec.base == 16)
471 shift = 4;
Denis Vlasenkob39a7342007-07-15 23:41:54 -0700472 do {
Rasmus Villemoes3ea8d442015-04-15 16:17:08 -0700473 tmp[i++] = (hex_asc_upper[((unsigned char)num) & mask] | locase);
Denis Vlasenkob39a7342007-07-15 23:41:54 -0700474 num >>= shift;
475 } while (num);
Denis Vlasenko4277eed2007-07-15 23:41:56 -0700476 } else { /* base 10 */
477 i = put_dec(tmp, num) - tmp;
478 }
Denis Vlasenkob39a7342007-07-15 23:41:54 -0700479
480 /* printing 100 using %2d gives "100", not "00" */
Rasmus Villemoes1c7a8e62016-01-15 16:58:41 -0800481 if (i > precision)
482 precision = i;
Denis Vlasenkob39a7342007-07-15 23:41:54 -0700483 /* leading space padding */
Rasmus Villemoes1c7a8e62016-01-15 16:58:41 -0800484 field_width -= precision;
Rasmus Villemoes51be17d2015-04-15 16:17:02 -0700485 if (!(spec.flags & (ZEROPAD | LEFT))) {
Rasmus Villemoes1c7a8e62016-01-15 16:58:41 -0800486 while (--field_width >= 0) {
Jeremy Fitzhardingef7969372006-06-25 05:49:17 -0700487 if (buf < end)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 *buf = ' ';
489 ++buf;
490 }
491 }
Denis Vlasenkob39a7342007-07-15 23:41:54 -0700492 /* sign */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 if (sign) {
Jeremy Fitzhardingef7969372006-06-25 05:49:17 -0700494 if (buf < end)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 *buf = sign;
496 ++buf;
497 }
Denis Vlasenkob39a7342007-07-15 23:41:54 -0700498 /* "0x" / "0" prefix */
499 if (need_pfx) {
Pierre Carrier7c203422012-05-29 15:07:35 -0700500 if (spec.base == 16 || !is_zero) {
501 if (buf < end)
502 *buf = '0';
503 ++buf;
504 }
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +0100505 if (spec.base == 16) {
Jeremy Fitzhardingef7969372006-06-25 05:49:17 -0700506 if (buf < end)
Denys Vlasenko9b706ae2008-02-09 23:24:09 +0100507 *buf = ('X' | locase);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 ++buf;
509 }
510 }
Denis Vlasenkob39a7342007-07-15 23:41:54 -0700511 /* zero or space padding */
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +0100512 if (!(spec.flags & LEFT)) {
Rasmus Villemoesd1c1b122015-04-15 16:17:11 -0700513 char c = ' ' + (spec.flags & ZEROPAD);
Andy Shevchenkob8866902020-07-31 21:08:22 +0300514
Rasmus Villemoes1c7a8e62016-01-15 16:58:41 -0800515 while (--field_width >= 0) {
Jeremy Fitzhardingef7969372006-06-25 05:49:17 -0700516 if (buf < end)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 *buf = c;
518 ++buf;
519 }
520 }
Denis Vlasenkob39a7342007-07-15 23:41:54 -0700521 /* hmm even more zero padding? */
Rasmus Villemoes1c7a8e62016-01-15 16:58:41 -0800522 while (i <= --precision) {
Jeremy Fitzhardingef7969372006-06-25 05:49:17 -0700523 if (buf < end)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 *buf = '0';
525 ++buf;
526 }
Denis Vlasenkob39a7342007-07-15 23:41:54 -0700527 /* actual digits of result */
528 while (--i >= 0) {
Jeremy Fitzhardingef7969372006-06-25 05:49:17 -0700529 if (buf < end)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 *buf = tmp[i];
531 ++buf;
532 }
Denis Vlasenkob39a7342007-07-15 23:41:54 -0700533 /* trailing space padding */
Rasmus Villemoes1c7a8e62016-01-15 16:58:41 -0800534 while (--field_width >= 0) {
Jeremy Fitzhardingef7969372006-06-25 05:49:17 -0700535 if (buf < end)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536 *buf = ' ';
537 ++buf;
538 }
André Goddard Rosa7b9186f2009-12-14 18:00:57 -0800539
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 return buf;
541}
542
Andy Shevchenko3cab1e72016-01-15 16:59:18 -0800543static noinline_for_stack
544char *special_hex_number(char *buf, char *end, unsigned long long num, int size)
545{
546 struct printf_spec spec;
547
548 spec.type = FORMAT_TYPE_PTR;
549 spec.field_width = 2 + 2 * size; /* 0x + hex */
550 spec.flags = SPECIAL | SMALL | ZEROPAD;
551 spec.base = 16;
552 spec.precision = -1;
553
554 return number(buf, end, num, spec);
555}
556
Rasmus Villemoescfccde02016-01-15 16:58:28 -0800557static void move_right(char *buf, char *end, unsigned len, unsigned spaces)
Al Viro4b6ccca2013-09-03 12:00:44 -0400558{
559 size_t size;
560 if (buf >= end) /* nowhere to put anything */
561 return;
562 size = end - buf;
563 if (size <= spaces) {
564 memset(buf, ' ', size);
565 return;
566 }
567 if (len) {
568 if (len > size - spaces)
569 len = size - spaces;
570 memmove(buf + spaces, buf, len);
571 }
572 memset(buf, ' ', spaces);
573}
574
Rasmus Villemoescfccde02016-01-15 16:58:28 -0800575/*
576 * Handle field width padding for a string.
577 * @buf: current buffer position
578 * @n: length of string
579 * @end: end of output buffer
580 * @spec: for field width and flags
581 * Returns: new buffer position after padding.
582 */
583static noinline_for_stack
584char *widen_string(char *buf, int n, char *end, struct printf_spec spec)
585{
586 unsigned spaces;
587
588 if (likely(n >= spec.field_width))
589 return buf;
590 /* we want to pad the sucker */
591 spaces = spec.field_width - n;
592 if (!(spec.flags & LEFT)) {
593 move_right(buf - n, end, n, spaces);
594 return buf + spaces;
595 }
596 while (spaces--) {
597 if (buf < end)
598 *buf = ' ';
599 ++buf;
600 }
601 return buf;
602}
603
Petr Mladekd529ac42019-04-17 13:53:43 +0200604/* Handle string from a well known address. */
605static char *string_nocheck(char *buf, char *end, const char *s,
606 struct printf_spec spec)
Rasmus Villemoes95508cf2016-01-15 16:58:31 -0800607{
Rasmus Villemoes34fc8b92016-01-15 16:58:34 -0800608 int len = 0;
Youngmin Namb314dd42019-06-10 16:47:07 +0900609 int lim = spec.precision;
Rasmus Villemoes95508cf2016-01-15 16:58:31 -0800610
Rasmus Villemoes34fc8b92016-01-15 16:58:34 -0800611 while (lim--) {
612 char c = *s++;
613 if (!c)
614 break;
Rasmus Villemoes95508cf2016-01-15 16:58:31 -0800615 if (buf < end)
Rasmus Villemoes34fc8b92016-01-15 16:58:34 -0800616 *buf = c;
Rasmus Villemoes95508cf2016-01-15 16:58:31 -0800617 ++buf;
Rasmus Villemoes34fc8b92016-01-15 16:58:34 -0800618 ++len;
Rasmus Villemoes95508cf2016-01-15 16:58:31 -0800619 }
Rasmus Villemoes34fc8b92016-01-15 16:58:34 -0800620 return widen_string(buf, len, end, spec);
Rasmus Villemoes95508cf2016-01-15 16:58:31 -0800621}
622
Rasmus Villemoes57f56772019-10-15 21:07:05 +0200623static char *err_ptr(char *buf, char *end, void *ptr,
624 struct printf_spec spec)
625{
626 int err = PTR_ERR(ptr);
627 const char *sym = errname(err);
628
629 if (sym)
630 return string_nocheck(buf, end, sym, spec);
631
632 /*
633 * Somebody passed ERR_PTR(-1234) or some other non-existing
634 * Efoo - or perhaps CONFIG_SYMBOLIC_ERRNAME=n. Fall back to
635 * printing it as its decimal representation.
636 */
637 spec.flags |= SIGN;
638 spec.base = 10;
639 return number(buf, end, err, spec);
640}
641
Petr Mladekc8c3b582019-04-17 13:53:50 +0200642/* Be careful: error messages must fit into the given buffer. */
643static char *error_string(char *buf, char *end, const char *s,
644 struct printf_spec spec)
645{
646 /*
647 * Hard limit to avoid a completely insane messages. It actually
648 * works pretty well because most error messages are in
649 * the many pointer format modifiers.
650 */
651 if (spec.precision == -1)
652 spec.precision = 2 * sizeof(void *);
653
654 return string_nocheck(buf, end, s, spec);
655}
656
Petr Mladek3e5903e2019-04-17 13:53:48 +0200657/*
Petr Mladek2ac5a3b2019-05-10 10:42:13 +0200658 * Do not call any complex external code here. Nested printk()/vsprintf()
659 * might cause infinite loops. Failures might break printk() and would
660 * be hard to debug.
Petr Mladek3e5903e2019-04-17 13:53:48 +0200661 */
662static const char *check_pointer_msg(const void *ptr)
663{
Petr Mladek3e5903e2019-04-17 13:53:48 +0200664 if (!ptr)
665 return "(null)";
666
Petr Mladek2ac5a3b2019-05-10 10:42:13 +0200667 if ((unsigned long)ptr < PAGE_SIZE || IS_ERR_VALUE(ptr))
Petr Mladek3e5903e2019-04-17 13:53:48 +0200668 return "(efault)";
669
670 return NULL;
671}
672
673static int check_pointer(char **buf, char *end, const void *ptr,
674 struct printf_spec spec)
675{
676 const char *err_msg;
677
678 err_msg = check_pointer_msg(ptr);
679 if (err_msg) {
Petr Mladekc8c3b582019-04-17 13:53:50 +0200680 *buf = error_string(*buf, end, err_msg, spec);
Petr Mladek3e5903e2019-04-17 13:53:48 +0200681 return -EFAULT;
682 }
683
684 return 0;
685}
686
Rasmus Villemoes95508cf2016-01-15 16:58:31 -0800687static noinline_for_stack
Petr Mladekd529ac42019-04-17 13:53:43 +0200688char *string(char *buf, char *end, const char *s,
689 struct printf_spec spec)
690{
Petr Mladek3e5903e2019-04-17 13:53:48 +0200691 if (check_pointer(&buf, end, s, spec))
692 return buf;
Petr Mladekd529ac42019-04-17 13:53:43 +0200693
694 return string_nocheck(buf, end, s, spec);
695}
696
YueHaibingce9d3ec2019-04-27 00:46:30 +0800697static char *pointer_string(char *buf, char *end,
698 const void *ptr,
699 struct printf_spec spec)
Geert Uytterhoeven9073dac2018-10-11 10:42:47 +0200700{
701 spec.base = 16;
702 spec.flags |= SMALL;
703 if (spec.field_width == -1) {
704 spec.field_width = 2 * sizeof(ptr);
705 spec.flags |= ZEROPAD;
706 }
707
708 return number(buf, end, (unsigned long int)ptr, spec);
709}
710
711/* Make pointers available for printing early in the boot sequence. */
712static int debug_boot_weak_hash __ro_after_init;
713
714static int __init debug_boot_weak_hash_enable(char *str)
715{
716 debug_boot_weak_hash = 1;
717 pr_info("debug_boot_weak_hash enabled\n");
718 return 0;
719}
720early_param("debug_boot_weak_hash", debug_boot_weak_hash_enable);
721
722static DEFINE_STATIC_KEY_TRUE(not_filled_random_ptr_key);
723static siphash_key_t ptr_key __read_mostly;
724
725static void enable_ptr_key_workfn(struct work_struct *work)
726{
727 get_random_bytes(&ptr_key, sizeof(ptr_key));
728 /* Needs to run from preemptible context */
729 static_branch_disable(&not_filled_random_ptr_key);
730}
731
732static DECLARE_WORK(enable_ptr_key_work, enable_ptr_key_workfn);
733
734static void fill_random_ptr_key(struct random_ready_callback *unused)
735{
736 /* This may be in an interrupt handler. */
737 queue_work(system_unbound_wq, &enable_ptr_key_work);
738}
739
740static struct random_ready_callback random_ready = {
741 .func = fill_random_ptr_key
742};
743
744static int __init initialize_ptr_random(void)
745{
746 int key_size = sizeof(ptr_key);
747 int ret;
748
749 /* Use hw RNG if available. */
750 if (get_random_bytes_arch(&ptr_key, key_size) == key_size) {
751 static_branch_disable(&not_filled_random_ptr_key);
752 return 0;
753 }
754
755 ret = add_random_ready_callback(&random_ready);
756 if (!ret) {
757 return 0;
758 } else if (ret == -EALREADY) {
759 /* This is in preemptible context */
760 enable_ptr_key_workfn(&enable_ptr_key_work);
761 return 0;
762 }
763
764 return ret;
765}
766early_initcall(initialize_ptr_random);
767
768/* Maps a pointer to a 32 bit unique identifier. */
Joel Fernandes (Google)e4dcad22019-11-30 17:50:33 -0800769static inline int __ptr_to_hashval(const void *ptr, unsigned long *hashval_out)
Geert Uytterhoeven9073dac2018-10-11 10:42:47 +0200770{
Geert Uytterhoeven9073dac2018-10-11 10:42:47 +0200771 unsigned long hashval;
772
Joel Fernandes (Google)e4dcad22019-11-30 17:50:33 -0800773 if (static_branch_unlikely(&not_filled_random_ptr_key))
774 return -EAGAIN;
Geert Uytterhoeven9073dac2018-10-11 10:42:47 +0200775
776#ifdef CONFIG_64BIT
777 hashval = (unsigned long)siphash_1u64((u64)ptr, &ptr_key);
778 /*
779 * Mask off the first 32 bits, this makes explicit that we have
780 * modified the address (and 32 bits is plenty for a unique ID).
781 */
782 hashval = hashval & 0xffffffff;
783#else
784 hashval = (unsigned long)siphash_1u32((u32)ptr, &ptr_key);
785#endif
Joel Fernandes (Google)e4dcad22019-11-30 17:50:33 -0800786 *hashval_out = hashval;
787 return 0;
788}
789
790int ptr_to_hashval(const void *ptr, unsigned long *hashval_out)
791{
792 return __ptr_to_hashval(ptr, hashval_out);
793}
794
795static char *ptr_to_id(char *buf, char *end, const void *ptr,
796 struct printf_spec spec)
797{
798 const char *str = sizeof(ptr) == 8 ? "(____ptrval____)" : "(ptrval)";
799 unsigned long hashval;
800 int ret;
801
Ilya Dryomov7bd57fb2020-05-19 13:26:57 +0200802 /*
803 * Print the real pointer value for NULL and error pointers,
804 * as they are not actual addresses.
805 */
806 if (IS_ERR_OR_NULL(ptr))
807 return pointer_string(buf, end, ptr, spec);
808
Joel Fernandes (Google)e4dcad22019-11-30 17:50:33 -0800809 /* When debugging early boot use non-cryptographically secure hash. */
810 if (unlikely(debug_boot_weak_hash)) {
811 hashval = hash_long((unsigned long)ptr, 32);
812 return pointer_string(buf, end, (const void *)hashval, spec);
813 }
814
815 ret = __ptr_to_hashval(ptr, &hashval);
816 if (ret) {
817 spec.field_width = 2 * sizeof(ptr);
818 /* string length must be less than default_width */
819 return error_string(buf, end, str, spec);
820 }
821
Geert Uytterhoeven9073dac2018-10-11 10:42:47 +0200822 return pointer_string(buf, end, (const void *)hashval, spec);
823}
824
Petr Mladek6eea2422019-04-17 13:53:41 +0200825int kptr_restrict __read_mostly;
826
827static noinline_for_stack
828char *restricted_pointer(char *buf, char *end, const void *ptr,
829 struct printf_spec spec)
830{
831 switch (kptr_restrict) {
832 case 0:
Petr Mladek1ac2f972019-04-17 13:53:42 +0200833 /* Handle as %p, hash and do _not_ leak addresses. */
834 return ptr_to_id(buf, end, ptr, spec);
Petr Mladek6eea2422019-04-17 13:53:41 +0200835 case 1: {
836 const struct cred *cred;
837
838 /*
839 * kptr_restrict==1 cannot be used in IRQ context
840 * because its test for CAP_SYSLOG would be meaningless.
841 */
842 if (in_irq() || in_serving_softirq() || in_nmi()) {
843 if (spec.field_width == -1)
844 spec.field_width = 2 * sizeof(ptr);
Petr Mladekc8c3b582019-04-17 13:53:50 +0200845 return error_string(buf, end, "pK-error", spec);
Petr Mladek6eea2422019-04-17 13:53:41 +0200846 }
847
848 /*
849 * Only print the real pointer value if the current
850 * process has CAP_SYSLOG and is running with the
851 * same credentials it started with. This is because
852 * access to files is checked at open() time, but %pK
853 * checks permission at read() time. We don't want to
854 * leak pointer values if a binary opens a file using
855 * %pK and then elevates privileges before reading it.
856 */
857 cred = current_cred();
858 if (!has_capability_noaudit(current, CAP_SYSLOG) ||
859 !uid_eq(cred->euid, cred->uid) ||
860 !gid_eq(cred->egid, cred->gid))
861 ptr = NULL;
862 break;
863 }
864 case 2:
865 default:
866 /* Always print 0's for %pK */
867 ptr = NULL;
868 break;
869 }
870
871 return pointer_string(buf, end, ptr, spec);
872}
873
Geert Uytterhoeven9073dac2018-10-11 10:42:47 +0200874static noinline_for_stack
Al Viro4b6ccca2013-09-03 12:00:44 -0400875char *dentry_name(char *buf, char *end, const struct dentry *d, struct printf_spec spec,
876 const char *fmt)
877{
878 const char *array[4], *s;
879 const struct dentry *p;
880 int depth;
881 int i, n;
882
883 switch (fmt[1]) {
884 case '2': case '3': case '4':
885 depth = fmt[1] - '0';
886 break;
887 default:
888 depth = 1;
889 }
890
891 rcu_read_lock();
892 for (i = 0; i < depth; i++, d = p) {
Petr Mladek3e5903e2019-04-17 13:53:48 +0200893 if (check_pointer(&buf, end, d, spec)) {
894 rcu_read_unlock();
895 return buf;
896 }
897
Mark Rutland6aa7de02017-10-23 14:07:29 -0700898 p = READ_ONCE(d->d_parent);
899 array[i] = READ_ONCE(d->d_name.name);
Al Viro4b6ccca2013-09-03 12:00:44 -0400900 if (p == d) {
901 if (i)
902 array[i] = "";
903 i++;
904 break;
905 }
906 }
907 s = array[--i];
908 for (n = 0; n != spec.precision; n++, buf++) {
909 char c = *s++;
910 if (!c) {
911 if (!i)
912 break;
913 c = '/';
914 s = array[--i];
915 }
916 if (buf < end)
917 *buf = c;
918 }
919 rcu_read_unlock();
Rasmus Villemoescfccde02016-01-15 16:58:28 -0800920 return widen_string(buf, n, end, spec);
Al Viro4b6ccca2013-09-03 12:00:44 -0400921}
922
Jia He36594b32019-08-09 09:24:56 +0800923static noinline_for_stack
924char *file_dentry_name(char *buf, char *end, const struct file *f,
925 struct printf_spec spec, const char *fmt)
926{
927 if (check_pointer(&buf, end, f, spec))
928 return buf;
929
930 return dentry_name(buf, end, f->f_path.dentry, spec, fmt);
931}
Dmitry Monakhov1031bc52015-04-13 16:31:35 +0400932#ifdef CONFIG_BLOCK
933static noinline_for_stack
934char *bdev_name(char *buf, char *end, struct block_device *bdev,
935 struct printf_spec spec, const char *fmt)
936{
Petr Mladek3e5903e2019-04-17 13:53:48 +0200937 struct gendisk *hd;
938
939 if (check_pointer(&buf, end, bdev, spec))
940 return buf;
941
942 hd = bdev->bd_disk;
Dmitry Monakhov1031bc52015-04-13 16:31:35 +0400943 buf = string(buf, end, hd->disk_name, spec);
Christoph Hellwig700cd592020-09-03 07:41:04 +0200944 if (bdev->bd_partno) {
Dmitry Monakhov1031bc52015-04-13 16:31:35 +0400945 if (isdigit(hd->disk_name[strlen(hd->disk_name)-1])) {
946 if (buf < end)
947 *buf = 'p';
948 buf++;
949 }
Christoph Hellwig700cd592020-09-03 07:41:04 +0200950 buf = number(buf, end, bdev->bd_partno, spec);
Dmitry Monakhov1031bc52015-04-13 16:31:35 +0400951 }
952 return buf;
953}
954#endif
955
Joe Perchescf3b4292010-05-24 14:33:16 -0700956static noinline_for_stack
957char *symbol_string(char *buf, char *end, void *ptr,
Joe Perchesb0d33c22012-12-12 10:18:50 -0800958 struct printf_spec spec, const char *fmt)
Linus Torvalds0fe1ef22008-07-06 16:43:12 -0700959{
Joe Perchesb0d33c22012-12-12 10:18:50 -0800960 unsigned long value;
Linus Torvalds0fe1ef22008-07-06 16:43:12 -0700961#ifdef CONFIG_KALLSYMS
962 char sym[KSYM_SYMBOL_LEN];
Joe Perchesb0d33c22012-12-12 10:18:50 -0800963#endif
964
965 if (fmt[1] == 'R')
966 ptr = __builtin_extract_return_addr(ptr);
967 value = (unsigned long)ptr;
968
969#ifdef CONFIG_KALLSYMS
970 if (*fmt == 'B')
Namhyung Kim0f77a8d2011-03-24 11:42:29 +0900971 sprint_backtrace(sym, value);
Sakari Ailus9af77062019-10-03 15:32:14 +0300972 else if (*fmt != 's')
Frederic Weisbecker0c8b9462009-04-15 17:48:18 +0200973 sprint_symbol(sym, value);
974 else
Stephen Boyd4796dd22012-05-29 15:07:33 -0700975 sprint_symbol_no_offset(sym, value);
André Goddard Rosa7b9186f2009-12-14 18:00:57 -0800976
Petr Mladekd529ac42019-04-17 13:53:43 +0200977 return string_nocheck(buf, end, sym, spec);
Linus Torvalds0fe1ef22008-07-06 16:43:12 -0700978#else
Andy Shevchenko3cab1e72016-01-15 16:59:18 -0800979 return special_hex_number(buf, end, value, sizeof(void *));
Linus Torvalds0fe1ef22008-07-06 16:43:12 -0700980#endif
981}
982
Andy Shevchenkoabd4fe62018-02-16 23:07:05 +0200983static const struct printf_spec default_str_spec = {
984 .field_width = -1,
985 .precision = -1,
986};
987
Andy Shevchenko54433972018-02-16 23:07:06 +0200988static const struct printf_spec default_flag_spec = {
989 .base = 16,
990 .precision = -1,
991 .flags = SPECIAL | SMALL,
992};
993
Andy Shevchenkoce0b4912018-02-16 23:07:04 +0200994static const struct printf_spec default_dec_spec = {
995 .base = 10,
996 .precision = -1,
997};
998
Andy Shevchenko4d42c442018-12-04 23:23:11 +0200999static const struct printf_spec default_dec02_spec = {
1000 .base = 10,
1001 .field_width = 2,
1002 .precision = -1,
1003 .flags = ZEROPAD,
1004};
1005
1006static const struct printf_spec default_dec04_spec = {
1007 .base = 10,
1008 .field_width = 4,
1009 .precision = -1,
1010 .flags = ZEROPAD,
1011};
1012
Joe Perchescf3b4292010-05-24 14:33:16 -07001013static noinline_for_stack
1014char *resource_string(char *buf, char *end, struct resource *res,
1015 struct printf_spec spec, const char *fmt)
Linus Torvalds332d2e72008-10-20 15:07:34 +11001016{
1017#ifndef IO_RSRC_PRINTK_SIZE
Bjorn Helgaas28405372009-10-06 15:33:29 -06001018#define IO_RSRC_PRINTK_SIZE 6
Linus Torvalds332d2e72008-10-20 15:07:34 +11001019#endif
1020
1021#ifndef MEM_RSRC_PRINTK_SIZE
Bjorn Helgaas28405372009-10-06 15:33:29 -06001022#define MEM_RSRC_PRINTK_SIZE 10
Linus Torvalds332d2e72008-10-20 15:07:34 +11001023#endif
Bjorn Helgaas4da0b662010-03-05 10:47:37 -07001024 static const struct printf_spec io_spec = {
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01001025 .base = 16,
Bjorn Helgaas4da0b662010-03-05 10:47:37 -07001026 .field_width = IO_RSRC_PRINTK_SIZE,
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01001027 .precision = -1,
1028 .flags = SPECIAL | SMALL | ZEROPAD,
1029 };
Bjorn Helgaas4da0b662010-03-05 10:47:37 -07001030 static const struct printf_spec mem_spec = {
1031 .base = 16,
1032 .field_width = MEM_RSRC_PRINTK_SIZE,
1033 .precision = -1,
1034 .flags = SPECIAL | SMALL | ZEROPAD,
1035 };
Bjorn Helgaas0f4050c2010-03-05 10:47:42 -07001036 static const struct printf_spec bus_spec = {
1037 .base = 16,
1038 .field_width = 2,
1039 .precision = -1,
1040 .flags = SMALL | ZEROPAD,
1041 };
Bjorn Helgaas4da0b662010-03-05 10:47:37 -07001042 static const struct printf_spec str_spec = {
Bjorn Helgaasfd955412009-10-06 15:33:39 -06001043 .field_width = -1,
1044 .precision = 10,
1045 .flags = LEFT,
1046 };
Bjorn Helgaasc7dabef2009-10-27 13:26:47 -06001047
1048 /* 32-bit res (sizeof==4): 10 chars in dec, 10 in hex ("0x" + 8)
1049 * 64-bit res (sizeof==8): 20 chars in dec, 18 in hex ("0x" + 16) */
1050#define RSRC_BUF_SIZE ((2 * sizeof(resource_size_t)) + 4)
1051#define FLAG_BUF_SIZE (2 * sizeof(res->flags))
Bjorn Helgaas9d7cca02010-03-05 10:47:47 -07001052#define DECODED_BUF_SIZE sizeof("[mem - 64bit pref window disabled]")
Bjorn Helgaasc7dabef2009-10-27 13:26:47 -06001053#define RAW_BUF_SIZE sizeof("[mem - flags 0x]")
1054 char sym[max(2*RSRC_BUF_SIZE + DECODED_BUF_SIZE,
1055 2*RSRC_BUF_SIZE + FLAG_BUF_SIZE + RAW_BUF_SIZE)];
1056
Linus Torvalds332d2e72008-10-20 15:07:34 +11001057 char *p = sym, *pend = sym + sizeof(sym);
Bjorn Helgaasc7dabef2009-10-27 13:26:47 -06001058 int decode = (fmt[0] == 'R') ? 1 : 0;
Bjorn Helgaas4da0b662010-03-05 10:47:37 -07001059 const struct printf_spec *specp;
Linus Torvalds332d2e72008-10-20 15:07:34 +11001060
Petr Mladek3e5903e2019-04-17 13:53:48 +02001061 if (check_pointer(&buf, end, res, spec))
1062 return buf;
1063
Linus Torvalds332d2e72008-10-20 15:07:34 +11001064 *p++ = '[';
Bjorn Helgaas4da0b662010-03-05 10:47:37 -07001065 if (res->flags & IORESOURCE_IO) {
Petr Mladekd529ac42019-04-17 13:53:43 +02001066 p = string_nocheck(p, pend, "io ", str_spec);
Bjorn Helgaas4da0b662010-03-05 10:47:37 -07001067 specp = &io_spec;
1068 } else if (res->flags & IORESOURCE_MEM) {
Petr Mladekd529ac42019-04-17 13:53:43 +02001069 p = string_nocheck(p, pend, "mem ", str_spec);
Bjorn Helgaas4da0b662010-03-05 10:47:37 -07001070 specp = &mem_spec;
1071 } else if (res->flags & IORESOURCE_IRQ) {
Petr Mladekd529ac42019-04-17 13:53:43 +02001072 p = string_nocheck(p, pend, "irq ", str_spec);
Andy Shevchenkoce0b4912018-02-16 23:07:04 +02001073 specp = &default_dec_spec;
Bjorn Helgaas4da0b662010-03-05 10:47:37 -07001074 } else if (res->flags & IORESOURCE_DMA) {
Petr Mladekd529ac42019-04-17 13:53:43 +02001075 p = string_nocheck(p, pend, "dma ", str_spec);
Andy Shevchenkoce0b4912018-02-16 23:07:04 +02001076 specp = &default_dec_spec;
Bjorn Helgaas0f4050c2010-03-05 10:47:42 -07001077 } else if (res->flags & IORESOURCE_BUS) {
Petr Mladekd529ac42019-04-17 13:53:43 +02001078 p = string_nocheck(p, pend, "bus ", str_spec);
Bjorn Helgaas0f4050c2010-03-05 10:47:42 -07001079 specp = &bus_spec;
Bjorn Helgaas4da0b662010-03-05 10:47:37 -07001080 } else {
Petr Mladekd529ac42019-04-17 13:53:43 +02001081 p = string_nocheck(p, pend, "??? ", str_spec);
Bjorn Helgaas4da0b662010-03-05 10:47:37 -07001082 specp = &mem_spec;
Bjorn Helgaasc7dabef2009-10-27 13:26:47 -06001083 decode = 0;
Bjorn Helgaasfd955412009-10-06 15:33:39 -06001084 }
Bjorn Helgaasd19cb802014-02-26 11:25:56 -07001085 if (decode && res->flags & IORESOURCE_UNSET) {
Petr Mladekd529ac42019-04-17 13:53:43 +02001086 p = string_nocheck(p, pend, "size ", str_spec);
Bjorn Helgaasd19cb802014-02-26 11:25:56 -07001087 p = number(p, pend, resource_size(res), *specp);
1088 } else {
1089 p = number(p, pend, res->start, *specp);
1090 if (res->start != res->end) {
1091 *p++ = '-';
1092 p = number(p, pend, res->end, *specp);
1093 }
Bjorn Helgaasc91d3372009-10-06 15:33:34 -06001094 }
Bjorn Helgaasc7dabef2009-10-27 13:26:47 -06001095 if (decode) {
Bjorn Helgaasfd955412009-10-06 15:33:39 -06001096 if (res->flags & IORESOURCE_MEM_64)
Petr Mladekd529ac42019-04-17 13:53:43 +02001097 p = string_nocheck(p, pend, " 64bit", str_spec);
Bjorn Helgaasfd955412009-10-06 15:33:39 -06001098 if (res->flags & IORESOURCE_PREFETCH)
Petr Mladekd529ac42019-04-17 13:53:43 +02001099 p = string_nocheck(p, pend, " pref", str_spec);
Bjorn Helgaas9d7cca02010-03-05 10:47:47 -07001100 if (res->flags & IORESOURCE_WINDOW)
Petr Mladekd529ac42019-04-17 13:53:43 +02001101 p = string_nocheck(p, pend, " window", str_spec);
Bjorn Helgaasfd955412009-10-06 15:33:39 -06001102 if (res->flags & IORESOURCE_DISABLED)
Petr Mladekd529ac42019-04-17 13:53:43 +02001103 p = string_nocheck(p, pend, " disabled", str_spec);
Bjorn Helgaasc7dabef2009-10-27 13:26:47 -06001104 } else {
Petr Mladekd529ac42019-04-17 13:53:43 +02001105 p = string_nocheck(p, pend, " flags ", str_spec);
Andy Shevchenko54433972018-02-16 23:07:06 +02001106 p = number(p, pend, res->flags, default_flag_spec);
Bjorn Helgaasfd955412009-10-06 15:33:39 -06001107 }
Linus Torvalds332d2e72008-10-20 15:07:34 +11001108 *p++ = ']';
Bjorn Helgaasc7dabef2009-10-27 13:26:47 -06001109 *p = '\0';
Linus Torvalds332d2e72008-10-20 15:07:34 +11001110
Petr Mladekd529ac42019-04-17 13:53:43 +02001111 return string_nocheck(buf, end, sym, spec);
Linus Torvalds332d2e72008-10-20 15:07:34 +11001112}
1113
Joe Perchescf3b4292010-05-24 14:33:16 -07001114static noinline_for_stack
Andy Shevchenko31550a12012-07-30 14:40:27 -07001115char *hex_string(char *buf, char *end, u8 *addr, struct printf_spec spec,
1116 const char *fmt)
1117{
Steven Rostedt360603a2013-05-28 15:47:39 -04001118 int i, len = 1; /* if we pass '%ph[CDN]', field width remains
Andy Shevchenko31550a12012-07-30 14:40:27 -07001119 negative value, fallback to the default */
1120 char separator;
1121
1122 if (spec.field_width == 0)
1123 /* nothing to print */
1124 return buf;
1125
Petr Mladek3e5903e2019-04-17 13:53:48 +02001126 if (check_pointer(&buf, end, addr, spec))
1127 return buf;
Andy Shevchenko31550a12012-07-30 14:40:27 -07001128
1129 switch (fmt[1]) {
1130 case 'C':
1131 separator = ':';
1132 break;
1133 case 'D':
1134 separator = '-';
1135 break;
1136 case 'N':
1137 separator = 0;
1138 break;
1139 default:
1140 separator = ' ';
1141 break;
1142 }
1143
1144 if (spec.field_width > 0)
1145 len = min_t(int, spec.field_width, 64);
1146
Rasmus Villemoes9c98f232015-04-15 16:17:23 -07001147 for (i = 0; i < len; ++i) {
1148 if (buf < end)
1149 *buf = hex_asc_hi(addr[i]);
1150 ++buf;
1151 if (buf < end)
1152 *buf = hex_asc_lo(addr[i]);
1153 ++buf;
Andy Shevchenko31550a12012-07-30 14:40:27 -07001154
Rasmus Villemoes9c98f232015-04-15 16:17:23 -07001155 if (separator && i != len - 1) {
1156 if (buf < end)
1157 *buf = separator;
1158 ++buf;
1159 }
Andy Shevchenko31550a12012-07-30 14:40:27 -07001160 }
1161
1162 return buf;
1163}
1164
1165static noinline_for_stack
Tejun Heodbc760b2015-02-13 14:36:53 -08001166char *bitmap_string(char *buf, char *end, unsigned long *bitmap,
1167 struct printf_spec spec, const char *fmt)
1168{
1169 const int CHUNKSZ = 32;
1170 int nr_bits = max_t(int, spec.field_width, 0);
1171 int i, chunksz;
1172 bool first = true;
1173
Petr Mladek3e5903e2019-04-17 13:53:48 +02001174 if (check_pointer(&buf, end, bitmap, spec))
1175 return buf;
1176
Tejun Heodbc760b2015-02-13 14:36:53 -08001177 /* reused to print numbers */
1178 spec = (struct printf_spec){ .flags = SMALL | ZEROPAD, .base = 16 };
1179
1180 chunksz = nr_bits & (CHUNKSZ - 1);
1181 if (chunksz == 0)
1182 chunksz = CHUNKSZ;
1183
1184 i = ALIGN(nr_bits, CHUNKSZ) - CHUNKSZ;
1185 for (; i >= 0; i -= CHUNKSZ) {
1186 u32 chunkmask, val;
1187 int word, bit;
1188
1189 chunkmask = ((1ULL << chunksz) - 1);
1190 word = i / BITS_PER_LONG;
1191 bit = i % BITS_PER_LONG;
1192 val = (bitmap[word] >> bit) & chunkmask;
1193
1194 if (!first) {
1195 if (buf < end)
1196 *buf = ',';
1197 buf++;
1198 }
1199 first = false;
1200
1201 spec.field_width = DIV_ROUND_UP(chunksz, 4);
1202 buf = number(buf, end, val, spec);
1203
1204 chunksz = CHUNKSZ;
1205 }
1206 return buf;
1207}
1208
1209static noinline_for_stack
1210char *bitmap_list_string(char *buf, char *end, unsigned long *bitmap,
1211 struct printf_spec spec, const char *fmt)
1212{
1213 int nr_bits = max_t(int, spec.field_width, 0);
1214 /* current bit is 'cur', most recently seen range is [rbot, rtop] */
1215 int cur, rbot, rtop;
1216 bool first = true;
1217
Petr Mladek3e5903e2019-04-17 13:53:48 +02001218 if (check_pointer(&buf, end, bitmap, spec))
1219 return buf;
1220
Tejun Heodbc760b2015-02-13 14:36:53 -08001221 rbot = cur = find_first_bit(bitmap, nr_bits);
1222 while (cur < nr_bits) {
1223 rtop = cur;
1224 cur = find_next_bit(bitmap, nr_bits, cur + 1);
1225 if (cur < nr_bits && cur <= rtop + 1)
1226 continue;
1227
1228 if (!first) {
1229 if (buf < end)
1230 *buf = ',';
1231 buf++;
1232 }
1233 first = false;
1234
Andy Shevchenkoce0b4912018-02-16 23:07:04 +02001235 buf = number(buf, end, rbot, default_dec_spec);
Tejun Heodbc760b2015-02-13 14:36:53 -08001236 if (rbot < rtop) {
1237 if (buf < end)
1238 *buf = '-';
1239 buf++;
1240
Andy Shevchenkoce0b4912018-02-16 23:07:04 +02001241 buf = number(buf, end, rtop, default_dec_spec);
Tejun Heodbc760b2015-02-13 14:36:53 -08001242 }
1243
1244 rbot = cur;
1245 }
1246 return buf;
1247}
1248
1249static noinline_for_stack
Joe Perchescf3b4292010-05-24 14:33:16 -07001250char *mac_address_string(char *buf, char *end, u8 *addr,
1251 struct printf_spec spec, const char *fmt)
Harvey Harrisondd45c9c2008-10-27 15:47:12 -07001252{
Joe Perches8a27f7c2009-08-17 12:29:44 +00001253 char mac_addr[sizeof("xx:xx:xx:xx:xx:xx")];
Harvey Harrisondd45c9c2008-10-27 15:47:12 -07001254 char *p = mac_addr;
1255 int i;
Joe Perchesbc7259a2010-01-07 11:43:50 +00001256 char separator;
Andrei Emeltchenko76597ff92012-07-30 14:40:23 -07001257 bool reversed = false;
Joe Perchesbc7259a2010-01-07 11:43:50 +00001258
Petr Mladek3e5903e2019-04-17 13:53:48 +02001259 if (check_pointer(&buf, end, addr, spec))
1260 return buf;
1261
Andrei Emeltchenko76597ff92012-07-30 14:40:23 -07001262 switch (fmt[1]) {
1263 case 'F':
Joe Perchesbc7259a2010-01-07 11:43:50 +00001264 separator = '-';
Andrei Emeltchenko76597ff92012-07-30 14:40:23 -07001265 break;
1266
1267 case 'R':
1268 reversed = true;
Nick Desaulniers4c1ca832020-11-15 20:35:31 -08001269 fallthrough;
Andrei Emeltchenko76597ff92012-07-30 14:40:23 -07001270
1271 default:
Joe Perchesbc7259a2010-01-07 11:43:50 +00001272 separator = ':';
Andrei Emeltchenko76597ff92012-07-30 14:40:23 -07001273 break;
Joe Perchesbc7259a2010-01-07 11:43:50 +00001274 }
Harvey Harrisondd45c9c2008-10-27 15:47:12 -07001275
1276 for (i = 0; i < 6; i++) {
Andrei Emeltchenko76597ff92012-07-30 14:40:23 -07001277 if (reversed)
1278 p = hex_byte_pack(p, addr[5 - i]);
1279 else
1280 p = hex_byte_pack(p, addr[i]);
1281
Joe Perches8a27f7c2009-08-17 12:29:44 +00001282 if (fmt[0] == 'M' && i != 5)
Joe Perchesbc7259a2010-01-07 11:43:50 +00001283 *p++ = separator;
Harvey Harrisondd45c9c2008-10-27 15:47:12 -07001284 }
1285 *p = '\0';
1286
Petr Mladekd529ac42019-04-17 13:53:43 +02001287 return string_nocheck(buf, end, mac_addr, spec);
Harvey Harrisondd45c9c2008-10-27 15:47:12 -07001288}
1289
Joe Perchescf3b4292010-05-24 14:33:16 -07001290static noinline_for_stack
1291char *ip4_string(char *p, const u8 *addr, const char *fmt)
Harvey Harrison689afa72008-10-28 16:04:44 -07001292{
Harvey Harrison689afa72008-10-28 16:04:44 -07001293 int i;
Joe Perches0159f242010-01-13 20:23:30 -08001294 bool leading_zeros = (fmt[0] == 'i');
1295 int index;
1296 int step;
Harvey Harrison689afa72008-10-28 16:04:44 -07001297
Joe Perches0159f242010-01-13 20:23:30 -08001298 switch (fmt[2]) {
1299 case 'h':
1300#ifdef __BIG_ENDIAN
1301 index = 0;
1302 step = 1;
1303#else
1304 index = 3;
1305 step = -1;
1306#endif
1307 break;
1308 case 'l':
1309 index = 3;
1310 step = -1;
1311 break;
1312 case 'n':
1313 case 'b':
1314 default:
1315 index = 0;
1316 step = 1;
1317 break;
1318 }
Joe Perches8a27f7c2009-08-17 12:29:44 +00001319 for (i = 0; i < 4; i++) {
Rasmus Villemoes7c43d9a2015-04-16 12:43:22 -07001320 char temp[4] __aligned(2); /* hold each IP quad in reverse order */
Denys Vlasenko133fd9f2012-05-31 16:26:08 -07001321 int digits = put_dec_trunc8(temp, addr[index]) - temp;
Joe Perches8a27f7c2009-08-17 12:29:44 +00001322 if (leading_zeros) {
1323 if (digits < 3)
1324 *p++ = '0';
1325 if (digits < 2)
1326 *p++ = '0';
1327 }
1328 /* reverse the digits in the quad */
1329 while (digits--)
1330 *p++ = temp[digits];
1331 if (i < 3)
1332 *p++ = '.';
Joe Perches0159f242010-01-13 20:23:30 -08001333 index += step;
Joe Perches8a27f7c2009-08-17 12:29:44 +00001334 }
Joe Perches8a27f7c2009-08-17 12:29:44 +00001335 *p = '\0';
André Goddard Rosa7b9186f2009-12-14 18:00:57 -08001336
Joe Perches8a27f7c2009-08-17 12:29:44 +00001337 return p;
1338}
1339
Joe Perchescf3b4292010-05-24 14:33:16 -07001340static noinline_for_stack
1341char *ip6_compressed_string(char *p, const char *addr)
Joe Perches8a27f7c2009-08-17 12:29:44 +00001342{
André Goddard Rosa7b9186f2009-12-14 18:00:57 -08001343 int i, j, range;
Joe Perches8a27f7c2009-08-17 12:29:44 +00001344 unsigned char zerolength[8];
1345 int longest = 1;
1346 int colonpos = -1;
1347 u16 word;
André Goddard Rosa7b9186f2009-12-14 18:00:57 -08001348 u8 hi, lo;
Joe Perches8a27f7c2009-08-17 12:29:44 +00001349 bool needcolon = false;
Joe Percheseb78cd22009-09-18 13:04:06 +00001350 bool useIPv4;
1351 struct in6_addr in6;
1352
1353 memcpy(&in6, addr, sizeof(struct in6_addr));
1354
1355 useIPv4 = ipv6_addr_v4mapped(&in6) || ipv6_addr_is_isatap(&in6);
Joe Perches8a27f7c2009-08-17 12:29:44 +00001356
1357 memset(zerolength, 0, sizeof(zerolength));
1358
1359 if (useIPv4)
1360 range = 6;
1361 else
1362 range = 8;
1363
1364 /* find position of longest 0 run */
1365 for (i = 0; i < range; i++) {
1366 for (j = i; j < range; j++) {
Joe Percheseb78cd22009-09-18 13:04:06 +00001367 if (in6.s6_addr16[j] != 0)
Joe Perches8a27f7c2009-08-17 12:29:44 +00001368 break;
1369 zerolength[i]++;
1370 }
1371 }
1372 for (i = 0; i < range; i++) {
1373 if (zerolength[i] > longest) {
1374 longest = zerolength[i];
1375 colonpos = i;
1376 }
1377 }
Joe Perches29cf5192011-06-09 11:23:37 -07001378 if (longest == 1) /* don't compress a single 0 */
1379 colonpos = -1;
Joe Perches8a27f7c2009-08-17 12:29:44 +00001380
1381 /* emit address */
1382 for (i = 0; i < range; i++) {
1383 if (i == colonpos) {
1384 if (needcolon || i == 0)
1385 *p++ = ':';
1386 *p++ = ':';
1387 needcolon = false;
1388 i += longest - 1;
1389 continue;
1390 }
1391 if (needcolon) {
1392 *p++ = ':';
1393 needcolon = false;
1394 }
1395 /* hex u16 without leading 0s */
Joe Percheseb78cd22009-09-18 13:04:06 +00001396 word = ntohs(in6.s6_addr16[i]);
Joe Perches8a27f7c2009-08-17 12:29:44 +00001397 hi = word >> 8;
1398 lo = word & 0xff;
1399 if (hi) {
1400 if (hi > 0x0f)
Andy Shevchenko55036ba2011-10-31 17:12:41 -07001401 p = hex_byte_pack(p, hi);
Joe Perches8a27f7c2009-08-17 12:29:44 +00001402 else
1403 *p++ = hex_asc_lo(hi);
Andy Shevchenko55036ba2011-10-31 17:12:41 -07001404 p = hex_byte_pack(p, lo);
Joe Perches8a27f7c2009-08-17 12:29:44 +00001405 }
André Goddard Rosab5ff9922009-12-14 18:00:59 -08001406 else if (lo > 0x0f)
Andy Shevchenko55036ba2011-10-31 17:12:41 -07001407 p = hex_byte_pack(p, lo);
Joe Perches8a27f7c2009-08-17 12:29:44 +00001408 else
1409 *p++ = hex_asc_lo(lo);
1410 needcolon = true;
1411 }
1412
1413 if (useIPv4) {
1414 if (needcolon)
1415 *p++ = ':';
Joe Perches0159f242010-01-13 20:23:30 -08001416 p = ip4_string(p, &in6.s6_addr[12], "I4");
Joe Perches8a27f7c2009-08-17 12:29:44 +00001417 }
Joe Perches8a27f7c2009-08-17 12:29:44 +00001418 *p = '\0';
André Goddard Rosa7b9186f2009-12-14 18:00:57 -08001419
Joe Perches8a27f7c2009-08-17 12:29:44 +00001420 return p;
1421}
1422
Joe Perchescf3b4292010-05-24 14:33:16 -07001423static noinline_for_stack
1424char *ip6_string(char *p, const char *addr, const char *fmt)
Joe Perches8a27f7c2009-08-17 12:29:44 +00001425{
1426 int i;
André Goddard Rosa7b9186f2009-12-14 18:00:57 -08001427
Harvey Harrison689afa72008-10-28 16:04:44 -07001428 for (i = 0; i < 8; i++) {
Andy Shevchenko55036ba2011-10-31 17:12:41 -07001429 p = hex_byte_pack(p, *addr++);
1430 p = hex_byte_pack(p, *addr++);
Joe Perches8a27f7c2009-08-17 12:29:44 +00001431 if (fmt[0] == 'I' && i != 7)
Harvey Harrison689afa72008-10-28 16:04:44 -07001432 *p++ = ':';
1433 }
1434 *p = '\0';
André Goddard Rosa7b9186f2009-12-14 18:00:57 -08001435
Joe Perches8a27f7c2009-08-17 12:29:44 +00001436 return p;
1437}
1438
Joe Perchescf3b4292010-05-24 14:33:16 -07001439static noinline_for_stack
1440char *ip6_addr_string(char *buf, char *end, const u8 *addr,
1441 struct printf_spec spec, const char *fmt)
Joe Perches8a27f7c2009-08-17 12:29:44 +00001442{
1443 char ip6_addr[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
1444
1445 if (fmt[0] == 'I' && fmt[2] == 'c')
Joe Percheseb78cd22009-09-18 13:04:06 +00001446 ip6_compressed_string(ip6_addr, addr);
Joe Perches8a27f7c2009-08-17 12:29:44 +00001447 else
Joe Percheseb78cd22009-09-18 13:04:06 +00001448 ip6_string(ip6_addr, addr, fmt);
Harvey Harrison689afa72008-10-28 16:04:44 -07001449
Petr Mladekd529ac42019-04-17 13:53:43 +02001450 return string_nocheck(buf, end, ip6_addr, spec);
Harvey Harrison689afa72008-10-28 16:04:44 -07001451}
1452
Joe Perchescf3b4292010-05-24 14:33:16 -07001453static noinline_for_stack
1454char *ip4_addr_string(char *buf, char *end, const u8 *addr,
1455 struct printf_spec spec, const char *fmt)
Harvey Harrison4aa99602008-10-29 12:49:58 -07001456{
Joe Perches8a27f7c2009-08-17 12:29:44 +00001457 char ip4_addr[sizeof("255.255.255.255")];
Harvey Harrison4aa99602008-10-29 12:49:58 -07001458
Joe Perches0159f242010-01-13 20:23:30 -08001459 ip4_string(ip4_addr, addr, fmt);
Harvey Harrison4aa99602008-10-29 12:49:58 -07001460
Petr Mladekd529ac42019-04-17 13:53:43 +02001461 return string_nocheck(buf, end, ip4_addr, spec);
Harvey Harrison4aa99602008-10-29 12:49:58 -07001462}
1463
Joe Perchescf3b4292010-05-24 14:33:16 -07001464static noinline_for_stack
Daniel Borkmann10679642013-06-28 19:49:39 +02001465char *ip6_addr_string_sa(char *buf, char *end, const struct sockaddr_in6 *sa,
1466 struct printf_spec spec, const char *fmt)
1467{
1468 bool have_p = false, have_s = false, have_f = false, have_c = false;
1469 char ip6_addr[sizeof("[xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255]") +
1470 sizeof(":12345") + sizeof("/123456789") +
1471 sizeof("%1234567890")];
1472 char *p = ip6_addr, *pend = ip6_addr + sizeof(ip6_addr);
1473 const u8 *addr = (const u8 *) &sa->sin6_addr;
1474 char fmt6[2] = { fmt[0], '6' };
1475 u8 off = 0;
1476
1477 fmt++;
1478 while (isalpha(*++fmt)) {
1479 switch (*fmt) {
1480 case 'p':
1481 have_p = true;
1482 break;
1483 case 'f':
1484 have_f = true;
1485 break;
1486 case 's':
1487 have_s = true;
1488 break;
1489 case 'c':
1490 have_c = true;
1491 break;
1492 }
1493 }
1494
1495 if (have_p || have_s || have_f) {
1496 *p = '[';
1497 off = 1;
1498 }
1499
1500 if (fmt6[0] == 'I' && have_c)
1501 p = ip6_compressed_string(ip6_addr + off, addr);
1502 else
1503 p = ip6_string(ip6_addr + off, addr, fmt6);
1504
1505 if (have_p || have_s || have_f)
1506 *p++ = ']';
1507
1508 if (have_p) {
1509 *p++ = ':';
1510 p = number(p, pend, ntohs(sa->sin6_port), spec);
1511 }
1512 if (have_f) {
1513 *p++ = '/';
1514 p = number(p, pend, ntohl(sa->sin6_flowinfo &
1515 IPV6_FLOWINFO_MASK), spec);
1516 }
1517 if (have_s) {
1518 *p++ = '%';
1519 p = number(p, pend, sa->sin6_scope_id, spec);
1520 }
1521 *p = '\0';
1522
Petr Mladekd529ac42019-04-17 13:53:43 +02001523 return string_nocheck(buf, end, ip6_addr, spec);
Daniel Borkmann10679642013-06-28 19:49:39 +02001524}
1525
1526static noinline_for_stack
1527char *ip4_addr_string_sa(char *buf, char *end, const struct sockaddr_in *sa,
1528 struct printf_spec spec, const char *fmt)
1529{
1530 bool have_p = false;
1531 char *p, ip4_addr[sizeof("255.255.255.255") + sizeof(":12345")];
1532 char *pend = ip4_addr + sizeof(ip4_addr);
1533 const u8 *addr = (const u8 *) &sa->sin_addr.s_addr;
1534 char fmt4[3] = { fmt[0], '4', 0 };
1535
1536 fmt++;
1537 while (isalpha(*++fmt)) {
1538 switch (*fmt) {
1539 case 'p':
1540 have_p = true;
1541 break;
1542 case 'h':
1543 case 'l':
1544 case 'n':
1545 case 'b':
1546 fmt4[2] = *fmt;
1547 break;
1548 }
1549 }
1550
1551 p = ip4_string(ip4_addr, addr, fmt4);
1552 if (have_p) {
1553 *p++ = ':';
1554 p = number(p, pend, ntohs(sa->sin_port), spec);
1555 }
1556 *p = '\0';
1557
Petr Mladekd529ac42019-04-17 13:53:43 +02001558 return string_nocheck(buf, end, ip4_addr, spec);
Daniel Borkmann10679642013-06-28 19:49:39 +02001559}
1560
1561static noinline_for_stack
Petr Mladekf00cc102019-04-17 13:53:44 +02001562char *ip_addr_string(char *buf, char *end, const void *ptr,
1563 struct printf_spec spec, const char *fmt)
1564{
Petr Mladek0b74d4d2019-04-17 13:53:47 +02001565 char *err_fmt_msg;
1566
Petr Mladek3e5903e2019-04-17 13:53:48 +02001567 if (check_pointer(&buf, end, ptr, spec))
1568 return buf;
1569
Petr Mladekf00cc102019-04-17 13:53:44 +02001570 switch (fmt[1]) {
1571 case '6':
1572 return ip6_addr_string(buf, end, ptr, spec, fmt);
1573 case '4':
1574 return ip4_addr_string(buf, end, ptr, spec, fmt);
1575 case 'S': {
1576 const union {
1577 struct sockaddr raw;
1578 struct sockaddr_in v4;
1579 struct sockaddr_in6 v6;
1580 } *sa = ptr;
1581
1582 switch (sa->raw.sa_family) {
1583 case AF_INET:
1584 return ip4_addr_string_sa(buf, end, &sa->v4, spec, fmt);
1585 case AF_INET6:
1586 return ip6_addr_string_sa(buf, end, &sa->v6, spec, fmt);
1587 default:
Petr Mladekc8c3b582019-04-17 13:53:50 +02001588 return error_string(buf, end, "(einval)", spec);
Petr Mladekf00cc102019-04-17 13:53:44 +02001589 }}
1590 }
1591
Petr Mladek0b74d4d2019-04-17 13:53:47 +02001592 err_fmt_msg = fmt[0] == 'i' ? "(%pi?)" : "(%pI?)";
Petr Mladekc8c3b582019-04-17 13:53:50 +02001593 return error_string(buf, end, err_fmt_msg, spec);
Petr Mladekf00cc102019-04-17 13:53:44 +02001594}
1595
1596static noinline_for_stack
Andy Shevchenko71dca952014-10-13 15:55:18 -07001597char *escaped_string(char *buf, char *end, u8 *addr, struct printf_spec spec,
1598 const char *fmt)
1599{
1600 bool found = true;
1601 int count = 1;
1602 unsigned int flags = 0;
1603 int len;
1604
1605 if (spec.field_width == 0)
1606 return buf; /* nothing to print */
1607
Petr Mladek3e5903e2019-04-17 13:53:48 +02001608 if (check_pointer(&buf, end, addr, spec))
1609 return buf;
Andy Shevchenko71dca952014-10-13 15:55:18 -07001610
1611 do {
1612 switch (fmt[count++]) {
1613 case 'a':
1614 flags |= ESCAPE_ANY;
1615 break;
1616 case 'c':
1617 flags |= ESCAPE_SPECIAL;
1618 break;
1619 case 'h':
1620 flags |= ESCAPE_HEX;
1621 break;
1622 case 'n':
1623 flags |= ESCAPE_NULL;
1624 break;
1625 case 'o':
1626 flags |= ESCAPE_OCTAL;
1627 break;
1628 case 'p':
1629 flags |= ESCAPE_NP;
1630 break;
1631 case 's':
1632 flags |= ESCAPE_SPACE;
1633 break;
1634 default:
1635 found = false;
1636 break;
1637 }
1638 } while (found);
1639
1640 if (!flags)
1641 flags = ESCAPE_ANY_NP;
1642
1643 len = spec.field_width < 0 ? 1 : spec.field_width;
1644
Rasmus Villemoes41416f22015-04-15 16:17:28 -07001645 /*
1646 * string_escape_mem() writes as many characters as it can to
1647 * the given buffer, and returns the total size of the output
1648 * had the buffer been big enough.
1649 */
1650 buf += string_escape_mem(addr, len, buf, buf < end ? end - buf : 0, flags, NULL);
Andy Shevchenko71dca952014-10-13 15:55:18 -07001651
1652 return buf;
1653}
1654
Petr Mladek3e5903e2019-04-17 13:53:48 +02001655static char *va_format(char *buf, char *end, struct va_format *va_fmt,
1656 struct printf_spec spec, const char *fmt)
Petr Mladek45c3e932019-04-17 13:53:45 +02001657{
1658 va_list va;
1659
Petr Mladek3e5903e2019-04-17 13:53:48 +02001660 if (check_pointer(&buf, end, va_fmt, spec))
1661 return buf;
1662
Petr Mladek45c3e932019-04-17 13:53:45 +02001663 va_copy(va, *va_fmt->va);
1664 buf += vsnprintf(buf, end > buf ? end - buf : 0, va_fmt->fmt, va);
1665 va_end(va);
1666
1667 return buf;
1668}
1669
Andy Shevchenko71dca952014-10-13 15:55:18 -07001670static noinline_for_stack
Joe Perchescf3b4292010-05-24 14:33:16 -07001671char *uuid_string(char *buf, char *end, const u8 *addr,
1672 struct printf_spec spec, const char *fmt)
Joe Perches9ac6e442009-12-14 18:01:09 -08001673{
Andy Shevchenko2b1b0d62016-05-20 17:01:04 -07001674 char uuid[UUID_STRING_LEN + 1];
Joe Perches9ac6e442009-12-14 18:01:09 -08001675 char *p = uuid;
1676 int i;
Christoph Hellwigf9727a12017-05-17 10:02:48 +02001677 const u8 *index = uuid_index;
Joe Perches9ac6e442009-12-14 18:01:09 -08001678 bool uc = false;
1679
Petr Mladek3e5903e2019-04-17 13:53:48 +02001680 if (check_pointer(&buf, end, addr, spec))
1681 return buf;
1682
Joe Perches9ac6e442009-12-14 18:01:09 -08001683 switch (*(++fmt)) {
1684 case 'L':
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001685 uc = true;
Nick Desaulniers4c1ca832020-11-15 20:35:31 -08001686 fallthrough;
Joe Perches9ac6e442009-12-14 18:01:09 -08001687 case 'l':
Christoph Hellwigf9727a12017-05-17 10:02:48 +02001688 index = guid_index;
Joe Perches9ac6e442009-12-14 18:01:09 -08001689 break;
1690 case 'B':
1691 uc = true;
1692 break;
1693 }
1694
1695 for (i = 0; i < 16; i++) {
Andy Shevchenkoaa4ea1c2016-05-20 17:00:54 -07001696 if (uc)
1697 p = hex_byte_pack_upper(p, addr[index[i]]);
1698 else
1699 p = hex_byte_pack(p, addr[index[i]]);
Joe Perches9ac6e442009-12-14 18:01:09 -08001700 switch (i) {
1701 case 3:
1702 case 5:
1703 case 7:
1704 case 9:
1705 *p++ = '-';
1706 break;
1707 }
1708 }
1709
1710 *p = 0;
1711
Petr Mladekd529ac42019-04-17 13:53:43 +02001712 return string_nocheck(buf, end, uuid, spec);
Joe Perches9ac6e442009-12-14 18:01:09 -08001713}
1714
Andy Shevchenko5b17aec2016-01-15 16:59:20 -08001715static noinline_for_stack
Geert Uytterhoeven431bca22018-10-11 10:42:49 +02001716char *netdev_bits(char *buf, char *end, const void *addr,
1717 struct printf_spec spec, const char *fmt)
Michał Mirosławc8f44af2011-11-15 15:29:55 +00001718{
Andy Shevchenko5b17aec2016-01-15 16:59:20 -08001719 unsigned long long num;
1720 int size;
1721
Petr Mladek3e5903e2019-04-17 13:53:48 +02001722 if (check_pointer(&buf, end, addr, spec))
1723 return buf;
1724
Andy Shevchenko5b17aec2016-01-15 16:59:20 -08001725 switch (fmt[1]) {
1726 case 'F':
1727 num = *(const netdev_features_t *)addr;
1728 size = sizeof(netdev_features_t);
1729 break;
1730 default:
Petr Mladekc8c3b582019-04-17 13:53:50 +02001731 return error_string(buf, end, "(%pN?)", spec);
Andy Shevchenko5b17aec2016-01-15 16:59:20 -08001732 }
Michał Mirosławc8f44af2011-11-15 15:29:55 +00001733
Andy Shevchenko3cab1e72016-01-15 16:59:18 -08001734 return special_hex_number(buf, end, num, size);
Michał Mirosławc8f44af2011-11-15 15:29:55 +00001735}
1736
Joe Perchesaaf07622014-01-23 15:54:17 -08001737static noinline_for_stack
Sakari Ailusaf612e42021-02-16 17:57:20 +02001738char *fourcc_string(char *buf, char *end, const u32 *fourcc,
1739 struct printf_spec spec, const char *fmt)
1740{
1741 char output[sizeof("0123 little-endian (0x01234567)")];
1742 char *p = output;
1743 unsigned int i;
1744 u32 val;
1745
1746 if (fmt[1] != 'c' || fmt[2] != 'c')
1747 return error_string(buf, end, "(%p4?)", spec);
1748
1749 if (check_pointer(&buf, end, fourcc, spec))
1750 return buf;
1751
1752 val = *fourcc & ~BIT(31);
1753
1754 for (i = 0; i < sizeof(*fourcc); i++) {
1755 unsigned char c = val >> (i * 8);
1756
1757 /* Print non-control ASCII characters as-is, dot otherwise */
1758 *p++ = isascii(c) && isprint(c) ? c : '.';
1759 }
1760
1761 strcpy(p, *fourcc & BIT(31) ? " big-endian" : " little-endian");
1762 p += strlen(p);
1763
1764 *p++ = ' ';
1765 *p++ = '(';
1766 p = special_hex_number(p, output + sizeof(output) - 2, *fourcc, sizeof(u32));
1767 *p++ = ')';
1768 *p = '\0';
1769
1770 return string(buf, end, output, spec);
1771}
1772
1773static noinline_for_stack
Petr Mladek3e5903e2019-04-17 13:53:48 +02001774char *address_val(char *buf, char *end, const void *addr,
1775 struct printf_spec spec, const char *fmt)
Joe Perchesaaf07622014-01-23 15:54:17 -08001776{
1777 unsigned long long num;
Andy Shevchenko3cab1e72016-01-15 16:59:18 -08001778 int size;
Joe Perchesaaf07622014-01-23 15:54:17 -08001779
Petr Mladek3e5903e2019-04-17 13:53:48 +02001780 if (check_pointer(&buf, end, addr, spec))
1781 return buf;
1782
Joe Perchesaaf07622014-01-23 15:54:17 -08001783 switch (fmt[1]) {
1784 case 'd':
1785 num = *(const dma_addr_t *)addr;
Andy Shevchenko3cab1e72016-01-15 16:59:18 -08001786 size = sizeof(dma_addr_t);
Joe Perchesaaf07622014-01-23 15:54:17 -08001787 break;
1788 case 'p':
1789 default:
1790 num = *(const phys_addr_t *)addr;
Andy Shevchenko3cab1e72016-01-15 16:59:18 -08001791 size = sizeof(phys_addr_t);
Joe Perchesaaf07622014-01-23 15:54:17 -08001792 break;
1793 }
1794
Andy Shevchenko3cab1e72016-01-15 16:59:18 -08001795 return special_hex_number(buf, end, num, size);
Joe Perchesaaf07622014-01-23 15:54:17 -08001796}
1797
Geert Uytterhoeven900cca22015-04-15 16:17:20 -07001798static noinline_for_stack
Andy Shevchenko4d42c442018-12-04 23:23:11 +02001799char *date_str(char *buf, char *end, const struct rtc_time *tm, bool r)
1800{
1801 int year = tm->tm_year + (r ? 0 : 1900);
1802 int mon = tm->tm_mon + (r ? 0 : 1);
1803
1804 buf = number(buf, end, year, default_dec04_spec);
1805 if (buf < end)
1806 *buf = '-';
1807 buf++;
1808
1809 buf = number(buf, end, mon, default_dec02_spec);
1810 if (buf < end)
1811 *buf = '-';
1812 buf++;
1813
1814 return number(buf, end, tm->tm_mday, default_dec02_spec);
1815}
1816
1817static noinline_for_stack
1818char *time_str(char *buf, char *end, const struct rtc_time *tm, bool r)
1819{
1820 buf = number(buf, end, tm->tm_hour, default_dec02_spec);
1821 if (buf < end)
1822 *buf = ':';
1823 buf++;
1824
1825 buf = number(buf, end, tm->tm_min, default_dec02_spec);
1826 if (buf < end)
1827 *buf = ':';
1828 buf++;
1829
1830 return number(buf, end, tm->tm_sec, default_dec02_spec);
1831}
1832
1833static noinline_for_stack
Petr Mladek3e5903e2019-04-17 13:53:48 +02001834char *rtc_str(char *buf, char *end, const struct rtc_time *tm,
1835 struct printf_spec spec, const char *fmt)
Andy Shevchenko4d42c442018-12-04 23:23:11 +02001836{
1837 bool have_t = true, have_d = true;
1838 bool raw = false;
1839 int count = 2;
1840
Petr Mladek3e5903e2019-04-17 13:53:48 +02001841 if (check_pointer(&buf, end, tm, spec))
1842 return buf;
1843
Andy Shevchenko4d42c442018-12-04 23:23:11 +02001844 switch (fmt[count]) {
1845 case 'd':
1846 have_t = false;
1847 count++;
1848 break;
1849 case 't':
1850 have_d = false;
1851 count++;
1852 break;
1853 }
1854
1855 raw = fmt[count] == 'r';
1856
1857 if (have_d)
1858 buf = date_str(buf, end, tm, raw);
1859 if (have_d && have_t) {
1860 /* Respect ISO 8601 */
1861 if (buf < end)
1862 *buf = 'T';
1863 buf++;
1864 }
1865 if (have_t)
1866 buf = time_str(buf, end, tm, raw);
1867
1868 return buf;
1869}
1870
1871static noinline_for_stack
Andy Shevchenko7daac5b2020-04-15 20:00:44 +03001872char *time64_str(char *buf, char *end, const time64_t time,
1873 struct printf_spec spec, const char *fmt)
1874{
1875 struct rtc_time rtc_time;
1876 struct tm tm;
1877
1878 time64_to_tm(time, 0, &tm);
1879
1880 rtc_time.tm_sec = tm.tm_sec;
1881 rtc_time.tm_min = tm.tm_min;
1882 rtc_time.tm_hour = tm.tm_hour;
1883 rtc_time.tm_mday = tm.tm_mday;
1884 rtc_time.tm_mon = tm.tm_mon;
1885 rtc_time.tm_year = tm.tm_year;
1886 rtc_time.tm_wday = tm.tm_wday;
1887 rtc_time.tm_yday = tm.tm_yday;
1888
1889 rtc_time.tm_isdst = 0;
1890
1891 return rtc_str(buf, end, &rtc_time, spec, fmt);
1892}
1893
1894static noinline_for_stack
Andy Shevchenko4d42c442018-12-04 23:23:11 +02001895char *time_and_date(char *buf, char *end, void *ptr, struct printf_spec spec,
1896 const char *fmt)
1897{
1898 switch (fmt[1]) {
1899 case 'R':
Petr Mladek3e5903e2019-04-17 13:53:48 +02001900 return rtc_str(buf, end, (const struct rtc_time *)ptr, spec, fmt);
Andy Shevchenko7daac5b2020-04-15 20:00:44 +03001901 case 'T':
1902 return time64_str(buf, end, *(const time64_t *)ptr, spec, fmt);
Andy Shevchenko4d42c442018-12-04 23:23:11 +02001903 default:
Andy Shevchenko7daac5b2020-04-15 20:00:44 +03001904 return error_string(buf, end, "(%pt?)", spec);
Andy Shevchenko4d42c442018-12-04 23:23:11 +02001905 }
1906}
1907
1908static noinline_for_stack
Geert Uytterhoeven900cca22015-04-15 16:17:20 -07001909char *clock(char *buf, char *end, struct clk *clk, struct printf_spec spec,
1910 const char *fmt)
1911{
Petr Mladek0b74d4d2019-04-17 13:53:47 +02001912 if (!IS_ENABLED(CONFIG_HAVE_CLK))
Petr Mladekc8c3b582019-04-17 13:53:50 +02001913 return error_string(buf, end, "(%pC?)", spec);
Petr Mladek0b74d4d2019-04-17 13:53:47 +02001914
Petr Mladek3e5903e2019-04-17 13:53:48 +02001915 if (check_pointer(&buf, end, clk, spec))
1916 return buf;
Geert Uytterhoeven900cca22015-04-15 16:17:20 -07001917
1918 switch (fmt[1]) {
Geert Uytterhoeven900cca22015-04-15 16:17:20 -07001919 case 'n':
1920 default:
1921#ifdef CONFIG_COMMON_CLK
1922 return string(buf, end, __clk_get_name(clk), spec);
1923#else
Geert Uytterhoeven4ca96aa2019-07-01 16:00:09 +02001924 return ptr_to_id(buf, end, clk, spec);
Geert Uytterhoeven900cca22015-04-15 16:17:20 -07001925#endif
1926 }
1927}
1928
Vlastimil Babkaedf14cd2016-03-15 14:55:56 -07001929static
1930char *format_flags(char *buf, char *end, unsigned long flags,
1931 const struct trace_print_flags *names)
1932{
1933 unsigned long mask;
Vlastimil Babkaedf14cd2016-03-15 14:55:56 -07001934
1935 for ( ; flags && names->name; names++) {
1936 mask = names->mask;
1937 if ((flags & mask) != mask)
1938 continue;
1939
Andy Shevchenkoabd4fe62018-02-16 23:07:05 +02001940 buf = string(buf, end, names->name, default_str_spec);
Vlastimil Babkaedf14cd2016-03-15 14:55:56 -07001941
1942 flags &= ~mask;
1943 if (flags) {
1944 if (buf < end)
1945 *buf = '|';
1946 buf++;
1947 }
1948 }
1949
1950 if (flags)
Andy Shevchenko54433972018-02-16 23:07:06 +02001951 buf = number(buf, end, flags, default_flag_spec);
Vlastimil Babkaedf14cd2016-03-15 14:55:56 -07001952
1953 return buf;
1954}
1955
Yafang Shaoc2442972021-03-19 18:12:46 +08001956struct page_flags_fields {
1957 int width;
1958 int shift;
1959 int mask;
1960 const struct printf_spec *spec;
1961 const char *name;
1962};
1963
1964static const struct page_flags_fields pff[] = {
1965 {SECTIONS_WIDTH, SECTIONS_PGSHIFT, SECTIONS_MASK,
1966 &default_dec_spec, "section"},
1967 {NODES_WIDTH, NODES_PGSHIFT, NODES_MASK,
1968 &default_dec_spec, "node"},
1969 {ZONES_WIDTH, ZONES_PGSHIFT, ZONES_MASK,
1970 &default_dec_spec, "zone"},
1971 {LAST_CPUPID_WIDTH, LAST_CPUPID_PGSHIFT, LAST_CPUPID_MASK,
1972 &default_flag_spec, "lastcpupid"},
1973 {KASAN_TAG_WIDTH, KASAN_TAG_PGSHIFT, KASAN_TAG_MASK,
1974 &default_flag_spec, "kasantag"},
1975};
1976
1977static
1978char *format_page_flags(char *buf, char *end, unsigned long flags)
1979{
1980 unsigned long main_flags = flags & (BIT(NR_PAGEFLAGS) - 1);
1981 bool append = false;
1982 int i;
1983
1984 /* Page flags from the main area. */
1985 if (main_flags) {
1986 buf = format_flags(buf, end, main_flags, pageflag_names);
1987 append = true;
1988 }
1989
1990 /* Page flags from the fields area */
1991 for (i = 0; i < ARRAY_SIZE(pff); i++) {
1992 /* Skip undefined fields. */
1993 if (!pff[i].width)
1994 continue;
1995
1996 /* Format: Flag Name + '=' (equals sign) + Number + '|' (separator) */
1997 if (append) {
1998 if (buf < end)
1999 *buf = '|';
2000 buf++;
2001 }
2002
2003 buf = string(buf, end, pff[i].name, default_str_spec);
2004 if (buf < end)
2005 *buf = '=';
2006 buf++;
2007 buf = number(buf, end, (flags >> pff[i].shift) & pff[i].mask,
2008 *pff[i].spec);
2009
2010 append = true;
2011 }
2012
2013 return buf;
2014}
2015
Vlastimil Babkaedf14cd2016-03-15 14:55:56 -07002016static noinline_for_stack
Petr Mladek0b74d4d2019-04-17 13:53:47 +02002017char *flags_string(char *buf, char *end, void *flags_ptr,
2018 struct printf_spec spec, const char *fmt)
Vlastimil Babkaedf14cd2016-03-15 14:55:56 -07002019{
2020 unsigned long flags;
2021 const struct trace_print_flags *names;
2022
Petr Mladek3e5903e2019-04-17 13:53:48 +02002023 if (check_pointer(&buf, end, flags_ptr, spec))
2024 return buf;
2025
Vlastimil Babkaedf14cd2016-03-15 14:55:56 -07002026 switch (fmt[1]) {
2027 case 'p':
Yafang Shaoc2442972021-03-19 18:12:46 +08002028 return format_page_flags(buf, end, *(unsigned long *)flags_ptr);
Vlastimil Babkaedf14cd2016-03-15 14:55:56 -07002029 case 'v':
2030 flags = *(unsigned long *)flags_ptr;
2031 names = vmaflag_names;
2032 break;
2033 case 'g':
Andy Shevchenko30d497a2020-07-31 21:08:24 +03002034 flags = (__force unsigned long)(*(gfp_t *)flags_ptr);
Vlastimil Babkaedf14cd2016-03-15 14:55:56 -07002035 names = gfpflag_names;
2036 break;
2037 default:
Petr Mladekc8c3b582019-04-17 13:53:50 +02002038 return error_string(buf, end, "(%pG?)", spec);
Vlastimil Babkaedf14cd2016-03-15 14:55:56 -07002039 }
2040
2041 return format_flags(buf, end, flags, names);
2042}
2043
Pantelis Antoniouce4fecf2015-01-21 19:06:14 +02002044static noinline_for_stack
Sakari Ailusa92eb762019-10-03 15:32:16 +03002045char *fwnode_full_name_string(struct fwnode_handle *fwnode, char *buf,
2046 char *end)
Pantelis Antoniouce4fecf2015-01-21 19:06:14 +02002047{
2048 int depth;
Pantelis Antoniouce4fecf2015-01-21 19:06:14 +02002049
Sakari Ailusa92eb762019-10-03 15:32:16 +03002050 /* Loop starting from the root node to the current node. */
2051 for (depth = fwnode_count_parents(fwnode); depth >= 0; depth--) {
2052 struct fwnode_handle *__fwnode =
2053 fwnode_get_nth_parent(fwnode, depth);
Pantelis Antoniouce4fecf2015-01-21 19:06:14 +02002054
Sakari Ailusa92eb762019-10-03 15:32:16 +03002055 buf = string(buf, end, fwnode_get_name_prefix(__fwnode),
Andy Shevchenkoabd4fe62018-02-16 23:07:05 +02002056 default_str_spec);
Sakari Ailusa92eb762019-10-03 15:32:16 +03002057 buf = string(buf, end, fwnode_get_name(__fwnode),
2058 default_str_spec);
2059
2060 fwnode_handle_put(__fwnode);
Pantelis Antoniouce4fecf2015-01-21 19:06:14 +02002061 }
Sakari Ailusa92eb762019-10-03 15:32:16 +03002062
Pantelis Antoniouce4fecf2015-01-21 19:06:14 +02002063 return buf;
2064}
2065
2066static noinline_for_stack
2067char *device_node_string(char *buf, char *end, struct device_node *dn,
2068 struct printf_spec spec, const char *fmt)
2069{
2070 char tbuf[sizeof("xxxx") + 1];
2071 const char *p;
2072 int ret;
2073 char *buf_start = buf;
2074 struct property *prop;
2075 bool has_mult, pass;
Pantelis Antoniouce4fecf2015-01-21 19:06:14 +02002076
2077 struct printf_spec str_spec = spec;
2078 str_spec.field_width = -1;
2079
Sakari Ailus83abc5a2019-10-03 15:32:17 +03002080 if (fmt[0] != 'F')
2081 return error_string(buf, end, "(%pO?)", spec);
2082
Pantelis Antoniouce4fecf2015-01-21 19:06:14 +02002083 if (!IS_ENABLED(CONFIG_OF))
Petr Mladekc8c3b582019-04-17 13:53:50 +02002084 return error_string(buf, end, "(%pOF?)", spec);
Pantelis Antoniouce4fecf2015-01-21 19:06:14 +02002085
Petr Mladek3e5903e2019-04-17 13:53:48 +02002086 if (check_pointer(&buf, end, dn, spec))
2087 return buf;
Pantelis Antoniouce4fecf2015-01-21 19:06:14 +02002088
2089 /* simple case without anything any more format specifiers */
2090 fmt++;
2091 if (fmt[0] == '\0' || strcspn(fmt,"fnpPFcC") > 0)
2092 fmt = "f";
2093
2094 for (pass = false; strspn(fmt,"fnpPFcC"); fmt++, pass = true) {
Rob Herring6d0a70a2018-08-27 08:13:56 -05002095 int precision;
Pantelis Antoniouce4fecf2015-01-21 19:06:14 +02002096 if (pass) {
2097 if (buf < end)
2098 *buf = ':';
2099 buf++;
2100 }
2101
2102 switch (*fmt) {
2103 case 'f': /* full_name */
Sakari Ailusa92eb762019-10-03 15:32:16 +03002104 buf = fwnode_full_name_string(of_fwnode_handle(dn), buf,
2105 end);
Pantelis Antoniouce4fecf2015-01-21 19:06:14 +02002106 break;
2107 case 'n': /* name */
Sakari Ailusa92eb762019-10-03 15:32:16 +03002108 p = fwnode_get_name(of_fwnode_handle(dn));
Rob Herring6d0a70a2018-08-27 08:13:56 -05002109 precision = str_spec.precision;
2110 str_spec.precision = strchrnul(p, '@') - p;
2111 buf = string(buf, end, p, str_spec);
2112 str_spec.precision = precision;
Pantelis Antoniouce4fecf2015-01-21 19:06:14 +02002113 break;
2114 case 'p': /* phandle */
Andy Shevchenko09ceb8d2020-07-31 21:08:23 +03002115 buf = number(buf, end, (unsigned int)dn->phandle, default_dec_spec);
Pantelis Antoniouce4fecf2015-01-21 19:06:14 +02002116 break;
2117 case 'P': /* path-spec */
Sakari Ailusa92eb762019-10-03 15:32:16 +03002118 p = fwnode_get_name(of_fwnode_handle(dn));
Pantelis Antoniouce4fecf2015-01-21 19:06:14 +02002119 if (!p[1])
2120 p = "/";
2121 buf = string(buf, end, p, str_spec);
2122 break;
2123 case 'F': /* flags */
2124 tbuf[0] = of_node_check_flag(dn, OF_DYNAMIC) ? 'D' : '-';
2125 tbuf[1] = of_node_check_flag(dn, OF_DETACHED) ? 'd' : '-';
2126 tbuf[2] = of_node_check_flag(dn, OF_POPULATED) ? 'P' : '-';
2127 tbuf[3] = of_node_check_flag(dn, OF_POPULATED_BUS) ? 'B' : '-';
2128 tbuf[4] = 0;
Petr Mladekd529ac42019-04-17 13:53:43 +02002129 buf = string_nocheck(buf, end, tbuf, str_spec);
Pantelis Antoniouce4fecf2015-01-21 19:06:14 +02002130 break;
2131 case 'c': /* major compatible string */
2132 ret = of_property_read_string(dn, "compatible", &p);
2133 if (!ret)
2134 buf = string(buf, end, p, str_spec);
2135 break;
2136 case 'C': /* full compatible string */
2137 has_mult = false;
2138 of_property_for_each_string(dn, "compatible", prop, p) {
2139 if (has_mult)
Petr Mladekd529ac42019-04-17 13:53:43 +02002140 buf = string_nocheck(buf, end, ",", str_spec);
2141 buf = string_nocheck(buf, end, "\"", str_spec);
Pantelis Antoniouce4fecf2015-01-21 19:06:14 +02002142 buf = string(buf, end, p, str_spec);
Petr Mladekd529ac42019-04-17 13:53:43 +02002143 buf = string_nocheck(buf, end, "\"", str_spec);
Pantelis Antoniouce4fecf2015-01-21 19:06:14 +02002144
2145 has_mult = true;
2146 }
2147 break;
2148 default:
2149 break;
2150 }
2151 }
2152
2153 return widen_string(buf, buf - buf_start, end, spec);
2154}
2155
Sakari Ailus3bd32d62019-10-03 15:32:18 +03002156static noinline_for_stack
2157char *fwnode_string(char *buf, char *end, struct fwnode_handle *fwnode,
2158 struct printf_spec spec, const char *fmt)
Petr Mladek798cc272019-04-17 13:53:46 +02002159{
Sakari Ailus3bd32d62019-10-03 15:32:18 +03002160 struct printf_spec str_spec = spec;
2161 char *buf_start = buf;
2162
2163 str_spec.field_width = -1;
2164
2165 if (*fmt != 'w')
2166 return error_string(buf, end, "(%pf?)", spec);
2167
2168 if (check_pointer(&buf, end, fwnode, spec))
2169 return buf;
2170
2171 fmt++;
2172
2173 switch (*fmt) {
2174 case 'P': /* name */
2175 buf = string(buf, end, fwnode_get_name(fwnode), str_spec);
2176 break;
2177 case 'f': /* full_name */
2178 default:
2179 buf = fwnode_full_name_string(fwnode, buf, end);
2180 break;
Petr Mladek798cc272019-04-17 13:53:46 +02002181 }
2182
Sakari Ailus3bd32d62019-10-03 15:32:18 +03002183 return widen_string(buf, buf - buf_start, end, spec);
Petr Mladek798cc272019-04-17 13:53:46 +02002184}
2185
Timur Tabi5ead7232021-02-14 10:13:48 -06002186/* Disable pointer hashing if requested */
2187bool no_hash_pointers __ro_after_init;
2188EXPORT_SYMBOL_GPL(no_hash_pointers);
2189
Stephen Boyd79270292021-06-28 19:34:52 -07002190int __init no_hash_pointers_enable(char *str)
Timur Tabi5ead7232021-02-14 10:13:48 -06002191{
Marco Elver9f961c22021-03-05 20:42:05 +01002192 if (no_hash_pointers)
2193 return 0;
2194
Timur Tabi5ead7232021-02-14 10:13:48 -06002195 no_hash_pointers = true;
2196
2197 pr_warn("**********************************************************\n");
2198 pr_warn("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n");
2199 pr_warn("** **\n");
2200 pr_warn("** This system shows unhashed kernel memory addresses **\n");
2201 pr_warn("** via the console, logs, and other interfaces. This **\n");
2202 pr_warn("** might reduce the security of your system. **\n");
2203 pr_warn("** **\n");
2204 pr_warn("** If you see this message and you are not debugging **\n");
2205 pr_warn("** the kernel, report this immediately to your system **\n");
2206 pr_warn("** administrator! **\n");
2207 pr_warn("** **\n");
2208 pr_warn("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n");
2209 pr_warn("**********************************************************\n");
2210
2211 return 0;
2212}
2213early_param("no_hash_pointers", no_hash_pointers_enable);
2214
Linus Torvalds4d8a7432008-07-06 16:24:57 -07002215/*
2216 * Show a '%p' thing. A kernel extension is that the '%p' is followed
2217 * by an extra set of alphanumeric characters that are extended format
2218 * specifiers.
2219 *
Joe Perches0b523762017-05-08 15:55:36 -07002220 * Please update scripts/checkpatch.pl when adding/removing conversion
2221 * characters. (Search for "check for vsprintf extension").
2222 *
Linus Torvalds332d2e72008-10-20 15:07:34 +11002223 * Right now we handle:
Linus Torvalds0fe1ef22008-07-06 16:43:12 -07002224 *
Sergey Senozhatskycdb7e522018-04-14 12:00:05 +09002225 * - 'S' For symbolic direct pointers (or function descriptors) with offset
2226 * - 's' For symbolic direct pointers (or function descriptors) without offset
Sakari Ailus9af77062019-10-03 15:32:14 +03002227 * - '[Ss]R' as above with __builtin_extract_return_addr() translation
Sakari Ailus1586c5a2019-10-03 15:32:15 +03002228 * - '[Ff]' %pf and %pF were obsoleted and later removed in favor of
2229 * %ps and %pS. Be careful when re-using these specifiers.
Namhyung Kim0f77a8d2011-03-24 11:42:29 +09002230 * - 'B' For backtraced symbolic direct pointers with offset
Bjorn Helgaasc7dabef2009-10-27 13:26:47 -06002231 * - 'R' For decoded struct resource, e.g., [mem 0x0-0x1f 64bit pref]
2232 * - 'r' For raw struct resource, e.g., [mem 0x0-0x1f flags 0x201]
Tejun Heodbc760b2015-02-13 14:36:53 -08002233 * - 'b[l]' For a bitmap, the number of bits is determined by the field
2234 * width which must be explicitly specified either as part of the
2235 * format string '%32b[l]' or through '%*b[l]', [l] selects
2236 * range-list format instead of hex format
Harvey Harrisondd45c9c2008-10-27 15:47:12 -07002237 * - 'M' For a 6-byte MAC address, it prints the address in the
2238 * usual colon-separated hex notation
Joe Perches8a27f7c2009-08-17 12:29:44 +00002239 * - 'm' For a 6-byte MAC address, it prints the hex address without colons
Joe Perchesbc7259a2010-01-07 11:43:50 +00002240 * - 'MF' For a 6-byte MAC FDDI address, it prints the address
Joe Perchesc8e00062010-01-11 00:44:14 -08002241 * with a dash-separated hex notation
Andy Shevchenko7c591542012-10-04 17:12:33 -07002242 * - '[mM]R' For a 6-byte MAC address, Reverse order (Bluetooth)
Joe Perches8a27f7c2009-08-17 12:29:44 +00002243 * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way
2244 * IPv4 uses dot-separated decimal without leading 0's (1.2.3.4)
2245 * IPv6 uses colon separated network-order 16 bit hex with leading 0's
Daniel Borkmann10679642013-06-28 19:49:39 +02002246 * [S][pfs]
2247 * Generic IPv4/IPv6 address (struct sockaddr *) that falls back to
2248 * [4] or [6] and is able to print port [p], flowinfo [f], scope [s]
Joe Perches8a27f7c2009-08-17 12:29:44 +00002249 * - 'i' [46] for 'raw' IPv4/IPv6 addresses
2250 * IPv6 omits the colons (01020304...0f)
2251 * IPv4 uses dot-separated decimal with leading 0's (010.123.045.006)
Daniel Borkmann10679642013-06-28 19:49:39 +02002252 * [S][pfs]
2253 * Generic IPv4/IPv6 address (struct sockaddr *) that falls back to
2254 * [4] or [6] and is able to print port [p], flowinfo [f], scope [s]
2255 * - '[Ii][4S][hnbl]' IPv4 addresses in host, network, big or little endian order
2256 * - 'I[6S]c' for IPv6 addresses printed as specified by
Alexander A. Klimov8eda94b2020-07-02 22:05:36 +02002257 * https://tools.ietf.org/html/rfc5952
Andy Shevchenko71dca952014-10-13 15:55:18 -07002258 * - 'E[achnops]' For an escaped buffer, where rules are defined by combination
2259 * of the following flags (see string_escape_mem() for the
2260 * details):
2261 * a - ESCAPE_ANY
2262 * c - ESCAPE_SPECIAL
2263 * h - ESCAPE_HEX
2264 * n - ESCAPE_NULL
2265 * o - ESCAPE_OCTAL
2266 * p - ESCAPE_NP
2267 * s - ESCAPE_SPACE
2268 * By default ESCAPE_ANY_NP is used.
Joe Perches9ac6e442009-12-14 18:01:09 -08002269 * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form
2270 * "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
2271 * Options for %pU are:
2272 * b big endian lower case hex (default)
2273 * B big endian UPPER case hex
2274 * l little endian lower case hex
2275 * L little endian UPPER case hex
2276 * big endian output byte order is:
2277 * [0][1][2][3]-[4][5]-[6][7]-[8][9]-[10][11][12][13][14][15]
2278 * little endian output byte order is:
2279 * [3][2][1][0]-[5][4]-[7][6]-[8][9]-[10][11][12][13][14][15]
Joe Perches7db6f5f2010-06-27 01:02:33 +00002280 * - 'V' For a struct va_format which contains a format string * and va_list *,
2281 * call vsnprintf(->format, *->va_list).
2282 * Implements a "recursive vsnprintf".
2283 * Do not use this feature without some mechanism to verify the
2284 * correctness of the format string and va_list arguments.
Vlastimil Babkaa48849e2021-02-25 17:46:39 +01002285 * - 'K' For a kernel pointer that should be hidden from unprivileged users.
2286 * Use only for procfs, sysfs and similar files, not printk(); please
2287 * read the documentation (path below) first.
Michał Mirosławc8f44af2011-11-15 15:29:55 +00002288 * - 'NF' For a netdev_features_t
Sakari Ailusaf612e42021-02-16 17:57:20 +02002289 * - '4cc' V4L2 or DRM FourCC code, with endianness and raw numerical value.
Andy Shevchenko31550a12012-07-30 14:40:27 -07002290 * - 'h[CDN]' For a variable-length buffer, it prints it as a hex string with
2291 * a certain separator (' ' by default):
2292 * C colon
2293 * D dash
2294 * N no separator
2295 * The maximum supported length is 64 bytes of the input. Consider
2296 * to use print_hex_dump() for the larger input.
Joe Perchesaaf07622014-01-23 15:54:17 -08002297 * - 'a[pd]' For address types [p] phys_addr_t, [d] dma_addr_t and derivatives
2298 * (default assumed to be phys_addr_t, passed by reference)
Olof Johanssonc0d92a52013-11-12 15:09:50 -08002299 * - 'd[234]' For a dentry name (optionally 2-4 last components)
2300 * - 'D[234]' Same as 'd' but for a struct file
Dmitry Monakhov1031bc52015-04-13 16:31:35 +04002301 * - 'g' For block_device name (gendisk + partition number)
Andy Shevchenko7daac5b2020-04-15 20:00:44 +03002302 * - 't[RT][dt][r]' For time and date as represented by:
Andy Shevchenko4d42c442018-12-04 23:23:11 +02002303 * R struct rtc_time
Andy Shevchenko7daac5b2020-04-15 20:00:44 +03002304 * T time64_t
Geert Uytterhoeven900cca22015-04-15 16:17:20 -07002305 * - 'C' For a clock, it prints the name (Common Clock Framework) or address
2306 * (legacy clock framework) of the clock
2307 * - 'Cn' For a clock, it prints the name (Common Clock Framework) or address
2308 * (legacy clock framework) of the clock
Vlastimil Babkaedf14cd2016-03-15 14:55:56 -07002309 * - 'G' For flags to be printed as a collection of symbolic strings that would
2310 * construct the specific value. Supported flags given by option:
2311 * p page flags (see struct page) given as pointer to unsigned long
2312 * g gfp flags (GFP_* and __GFP_*) given as pointer to gfp_t
2313 * v vma flags (VM_*) given as pointer to unsigned long
Geert Uytterhoeven94ac8f22018-10-08 13:08:48 +02002314 * - 'OF[fnpPcCF]' For a device tree object
2315 * Without any optional arguments prints the full_name
2316 * f device node full_name
2317 * n device node name
2318 * p device node phandle
2319 * P device node path spec (name + @unit)
2320 * F device node flags
2321 * c major compatible string
2322 * C full compatible string
Sakari Ailus3bd32d62019-10-03 15:32:18 +03002323 * - 'fw[fP]' For a firmware node (struct fwnode_handle) pointer
2324 * Without an option prints the full name of the node
2325 * f full name
2326 * P node name, including a possible unit address
Vlastimil Babkaa48849e2021-02-25 17:46:39 +01002327 * - 'x' For printing the address unmodified. Equivalent to "%lx".
2328 * Please read the documentation (path below) before using!
Daniel Borkmannb2a52122020-05-15 12:11:18 +02002329 * - '[ku]s' For a BPF/tracing related format specifier, e.g. used out of
2330 * bpf_trace_printk() where [ku] prefix specifies either kernel (k)
2331 * or user (u) memory to probe, and:
2332 * s a string, equivalent to "%s" on direct vsnprintf() use
Tobin C. Harding7b1924a2017-11-23 10:59:45 +11002333 *
Tobin C. Hardingb3ed2322017-12-20 08:17:15 +11002334 * ** When making changes please also update:
2335 * Documentation/core-api/printk-formats.rst
Joe Perches9ac6e442009-12-14 18:01:09 -08002336 *
Tobin C. Hardingad67b742017-11-01 15:32:23 +11002337 * Note: The default behaviour (unadorned %p) is to hash the address,
2338 * rendering it useful as a unique identifier.
Linus Torvalds4d8a7432008-07-06 16:24:57 -07002339 */
Joe Perchescf3b4292010-05-24 14:33:16 -07002340static noinline_for_stack
2341char *pointer(const char *fmt, char *buf, char *end, void *ptr,
2342 struct printf_spec spec)
Linus Torvalds78a8bf62008-07-06 16:16:15 -07002343{
Linus Torvalds0fe1ef22008-07-06 16:43:12 -07002344 switch (*fmt) {
Linus Torvalds0fe1ef22008-07-06 16:43:12 -07002345 case 'S':
Joe Perches9ac6e442009-12-14 18:01:09 -08002346 case 's':
Sergey Senozhatsky04b8eb72017-12-06 13:36:49 +09002347 ptr = dereference_symbol_descriptor(ptr);
Nick Desaulniers4c1ca832020-11-15 20:35:31 -08002348 fallthrough;
Namhyung Kim0f77a8d2011-03-24 11:42:29 +09002349 case 'B':
Joe Perchesb0d33c22012-12-12 10:18:50 -08002350 return symbol_string(buf, end, ptr, spec, fmt);
Linus Torvalds332d2e72008-10-20 15:07:34 +11002351 case 'R':
Bjorn Helgaasc7dabef2009-10-27 13:26:47 -06002352 case 'r':
Bjorn Helgaasfd955412009-10-06 15:33:39 -06002353 return resource_string(buf, end, ptr, spec, fmt);
Andy Shevchenko31550a12012-07-30 14:40:27 -07002354 case 'h':
2355 return hex_string(buf, end, ptr, spec, fmt);
Tejun Heodbc760b2015-02-13 14:36:53 -08002356 case 'b':
2357 switch (fmt[1]) {
2358 case 'l':
2359 return bitmap_list_string(buf, end, ptr, spec, fmt);
2360 default:
2361 return bitmap_string(buf, end, ptr, spec, fmt);
2362 }
Joe Perches8a27f7c2009-08-17 12:29:44 +00002363 case 'M': /* Colon separated: 00:01:02:03:04:05 */
2364 case 'm': /* Contiguous: 000102030405 */
Andrei Emeltchenko76597ff92012-07-30 14:40:23 -07002365 /* [mM]F (FDDI) */
2366 /* [mM]R (Reverse order; Bluetooth) */
Joe Perches8a27f7c2009-08-17 12:29:44 +00002367 return mac_address_string(buf, end, ptr, spec, fmt);
2368 case 'I': /* Formatted IP supported
2369 * 4: 1.2.3.4
2370 * 6: 0001:0203:...:0708
2371 * 6c: 1::708 or 1::1.2.3.4
2372 */
2373 case 'i': /* Contiguous:
2374 * 4: 001.002.003.004
2375 * 6: 000102...0f
2376 */
Petr Mladekf00cc102019-04-17 13:53:44 +02002377 return ip_addr_string(buf, end, ptr, spec, fmt);
Andy Shevchenko71dca952014-10-13 15:55:18 -07002378 case 'E':
2379 return escaped_string(buf, end, ptr, spec, fmt);
Joe Perches9ac6e442009-12-14 18:01:09 -08002380 case 'U':
2381 return uuid_string(buf, end, ptr, spec, fmt);
Joe Perches7db6f5f2010-06-27 01:02:33 +00002382 case 'V':
Petr Mladek3e5903e2019-04-17 13:53:48 +02002383 return va_format(buf, end, ptr, spec, fmt);
Dan Rosenberg455cd5a2011-01-12 16:59:41 -08002384 case 'K':
Tobin C. Harding57e73442017-11-23 10:56:39 +11002385 return restricted_pointer(buf, end, ptr, spec);
Michał Mirosławc8f44af2011-11-15 15:29:55 +00002386 case 'N':
Geert Uytterhoeven431bca22018-10-11 10:42:49 +02002387 return netdev_bits(buf, end, ptr, spec, fmt);
Sakari Ailusaf612e42021-02-16 17:57:20 +02002388 case '4':
2389 return fourcc_string(buf, end, ptr, spec, fmt);
Stepan Moskovchenko7d799212013-02-21 16:43:09 -08002390 case 'a':
Petr Mladek3e5903e2019-04-17 13:53:48 +02002391 return address_val(buf, end, ptr, spec, fmt);
Al Viro4b6ccca2013-09-03 12:00:44 -04002392 case 'd':
2393 return dentry_name(buf, end, ptr, spec, fmt);
Andy Shevchenko4d42c442018-12-04 23:23:11 +02002394 case 't':
2395 return time_and_date(buf, end, ptr, spec, fmt);
Geert Uytterhoeven900cca22015-04-15 16:17:20 -07002396 case 'C':
2397 return clock(buf, end, ptr, spec, fmt);
Al Viro4b6ccca2013-09-03 12:00:44 -04002398 case 'D':
Jia He36594b32019-08-09 09:24:56 +08002399 return file_dentry_name(buf, end, ptr, spec, fmt);
Dmitry Monakhov1031bc52015-04-13 16:31:35 +04002400#ifdef CONFIG_BLOCK
2401 case 'g':
2402 return bdev_name(buf, end, ptr, spec, fmt);
2403#endif
2404
Vlastimil Babkaedf14cd2016-03-15 14:55:56 -07002405 case 'G':
Petr Mladek0b74d4d2019-04-17 13:53:47 +02002406 return flags_string(buf, end, ptr, spec, fmt);
Pantelis Antoniouce4fecf2015-01-21 19:06:14 +02002407 case 'O':
Sakari Ailus83abc5a2019-10-03 15:32:17 +03002408 return device_node_string(buf, end, ptr, spec, fmt + 1);
Sakari Ailus3bd32d62019-10-03 15:32:18 +03002409 case 'f':
2410 return fwnode_string(buf, end, ptr, spec, fmt + 1);
Tobin C. Harding7b1924a2017-11-23 10:59:45 +11002411 case 'x':
2412 return pointer_string(buf, end, ptr, spec);
Rasmus Villemoes57f56772019-10-15 21:07:05 +02002413 case 'e':
2414 /* %pe with a non-ERR_PTR gets treated as plain %p */
2415 if (!IS_ERR(ptr))
2416 break;
2417 return err_ptr(buf, end, ptr, spec);
Daniel Borkmannb2a52122020-05-15 12:11:18 +02002418 case 'u':
2419 case 'k':
2420 switch (fmt[1]) {
2421 case 's':
2422 return string(buf, end, ptr, spec);
2423 default:
2424 return error_string(buf, end, "(einval)", spec);
2425 }
Linus Torvalds0fe1ef22008-07-06 16:43:12 -07002426 }
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002427
Timur Tabi5ead7232021-02-14 10:13:48 -06002428 /*
2429 * default is to _not_ leak addresses, so hash before printing,
2430 * unless no_hash_pointers is specified on the command line.
2431 */
2432 if (unlikely(no_hash_pointers))
2433 return pointer_string(buf, end, ptr, spec);
2434 else
2435 return ptr_to_id(buf, end, ptr, spec);
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002436}
2437
2438/*
2439 * Helper function to decode printf style format.
2440 * Each call decode a token from the format and return the
2441 * number of characters read (or likely the delta where it wants
2442 * to go on the next call).
2443 * The decoded token is returned through the parameters
2444 *
2445 * 'h', 'l', or 'L' for integer fields
2446 * 'z' support added 23/7/1999 S.H.
2447 * 'z' changed to 'Z' --davidm 1/25/99
Alexey Dobriyan5b5e0922017-02-27 14:30:02 -08002448 * 'Z' changed to 'z' --adobriyan 2017-01-25
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002449 * 't' added for ptrdiff_t
2450 *
2451 * @fmt: the format string
2452 * @type of the token returned
2453 * @flags: various flags such as +, -, # tokens..
2454 * @field_width: overwritten width
2455 * @base: base of the number (octal, hex, ...)
2456 * @precision: precision of a number
2457 * @qualifier: qualifier of a number (long, size_t, ...)
2458 */
Joe Perchescf3b4292010-05-24 14:33:16 -07002459static noinline_for_stack
2460int format_decode(const char *fmt, struct printf_spec *spec)
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002461{
2462 const char *start = fmt;
Rasmus Villemoesd0484192016-01-15 16:58:37 -08002463 char qualifier;
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002464
2465 /* we finished early by reading the field width */
Vegard Nossumed681a92009-03-14 12:08:50 +01002466 if (spec->type == FORMAT_TYPE_WIDTH) {
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002467 if (spec->field_width < 0) {
2468 spec->field_width = -spec->field_width;
2469 spec->flags |= LEFT;
2470 }
2471 spec->type = FORMAT_TYPE_NONE;
2472 goto precision;
2473 }
2474
2475 /* we finished early by reading the precision */
2476 if (spec->type == FORMAT_TYPE_PRECISION) {
2477 if (spec->precision < 0)
2478 spec->precision = 0;
2479
2480 spec->type = FORMAT_TYPE_NONE;
2481 goto qualifier;
2482 }
2483
2484 /* By default */
2485 spec->type = FORMAT_TYPE_NONE;
2486
2487 for (; *fmt ; ++fmt) {
2488 if (*fmt == '%')
2489 break;
2490 }
2491
2492 /* Return the current non-format string */
2493 if (fmt != start || !*fmt)
2494 return fmt - start;
2495
2496 /* Process flags */
2497 spec->flags = 0;
2498
2499 while (1) { /* this also skips first '%' */
2500 bool found = true;
2501
2502 ++fmt;
2503
2504 switch (*fmt) {
2505 case '-': spec->flags |= LEFT; break;
2506 case '+': spec->flags |= PLUS; break;
2507 case ' ': spec->flags |= SPACE; break;
2508 case '#': spec->flags |= SPECIAL; break;
2509 case '0': spec->flags |= ZEROPAD; break;
2510 default: found = false;
2511 }
2512
2513 if (!found)
2514 break;
2515 }
2516
2517 /* get field width */
2518 spec->field_width = -1;
2519
2520 if (isdigit(*fmt))
2521 spec->field_width = skip_atoi(&fmt);
2522 else if (*fmt == '*') {
2523 /* it's the next argument */
Vegard Nossumed681a92009-03-14 12:08:50 +01002524 spec->type = FORMAT_TYPE_WIDTH;
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002525 return ++fmt - start;
2526 }
2527
2528precision:
2529 /* get the precision */
2530 spec->precision = -1;
2531 if (*fmt == '.') {
2532 ++fmt;
2533 if (isdigit(*fmt)) {
2534 spec->precision = skip_atoi(&fmt);
2535 if (spec->precision < 0)
2536 spec->precision = 0;
2537 } else if (*fmt == '*') {
2538 /* it's the next argument */
Vegard Nossumadf26f82009-03-14 12:08:50 +01002539 spec->type = FORMAT_TYPE_PRECISION;
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002540 return ++fmt - start;
2541 }
2542 }
2543
2544qualifier:
2545 /* get the conversion qualifier */
Rasmus Villemoesd0484192016-01-15 16:58:37 -08002546 qualifier = 0;
Andy Shevchenko75fb8f22011-07-25 17:13:20 -07002547 if (*fmt == 'h' || _tolower(*fmt) == 'l' ||
Alexey Dobriyan5b5e0922017-02-27 14:30:02 -08002548 *fmt == 'z' || *fmt == 't') {
Rasmus Villemoesd0484192016-01-15 16:58:37 -08002549 qualifier = *fmt++;
2550 if (unlikely(qualifier == *fmt)) {
2551 if (qualifier == 'l') {
2552 qualifier = 'L';
Zhaoleia4e94ef2009-03-27 17:07:05 +08002553 ++fmt;
Rasmus Villemoesd0484192016-01-15 16:58:37 -08002554 } else if (qualifier == 'h') {
2555 qualifier = 'H';
Zhaoleia4e94ef2009-03-27 17:07:05 +08002556 ++fmt;
2557 }
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002558 }
2559 }
2560
2561 /* default base */
2562 spec->base = 10;
2563 switch (*fmt) {
2564 case 'c':
2565 spec->type = FORMAT_TYPE_CHAR;
2566 return ++fmt - start;
2567
2568 case 's':
2569 spec->type = FORMAT_TYPE_STR;
2570 return ++fmt - start;
2571
2572 case 'p':
2573 spec->type = FORMAT_TYPE_PTR;
Rasmus Villemoesffbfed02015-02-12 15:01:37 -08002574 return ++fmt - start;
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002575
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002576 case '%':
2577 spec->type = FORMAT_TYPE_PERCENT_CHAR;
2578 return ++fmt - start;
2579
2580 /* integer number formats - set up the flags and "break" */
2581 case 'o':
2582 spec->base = 8;
2583 break;
2584
2585 case 'x':
2586 spec->flags |= SMALL;
Nick Desaulniers4c1ca832020-11-15 20:35:31 -08002587 fallthrough;
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002588
2589 case 'X':
2590 spec->base = 16;
2591 break;
2592
2593 case 'd':
2594 case 'i':
Frederic Weisbecker39e874f2009-03-09 21:15:04 +01002595 spec->flags |= SIGN;
Gustavo A. R. Silva36f9ff92020-11-19 07:11:44 -06002596 break;
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002597 case 'u':
2598 break;
2599
Ryan Mallon708d96fd2014-04-03 14:48:37 -07002600 case 'n':
2601 /*
Rasmus Villemoesb006f192015-11-06 16:30:20 -08002602 * Since %n poses a greater security risk than
2603 * utility, treat it as any other invalid or
2604 * unsupported format specifier.
Ryan Mallon708d96fd2014-04-03 14:48:37 -07002605 */
Nick Desaulniers4c1ca832020-11-15 20:35:31 -08002606 fallthrough;
Ryan Mallon708d96fd2014-04-03 14:48:37 -07002607
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002608 default:
Rasmus Villemoesb006f192015-11-06 16:30:20 -08002609 WARN_ONCE(1, "Please remove unsupported %%%c in format string\n", *fmt);
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002610 spec->type = FORMAT_TYPE_INVALID;
2611 return fmt - start;
2612 }
2613
Rasmus Villemoesd0484192016-01-15 16:58:37 -08002614 if (qualifier == 'L')
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002615 spec->type = FORMAT_TYPE_LONG_LONG;
Rasmus Villemoesd0484192016-01-15 16:58:37 -08002616 else if (qualifier == 'l') {
Rasmus Villemoes51be17d2015-04-15 16:17:02 -07002617 BUILD_BUG_ON(FORMAT_TYPE_ULONG + SIGN != FORMAT_TYPE_LONG);
2618 spec->type = FORMAT_TYPE_ULONG + (spec->flags & SIGN);
Alexey Dobriyan5b5e0922017-02-27 14:30:02 -08002619 } else if (qualifier == 'z') {
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002620 spec->type = FORMAT_TYPE_SIZE_T;
Rasmus Villemoesd0484192016-01-15 16:58:37 -08002621 } else if (qualifier == 't') {
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002622 spec->type = FORMAT_TYPE_PTRDIFF;
Rasmus Villemoesd0484192016-01-15 16:58:37 -08002623 } else if (qualifier == 'H') {
Rasmus Villemoes51be17d2015-04-15 16:17:02 -07002624 BUILD_BUG_ON(FORMAT_TYPE_UBYTE + SIGN != FORMAT_TYPE_BYTE);
2625 spec->type = FORMAT_TYPE_UBYTE + (spec->flags & SIGN);
Rasmus Villemoesd0484192016-01-15 16:58:37 -08002626 } else if (qualifier == 'h') {
Rasmus Villemoes51be17d2015-04-15 16:17:02 -07002627 BUILD_BUG_ON(FORMAT_TYPE_USHORT + SIGN != FORMAT_TYPE_SHORT);
2628 spec->type = FORMAT_TYPE_USHORT + (spec->flags & SIGN);
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002629 } else {
Rasmus Villemoes51be17d2015-04-15 16:17:02 -07002630 BUILD_BUG_ON(FORMAT_TYPE_UINT + SIGN != FORMAT_TYPE_INT);
2631 spec->type = FORMAT_TYPE_UINT + (spec->flags & SIGN);
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002632 }
2633
2634 return ++fmt - start;
Linus Torvalds78a8bf62008-07-06 16:16:15 -07002635}
2636
Rasmus Villemoes4d72ba02016-01-15 16:58:44 -08002637static void
2638set_field_width(struct printf_spec *spec, int width)
2639{
2640 spec->field_width = width;
2641 if (WARN_ONCE(spec->field_width != width, "field width %d too large", width)) {
2642 spec->field_width = clamp(width, -FIELD_WIDTH_MAX, FIELD_WIDTH_MAX);
2643 }
2644}
2645
2646static void
2647set_precision(struct printf_spec *spec, int prec)
2648{
2649 spec->precision = prec;
2650 if (WARN_ONCE(spec->precision != prec, "precision %d too large", prec)) {
2651 spec->precision = clamp(prec, 0, PRECISION_MAX);
2652 }
2653}
2654
Linus Torvalds1da177e2005-04-16 15:20:36 -07002655/**
2656 * vsnprintf - Format a string and place it in a buffer
2657 * @buf: The buffer to place the result into
2658 * @size: The size of the buffer, including the trailing null space
2659 * @fmt: The format string to use
2660 * @args: Arguments for the format string
2661 *
Rasmus Villemoesd7ec9a02015-11-06 16:30:35 -08002662 * This function generally follows C99 vsnprintf, but has some
2663 * extensions and a few limitations:
2664 *
mchehab@s-opensource.com6cc89132017-03-30 17:11:33 -03002665 * - ``%n`` is unsupported
2666 * - ``%p*`` is handled by pointer()
Andi Kleen20036fd2008-10-15 22:02:02 -07002667 *
Jonathan Corbet27e7c0e2017-12-21 12:39:45 -07002668 * See pointer() or Documentation/core-api/printk-formats.rst for more
Martin Kletzander5e4ee7b2015-11-06 16:30:17 -08002669 * extensive description.
2670 *
mchehab@s-opensource.com6cc89132017-03-30 17:11:33 -03002671 * **Please update the documentation in both places when making changes**
Andrew Morton80f548e2012-07-30 14:40:25 -07002672 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673 * The return value is the number of characters which would
2674 * be generated for the given input, excluding the trailing
2675 * '\0', as per ISO C99. If you want to have the exact
2676 * number of characters written into @buf as return value
Robert P. J. Day72fd4a32007-02-10 01:45:59 -08002677 * (not including the trailing '\0'), use vscnprintf(). If the
Linus Torvalds1da177e2005-04-16 15:20:36 -07002678 * return is greater than or equal to @size, the resulting
2679 * string is truncated.
2680 *
Uwe Kleine-Königba1835e2011-04-06 07:49:04 -07002681 * If you're not already dealing with a va_list consider using snprintf().
Linus Torvalds1da177e2005-04-16 15:20:36 -07002682 */
2683int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
2684{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002685 unsigned long long num;
André Goddard Rosad4be1512009-12-14 18:00:59 -08002686 char *str, *end;
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002687 struct printf_spec spec = {0};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002688
Jeremy Fitzhardingef7969372006-06-25 05:49:17 -07002689 /* Reject out-of-range values early. Large positive sizes are
2690 used for unknown buffer sizes. */
Rasmus Villemoes2aa2f9e2015-02-12 15:01:39 -08002691 if (WARN_ON_ONCE(size > INT_MAX))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002692 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002693
2694 str = buf;
Jeremy Fitzhardingef7969372006-06-25 05:49:17 -07002695 end = buf + size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002696
Jeremy Fitzhardingef7969372006-06-25 05:49:17 -07002697 /* Make sure end is always >= buf */
2698 if (end < buf) {
2699 end = ((void *)-1);
2700 size = end - buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002701 }
2702
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002703 while (*fmt) {
2704 const char *old_fmt = fmt;
André Goddard Rosad4be1512009-12-14 18:00:59 -08002705 int read = format_decode(fmt, &spec);
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002706
2707 fmt += read;
2708
2709 switch (spec.type) {
2710 case FORMAT_TYPE_NONE: {
2711 int copy = read;
2712 if (str < end) {
2713 if (copy > end - str)
2714 copy = end - str;
2715 memcpy(str, old_fmt, copy);
2716 }
2717 str += read;
2718 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002719 }
2720
Vegard Nossumed681a92009-03-14 12:08:50 +01002721 case FORMAT_TYPE_WIDTH:
Rasmus Villemoes4d72ba02016-01-15 16:58:44 -08002722 set_field_width(&spec, va_arg(args, int));
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002723 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002725 case FORMAT_TYPE_PRECISION:
Rasmus Villemoes4d72ba02016-01-15 16:58:44 -08002726 set_precision(&spec, va_arg(args, int));
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002727 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728
André Goddard Rosad4be1512009-12-14 18:00:59 -08002729 case FORMAT_TYPE_CHAR: {
2730 char c;
2731
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002732 if (!(spec.flags & LEFT)) {
2733 while (--spec.field_width > 0) {
Jeremy Fitzhardingef7969372006-06-25 05:49:17 -07002734 if (str < end)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002735 *str = ' ';
2736 ++str;
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002737
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738 }
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002739 }
2740 c = (unsigned char) va_arg(args, int);
2741 if (str < end)
2742 *str = c;
2743 ++str;
2744 while (--spec.field_width > 0) {
Jeremy Fitzhardingef7969372006-06-25 05:49:17 -07002745 if (str < end)
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002746 *str = ' ';
Linus Torvalds1da177e2005-04-16 15:20:36 -07002747 ++str;
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002748 }
2749 break;
André Goddard Rosad4be1512009-12-14 18:00:59 -08002750 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002751
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002752 case FORMAT_TYPE_STR:
2753 str = string(str, end, va_arg(args, char *), spec);
2754 break;
2755
2756 case FORMAT_TYPE_PTR:
Rasmus Villemoesffbfed02015-02-12 15:01:37 -08002757 str = pointer(fmt, str, end, va_arg(args, void *),
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002758 spec);
2759 while (isalnum(*fmt))
2760 fmt++;
2761 break;
2762
2763 case FORMAT_TYPE_PERCENT_CHAR:
2764 if (str < end)
2765 *str = '%';
2766 ++str;
2767 break;
2768
2769 case FORMAT_TYPE_INVALID:
Rasmus Villemoesb006f192015-11-06 16:30:20 -08002770 /*
2771 * Presumably the arguments passed gcc's type
2772 * checking, but there is no safe or sane way
2773 * for us to continue parsing the format and
2774 * fetching from the va_list; the remaining
2775 * specifiers and arguments would be out of
2776 * sync.
2777 */
2778 goto out;
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002779
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002780 default:
2781 switch (spec.type) {
2782 case FORMAT_TYPE_LONG_LONG:
2783 num = va_arg(args, long long);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002784 break;
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002785 case FORMAT_TYPE_ULONG:
2786 num = va_arg(args, unsigned long);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002787 break;
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002788 case FORMAT_TYPE_LONG:
2789 num = va_arg(args, long);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002790 break;
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002791 case FORMAT_TYPE_SIZE_T:
Jason Gunthorpeef124962012-12-17 15:59:58 -08002792 if (spec.flags & SIGN)
2793 num = va_arg(args, ssize_t);
2794 else
2795 num = va_arg(args, size_t);
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002796 break;
2797 case FORMAT_TYPE_PTRDIFF:
2798 num = va_arg(args, ptrdiff_t);
2799 break;
Zhaoleia4e94ef2009-03-27 17:07:05 +08002800 case FORMAT_TYPE_UBYTE:
2801 num = (unsigned char) va_arg(args, int);
2802 break;
2803 case FORMAT_TYPE_BYTE:
2804 num = (signed char) va_arg(args, int);
2805 break;
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002806 case FORMAT_TYPE_USHORT:
2807 num = (unsigned short) va_arg(args, int);
2808 break;
2809 case FORMAT_TYPE_SHORT:
2810 num = (short) va_arg(args, int);
2811 break;
Frederic Weisbecker39e874f2009-03-09 21:15:04 +01002812 case FORMAT_TYPE_INT:
2813 num = (int) va_arg(args, int);
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002814 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002815 default:
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002816 num = va_arg(args, unsigned int);
2817 }
2818
2819 str = number(str, end, num, spec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002821 }
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002822
Rasmus Villemoesb006f192015-11-06 16:30:20 -08002823out:
Jeremy Fitzhardingef7969372006-06-25 05:49:17 -07002824 if (size > 0) {
2825 if (str < end)
2826 *str = '\0';
2827 else
Linus Torvalds0a6047e2006-06-28 17:09:34 -07002828 end[-1] = '\0';
Jeremy Fitzhardingef7969372006-06-25 05:49:17 -07002829 }
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002830
Jeremy Fitzhardingef7969372006-06-25 05:49:17 -07002831 /* the trailing null byte doesn't count towards the total */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002832 return str-buf;
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002833
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002835EXPORT_SYMBOL(vsnprintf);
2836
2837/**
2838 * vscnprintf - Format a string and place it in a buffer
2839 * @buf: The buffer to place the result into
2840 * @size: The size of the buffer, including the trailing null space
2841 * @fmt: The format string to use
2842 * @args: Arguments for the format string
2843 *
2844 * The return value is the number of characters which have been written into
Anton Arapovb921c692011-01-12 16:59:49 -08002845 * the @buf not including the trailing '\0'. If @size is == 0 the function
Linus Torvalds1da177e2005-04-16 15:20:36 -07002846 * returns 0.
2847 *
Uwe Kleine-Königba1835e2011-04-06 07:49:04 -07002848 * If you're not already dealing with a va_list consider using scnprintf().
Andi Kleen20036fd2008-10-15 22:02:02 -07002849 *
2850 * See the vsnprintf() documentation for format string extensions over C99.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002851 */
2852int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
2853{
2854 int i;
2855
André Goddard Rosa7b9186f2009-12-14 18:00:57 -08002856 i = vsnprintf(buf, size, fmt, args);
2857
Anton Arapovb921c692011-01-12 16:59:49 -08002858 if (likely(i < size))
2859 return i;
2860 if (size != 0)
2861 return size - 1;
2862 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002863}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002864EXPORT_SYMBOL(vscnprintf);
2865
2866/**
2867 * snprintf - Format a string and place it in a buffer
2868 * @buf: The buffer to place the result into
2869 * @size: The size of the buffer, including the trailing null space
2870 * @fmt: The format string to use
2871 * @...: Arguments for the format string
2872 *
2873 * The return value is the number of characters which would be
2874 * generated for the given input, excluding the trailing null,
2875 * as per ISO C99. If the return is greater than or equal to
2876 * @size, the resulting string is truncated.
Andi Kleen20036fd2008-10-15 22:02:02 -07002877 *
2878 * See the vsnprintf() documentation for format string extensions over C99.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002879 */
André Goddard Rosa7b9186f2009-12-14 18:00:57 -08002880int snprintf(char *buf, size_t size, const char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002881{
2882 va_list args;
2883 int i;
2884
2885 va_start(args, fmt);
André Goddard Rosa7b9186f2009-12-14 18:00:57 -08002886 i = vsnprintf(buf, size, fmt, args);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002887 va_end(args);
André Goddard Rosa7b9186f2009-12-14 18:00:57 -08002888
Linus Torvalds1da177e2005-04-16 15:20:36 -07002889 return i;
2890}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002891EXPORT_SYMBOL(snprintf);
2892
2893/**
2894 * scnprintf - Format a string and place it in a buffer
2895 * @buf: The buffer to place the result into
2896 * @size: The size of the buffer, including the trailing null space
2897 * @fmt: The format string to use
2898 * @...: Arguments for the format string
2899 *
2900 * The return value is the number of characters written into @buf not including
Changli Gaob903c0b2010-10-26 14:22:50 -07002901 * the trailing '\0'. If @size is == 0 the function returns 0.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002902 */
2903
André Goddard Rosa7b9186f2009-12-14 18:00:57 -08002904int scnprintf(char *buf, size_t size, const char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002905{
2906 va_list args;
2907 int i;
2908
2909 va_start(args, fmt);
Anton Arapovb921c692011-01-12 16:59:49 -08002910 i = vscnprintf(buf, size, fmt, args);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002911 va_end(args);
André Goddard Rosa7b9186f2009-12-14 18:00:57 -08002912
Anton Arapovb921c692011-01-12 16:59:49 -08002913 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002914}
2915EXPORT_SYMBOL(scnprintf);
2916
2917/**
2918 * vsprintf - Format a string and place it in a buffer
2919 * @buf: The buffer to place the result into
2920 * @fmt: The format string to use
2921 * @args: Arguments for the format string
2922 *
2923 * The function returns the number of characters written
Robert P. J. Day72fd4a32007-02-10 01:45:59 -08002924 * into @buf. Use vsnprintf() or vscnprintf() in order to avoid
Linus Torvalds1da177e2005-04-16 15:20:36 -07002925 * buffer overflows.
2926 *
Uwe Kleine-Königba1835e2011-04-06 07:49:04 -07002927 * If you're not already dealing with a va_list consider using sprintf().
Andi Kleen20036fd2008-10-15 22:02:02 -07002928 *
2929 * See the vsnprintf() documentation for format string extensions over C99.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002930 */
2931int vsprintf(char *buf, const char *fmt, va_list args)
2932{
2933 return vsnprintf(buf, INT_MAX, fmt, args);
2934}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002935EXPORT_SYMBOL(vsprintf);
2936
2937/**
2938 * sprintf - Format a string and place it in a buffer
2939 * @buf: The buffer to place the result into
2940 * @fmt: The format string to use
2941 * @...: Arguments for the format string
2942 *
2943 * The function returns the number of characters written
Robert P. J. Day72fd4a32007-02-10 01:45:59 -08002944 * into @buf. Use snprintf() or scnprintf() in order to avoid
Linus Torvalds1da177e2005-04-16 15:20:36 -07002945 * buffer overflows.
Andi Kleen20036fd2008-10-15 22:02:02 -07002946 *
2947 * See the vsnprintf() documentation for format string extensions over C99.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002948 */
André Goddard Rosa7b9186f2009-12-14 18:00:57 -08002949int sprintf(char *buf, const char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002950{
2951 va_list args;
2952 int i;
2953
2954 va_start(args, fmt);
André Goddard Rosa7b9186f2009-12-14 18:00:57 -08002955 i = vsnprintf(buf, INT_MAX, fmt, args);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002956 va_end(args);
André Goddard Rosa7b9186f2009-12-14 18:00:57 -08002957
Linus Torvalds1da177e2005-04-16 15:20:36 -07002958 return i;
2959}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002960EXPORT_SYMBOL(sprintf);
2961
Lai Jiangshan4370aa42009-03-06 17:21:46 +01002962#ifdef CONFIG_BINARY_PRINTF
2963/*
2964 * bprintf service:
2965 * vbin_printf() - VA arguments to binary data
2966 * bstr_printf() - Binary data to text string
2967 */
2968
2969/**
2970 * vbin_printf - Parse a format string and place args' binary value in a buffer
2971 * @bin_buf: The buffer to place args' binary value
2972 * @size: The size of the buffer(by words(32bits), not characters)
2973 * @fmt: The format string to use
2974 * @args: Arguments for the format string
2975 *
2976 * The format follows C99 vsnprintf, except %n is ignored, and its argument
Masanari Iidada3dae52014-09-09 01:27:23 +09002977 * is skipped.
Lai Jiangshan4370aa42009-03-06 17:21:46 +01002978 *
2979 * The return value is the number of words(32bits) which would be generated for
2980 * the given input.
2981 *
2982 * NOTE:
2983 * If the return value is greater than @size, the resulting bin_buf is NOT
2984 * valid for bstr_printf().
2985 */
2986int vbin_printf(u32 *bin_buf, size_t size, const char *fmt, va_list args)
2987{
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01002988 struct printf_spec spec = {0};
Lai Jiangshan4370aa42009-03-06 17:21:46 +01002989 char *str, *end;
Steven Rostedt (VMware)841a9152017-12-28 20:40:25 -05002990 int width;
Lai Jiangshan4370aa42009-03-06 17:21:46 +01002991
2992 str = (char *)bin_buf;
2993 end = (char *)(bin_buf + size);
2994
2995#define save_arg(type) \
Steven Rostedt (VMware)841a9152017-12-28 20:40:25 -05002996({ \
2997 unsigned long long value; \
Lai Jiangshan4370aa42009-03-06 17:21:46 +01002998 if (sizeof(type) == 8) { \
Steven Rostedt (VMware)841a9152017-12-28 20:40:25 -05002999 unsigned long long val8; \
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003000 str = PTR_ALIGN(str, sizeof(u32)); \
Steven Rostedt (VMware)841a9152017-12-28 20:40:25 -05003001 val8 = va_arg(args, unsigned long long); \
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003002 if (str + sizeof(type) <= end) { \
Steven Rostedt (VMware)841a9152017-12-28 20:40:25 -05003003 *(u32 *)str = *(u32 *)&val8; \
3004 *(u32 *)(str + 4) = *((u32 *)&val8 + 1); \
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003005 } \
Steven Rostedt (VMware)841a9152017-12-28 20:40:25 -05003006 value = val8; \
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003007 } else { \
Steven Rostedt (VMware)841a9152017-12-28 20:40:25 -05003008 unsigned int val4; \
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003009 str = PTR_ALIGN(str, sizeof(type)); \
Steven Rostedt (VMware)841a9152017-12-28 20:40:25 -05003010 val4 = va_arg(args, int); \
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003011 if (str + sizeof(type) <= end) \
Steven Rostedt (VMware)841a9152017-12-28 20:40:25 -05003012 *(typeof(type) *)str = (type)(long)val4; \
3013 value = (unsigned long long)val4; \
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003014 } \
3015 str += sizeof(type); \
Steven Rostedt (VMware)841a9152017-12-28 20:40:25 -05003016 value; \
3017})
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003018
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003019 while (*fmt) {
André Goddard Rosad4be1512009-12-14 18:00:59 -08003020 int read = format_decode(fmt, &spec);
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003021
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003022 fmt += read;
3023
3024 switch (spec.type) {
3025 case FORMAT_TYPE_NONE:
André Goddard Rosad4be1512009-12-14 18:00:59 -08003026 case FORMAT_TYPE_PERCENT_CHAR:
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003027 break;
Rasmus Villemoesb006f192015-11-06 16:30:20 -08003028 case FORMAT_TYPE_INVALID:
3029 goto out;
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003030
Vegard Nossumed681a92009-03-14 12:08:50 +01003031 case FORMAT_TYPE_WIDTH:
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003032 case FORMAT_TYPE_PRECISION:
Steven Rostedt (VMware)841a9152017-12-28 20:40:25 -05003033 width = (int)save_arg(int);
3034 /* Pointers may require the width */
3035 if (*fmt == 'p')
3036 set_field_width(&spec, width);
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003037 break;
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003038
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003039 case FORMAT_TYPE_CHAR:
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003040 save_arg(char);
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003041 break;
3042
3043 case FORMAT_TYPE_STR: {
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003044 const char *save_str = va_arg(args, char *);
Petr Mladek3e5903e2019-04-17 13:53:48 +02003045 const char *err_msg;
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003046 size_t len;
André Goddard Rosa6c356632009-12-14 18:00:56 -08003047
Petr Mladek3e5903e2019-04-17 13:53:48 +02003048 err_msg = check_pointer_msg(save_str);
3049 if (err_msg)
3050 save_str = err_msg;
3051
André Goddard Rosa6c356632009-12-14 18:00:56 -08003052 len = strlen(save_str) + 1;
3053 if (str + len < end)
3054 memcpy(str, save_str, len);
3055 str += len;
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003056 break;
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003057 }
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003058
3059 case FORMAT_TYPE_PTR:
Steven Rostedt (VMware)841a9152017-12-28 20:40:25 -05003060 /* Dereferenced pointers must be done now */
3061 switch (*fmt) {
3062 /* Dereference of functions is still OK */
3063 case 'S':
3064 case 's':
Steven Rostedt (VMware)1e6338c2018-04-03 14:38:53 -04003065 case 'x':
3066 case 'K':
Rasmus Villemoes57f56772019-10-15 21:07:05 +02003067 case 'e':
Steven Rostedt (VMware)841a9152017-12-28 20:40:25 -05003068 save_arg(void *);
3069 break;
3070 default:
3071 if (!isalnum(*fmt)) {
3072 save_arg(void *);
3073 break;
3074 }
3075 str = pointer(fmt, str, end, va_arg(args, void *),
3076 spec);
3077 if (str + 1 < end)
3078 *str++ = '\0';
3079 else
3080 end[-1] = '\0'; /* Must be nul terminated */
3081 }
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003082 /* skip all alphanumeric pointer suffixes */
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003083 while (isalnum(*fmt))
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003084 fmt++;
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003085 break;
3086
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003087 default:
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003088 switch (spec.type) {
3089
3090 case FORMAT_TYPE_LONG_LONG:
3091 save_arg(long long);
3092 break;
3093 case FORMAT_TYPE_ULONG:
3094 case FORMAT_TYPE_LONG:
3095 save_arg(unsigned long);
3096 break;
3097 case FORMAT_TYPE_SIZE_T:
3098 save_arg(size_t);
3099 break;
3100 case FORMAT_TYPE_PTRDIFF:
3101 save_arg(ptrdiff_t);
3102 break;
Zhaoleia4e94ef2009-03-27 17:07:05 +08003103 case FORMAT_TYPE_UBYTE:
3104 case FORMAT_TYPE_BYTE:
3105 save_arg(char);
3106 break;
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003107 case FORMAT_TYPE_USHORT:
3108 case FORMAT_TYPE_SHORT:
3109 save_arg(short);
3110 break;
3111 default:
3112 save_arg(int);
3113 }
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003114 }
3115 }
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003116
Rasmus Villemoesb006f192015-11-06 16:30:20 -08003117out:
André Goddard Rosa7b9186f2009-12-14 18:00:57 -08003118 return (u32 *)(PTR_ALIGN(str, sizeof(u32))) - bin_buf;
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003119#undef save_arg
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003120}
3121EXPORT_SYMBOL_GPL(vbin_printf);
3122
3123/**
3124 * bstr_printf - Format a string from binary arguments and place it in a buffer
3125 * @buf: The buffer to place the result into
3126 * @size: The size of the buffer, including the trailing null space
3127 * @fmt: The format string to use
3128 * @bin_buf: Binary arguments for the format string
3129 *
3130 * This function like C99 vsnprintf, but the difference is that vsnprintf gets
3131 * arguments from stack, and bstr_printf gets arguments from @bin_buf which is
3132 * a binary buffer that generated by vbin_printf.
3133 *
3134 * The format follows C99 vsnprintf, but has some extensions:
Steven Rostedt0efb4d22009-09-17 09:27:29 -04003135 * see vsnprintf comment for details.
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003136 *
3137 * The return value is the number of characters which would
3138 * be generated for the given input, excluding the trailing
3139 * '\0', as per ISO C99. If you want to have the exact
3140 * number of characters written into @buf as return value
3141 * (not including the trailing '\0'), use vscnprintf(). If the
3142 * return is greater than or equal to @size, the resulting
3143 * string is truncated.
3144 */
3145int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf)
3146{
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003147 struct printf_spec spec = {0};
André Goddard Rosad4be1512009-12-14 18:00:59 -08003148 char *str, *end;
3149 const char *args = (const char *)bin_buf;
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003150
Rasmus Villemoes762abb52015-11-06 16:30:23 -08003151 if (WARN_ON_ONCE(size > INT_MAX))
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003152 return 0;
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003153
3154 str = buf;
3155 end = buf + size;
3156
3157#define get_arg(type) \
3158({ \
3159 typeof(type) value; \
3160 if (sizeof(type) == 8) { \
3161 args = PTR_ALIGN(args, sizeof(u32)); \
3162 *(u32 *)&value = *(u32 *)args; \
3163 *((u32 *)&value + 1) = *(u32 *)(args + 4); \
3164 } else { \
3165 args = PTR_ALIGN(args, sizeof(type)); \
3166 value = *(typeof(type) *)args; \
3167 } \
3168 args += sizeof(type); \
3169 value; \
3170})
3171
3172 /* Make sure end is always >= buf */
3173 if (end < buf) {
3174 end = ((void *)-1);
3175 size = end - buf;
3176 }
3177
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003178 while (*fmt) {
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003179 const char *old_fmt = fmt;
André Goddard Rosad4be1512009-12-14 18:00:59 -08003180 int read = format_decode(fmt, &spec);
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003181
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003182 fmt += read;
3183
3184 switch (spec.type) {
3185 case FORMAT_TYPE_NONE: {
3186 int copy = read;
3187 if (str < end) {
3188 if (copy > end - str)
3189 copy = end - str;
3190 memcpy(str, old_fmt, copy);
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003191 }
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003192 str += read;
3193 break;
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003194 }
3195
Vegard Nossumed681a92009-03-14 12:08:50 +01003196 case FORMAT_TYPE_WIDTH:
Rasmus Villemoes4d72ba02016-01-15 16:58:44 -08003197 set_field_width(&spec, get_arg(int));
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003198 break;
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003199
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003200 case FORMAT_TYPE_PRECISION:
Rasmus Villemoes4d72ba02016-01-15 16:58:44 -08003201 set_precision(&spec, get_arg(int));
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003202 break;
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003203
André Goddard Rosad4be1512009-12-14 18:00:59 -08003204 case FORMAT_TYPE_CHAR: {
3205 char c;
3206
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003207 if (!(spec.flags & LEFT)) {
3208 while (--spec.field_width > 0) {
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003209 if (str < end)
3210 *str = ' ';
3211 ++str;
3212 }
3213 }
3214 c = (unsigned char) get_arg(char);
3215 if (str < end)
3216 *str = c;
3217 ++str;
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003218 while (--spec.field_width > 0) {
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003219 if (str < end)
3220 *str = ' ';
3221 ++str;
3222 }
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003223 break;
André Goddard Rosad4be1512009-12-14 18:00:59 -08003224 }
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003225
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003226 case FORMAT_TYPE_STR: {
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003227 const char *str_arg = args;
André Goddard Rosad4be1512009-12-14 18:00:59 -08003228 args += strlen(str_arg) + 1;
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003229 str = string(str, end, (char *)str_arg, spec);
3230 break;
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003231 }
3232
Steven Rostedt (VMware)841a9152017-12-28 20:40:25 -05003233 case FORMAT_TYPE_PTR: {
3234 bool process = false;
3235 int copy, len;
3236 /* Non function dereferences were already done */
3237 switch (*fmt) {
3238 case 'S':
3239 case 's':
Steven Rostedt (VMware)1e6338c2018-04-03 14:38:53 -04003240 case 'x':
3241 case 'K':
Rasmus Villemoes57f56772019-10-15 21:07:05 +02003242 case 'e':
Steven Rostedt (VMware)841a9152017-12-28 20:40:25 -05003243 process = true;
3244 break;
3245 default:
3246 if (!isalnum(*fmt)) {
3247 process = true;
3248 break;
3249 }
3250 /* Pointer dereference was already processed */
3251 if (str < end) {
3252 len = copy = strlen(args);
3253 if (copy > end - str)
3254 copy = end - str;
3255 memcpy(str, args, copy);
3256 str += len;
Steven Rostedt (VMware)62165602018-10-05 10:08:03 -04003257 args += len + 1;
Steven Rostedt (VMware)841a9152017-12-28 20:40:25 -05003258 }
3259 }
3260 if (process)
3261 str = pointer(fmt, str, end, get_arg(void *), spec);
3262
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003263 while (isalnum(*fmt))
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003264 fmt++;
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003265 break;
Steven Rostedt (VMware)841a9152017-12-28 20:40:25 -05003266 }
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003267
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003268 case FORMAT_TYPE_PERCENT_CHAR:
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003269 if (str < end)
3270 *str = '%';
3271 ++str;
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003272 break;
3273
Rasmus Villemoesb006f192015-11-06 16:30:20 -08003274 case FORMAT_TYPE_INVALID:
3275 goto out;
3276
André Goddard Rosad4be1512009-12-14 18:00:59 -08003277 default: {
3278 unsigned long long num;
3279
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003280 switch (spec.type) {
3281
3282 case FORMAT_TYPE_LONG_LONG:
3283 num = get_arg(long long);
3284 break;
3285 case FORMAT_TYPE_ULONG:
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003286 case FORMAT_TYPE_LONG:
3287 num = get_arg(unsigned long);
3288 break;
3289 case FORMAT_TYPE_SIZE_T:
3290 num = get_arg(size_t);
3291 break;
3292 case FORMAT_TYPE_PTRDIFF:
3293 num = get_arg(ptrdiff_t);
3294 break;
Zhaoleia4e94ef2009-03-27 17:07:05 +08003295 case FORMAT_TYPE_UBYTE:
3296 num = get_arg(unsigned char);
3297 break;
3298 case FORMAT_TYPE_BYTE:
3299 num = get_arg(signed char);
3300 break;
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003301 case FORMAT_TYPE_USHORT:
3302 num = get_arg(unsigned short);
3303 break;
3304 case FORMAT_TYPE_SHORT:
3305 num = get_arg(short);
3306 break;
3307 case FORMAT_TYPE_UINT:
3308 num = get_arg(unsigned int);
3309 break;
3310 default:
3311 num = get_arg(int);
3312 }
3313
3314 str = number(str, end, num, spec);
André Goddard Rosad4be1512009-12-14 18:00:59 -08003315 } /* default: */
3316 } /* switch(spec.type) */
3317 } /* while(*fmt) */
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003318
Rasmus Villemoesb006f192015-11-06 16:30:20 -08003319out:
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003320 if (size > 0) {
3321 if (str < end)
3322 *str = '\0';
3323 else
3324 end[-1] = '\0';
3325 }
Frederic Weisbeckerfef20d92009-03-06 17:21:50 +01003326
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003327#undef get_arg
3328
3329 /* the trailing null byte doesn't count towards the total */
3330 return str - buf;
3331}
3332EXPORT_SYMBOL_GPL(bstr_printf);
3333
3334/**
3335 * bprintf - Parse a format string and place args' binary value in a buffer
3336 * @bin_buf: The buffer to place args' binary value
3337 * @size: The size of the buffer(by words(32bits), not characters)
3338 * @fmt: The format string to use
3339 * @...: Arguments for the format string
3340 *
3341 * The function returns the number of words(u32) written
3342 * into @bin_buf.
3343 */
3344int bprintf(u32 *bin_buf, size_t size, const char *fmt, ...)
3345{
3346 va_list args;
3347 int ret;
3348
3349 va_start(args, fmt);
3350 ret = vbin_printf(bin_buf, size, fmt, args);
3351 va_end(args);
André Goddard Rosa7b9186f2009-12-14 18:00:57 -08003352
Lai Jiangshan4370aa42009-03-06 17:21:46 +01003353 return ret;
3354}
3355EXPORT_SYMBOL_GPL(bprintf);
3356
3357#endif /* CONFIG_BINARY_PRINTF */
3358
Linus Torvalds1da177e2005-04-16 15:20:36 -07003359/**
3360 * vsscanf - Unformat a buffer into a list of arguments
3361 * @buf: input buffer
3362 * @fmt: format of buffer
3363 * @args: arguments
3364 */
André Goddard Rosa7b9186f2009-12-14 18:00:57 -08003365int vsscanf(const char *buf, const char *fmt, va_list args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003366{
3367 const char *str = buf;
3368 char *next;
3369 char digit;
3370 int num = 0;
Joe Perchesef0658f2010-03-06 17:10:14 -08003371 u8 qualifier;
Jan Beulich53809752012-12-17 16:01:31 -08003372 unsigned int base;
3373 union {
3374 long long s;
3375 unsigned long long u;
3376 } val;
Joe Perchesef0658f2010-03-06 17:10:14 -08003377 s16 field_width;
André Goddard Rosad4be1512009-12-14 18:00:59 -08003378 bool is_sign;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003379
Jan Beulichda990752012-10-04 17:13:24 -07003380 while (*fmt) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003381 /* skip any white space in format */
3382 /* white space in format matchs any amount of
3383 * white space, including none, in the input.
3384 */
3385 if (isspace(*fmt)) {
André Goddard Rosae7d28602009-12-14 18:01:06 -08003386 fmt = skip_spaces(++fmt);
3387 str = skip_spaces(str);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003388 }
3389
3390 /* anything that is not a conversion must match exactly */
3391 if (*fmt != '%' && *fmt) {
3392 if (*fmt++ != *str++)
3393 break;
3394 continue;
3395 }
3396
3397 if (!*fmt)
3398 break;
3399 ++fmt;
André Goddard Rosa7b9186f2009-12-14 18:00:57 -08003400
Linus Torvalds1da177e2005-04-16 15:20:36 -07003401 /* skip this conversion.
3402 * advance both strings to next white space
3403 */
3404 if (*fmt == '*') {
Jan Beulichda990752012-10-04 17:13:24 -07003405 if (!*str)
3406 break;
Jessica Yuf9310b22016-03-17 14:23:07 -07003407 while (!isspace(*fmt) && *fmt != '%' && *fmt) {
3408 /* '%*[' not yet supported, invalid format */
3409 if (*fmt == '[')
3410 return num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003411 fmt++;
Jessica Yuf9310b22016-03-17 14:23:07 -07003412 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003413 while (!isspace(*str) && *str)
3414 str++;
3415 continue;
3416 }
3417
3418 /* get field width */
3419 field_width = -1;
Jan Beulich53809752012-12-17 16:01:31 -08003420 if (isdigit(*fmt)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003421 field_width = skip_atoi(&fmt);
Jan Beulich53809752012-12-17 16:01:31 -08003422 if (field_width <= 0)
3423 break;
3424 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003425
3426 /* get conversion qualifier */
3427 qualifier = -1;
Andy Shevchenko75fb8f22011-07-25 17:13:20 -07003428 if (*fmt == 'h' || _tolower(*fmt) == 'l' ||
Alexey Dobriyan5b5e0922017-02-27 14:30:02 -08003429 *fmt == 'z') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003430 qualifier = *fmt++;
3431 if (unlikely(qualifier == *fmt)) {
3432 if (qualifier == 'h') {
3433 qualifier = 'H';
3434 fmt++;
3435 } else if (qualifier == 'l') {
3436 qualifier = 'L';
3437 fmt++;
3438 }
3439 }
3440 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003441
Jan Beulichda990752012-10-04 17:13:24 -07003442 if (!*fmt)
3443 break;
3444
3445 if (*fmt == 'n') {
3446 /* return number of characters read so far */
3447 *va_arg(args, int *) = str - buf;
3448 ++fmt;
3449 continue;
3450 }
3451
3452 if (!*str)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003453 break;
3454
André Goddard Rosad4be1512009-12-14 18:00:59 -08003455 base = 10;
Fabian Frederick3f623eb2014-06-04 16:11:52 -07003456 is_sign = false;
André Goddard Rosad4be1512009-12-14 18:00:59 -08003457
André Goddard Rosa7b9186f2009-12-14 18:00:57 -08003458 switch (*fmt++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003459 case 'c':
3460 {
André Goddard Rosa7b9186f2009-12-14 18:00:57 -08003461 char *s = (char *)va_arg(args, char*);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003462 if (field_width == -1)
3463 field_width = 1;
3464 do {
3465 *s++ = *str++;
3466 } while (--field_width > 0 && *str);
3467 num++;
3468 }
3469 continue;
3470 case 's':
3471 {
André Goddard Rosa7b9186f2009-12-14 18:00:57 -08003472 char *s = (char *)va_arg(args, char *);
3473 if (field_width == -1)
Alexey Dobriyan4be929b2010-05-24 14:33:03 -07003474 field_width = SHRT_MAX;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003475 /* first, skip leading white space in buffer */
André Goddard Rosae7d28602009-12-14 18:01:06 -08003476 str = skip_spaces(str);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003477
3478 /* now copy until next white space */
André Goddard Rosa7b9186f2009-12-14 18:00:57 -08003479 while (*str && !isspace(*str) && field_width--)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003480 *s++ = *str++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003481 *s = '\0';
3482 num++;
3483 }
3484 continue;
Jessica Yuf9310b22016-03-17 14:23:07 -07003485 /*
3486 * Warning: This implementation of the '[' conversion specifier
3487 * deviates from its glibc counterpart in the following ways:
3488 * (1) It does NOT support ranges i.e. '-' is NOT a special
3489 * character
3490 * (2) It cannot match the closing bracket ']' itself
3491 * (3) A field width is required
3492 * (4) '%*[' (discard matching input) is currently not supported
3493 *
3494 * Example usage:
3495 * ret = sscanf("00:0a:95","%2[^:]:%2[^:]:%2[^:]",
3496 * buf1, buf2, buf3);
3497 * if (ret < 3)
3498 * // etc..
3499 */
3500 case '[':
3501 {
3502 char *s = (char *)va_arg(args, char *);
3503 DECLARE_BITMAP(set, 256) = {0};
3504 unsigned int len = 0;
3505 bool negate = (*fmt == '^');
3506
3507 /* field width is required */
3508 if (field_width == -1)
3509 return num;
3510
3511 if (negate)
3512 ++fmt;
3513
3514 for ( ; *fmt && *fmt != ']'; ++fmt, ++len)
3515 set_bit((u8)*fmt, set);
3516
3517 /* no ']' or no character set found */
3518 if (!*fmt || !len)
3519 return num;
3520 ++fmt;
3521
3522 if (negate) {
3523 bitmap_complement(set, set, 256);
3524 /* exclude null '\0' byte */
3525 clear_bit(0, set);
3526 }
3527
3528 /* match must be non-empty */
3529 if (!test_bit((u8)*str, set))
3530 return num;
3531
3532 while (test_bit((u8)*str, set) && field_width--)
3533 *s++ = *str++;
3534 *s = '\0';
3535 ++num;
3536 }
3537 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003538 case 'o':
3539 base = 8;
3540 break;
3541 case 'x':
3542 case 'X':
3543 base = 16;
3544 break;
3545 case 'i':
André Goddard Rosa7b9186f2009-12-14 18:00:57 -08003546 base = 0;
Nick Desaulniers4c1ca832020-11-15 20:35:31 -08003547 fallthrough;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003548 case 'd':
Fabian Frederick3f623eb2014-06-04 16:11:52 -07003549 is_sign = true;
Nick Desaulniers4c1ca832020-11-15 20:35:31 -08003550 fallthrough;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003551 case 'u':
3552 break;
3553 case '%':
3554 /* looking for '%' in str */
André Goddard Rosa7b9186f2009-12-14 18:00:57 -08003555 if (*str++ != '%')
Linus Torvalds1da177e2005-04-16 15:20:36 -07003556 return num;
3557 continue;
3558 default:
3559 /* invalid format; stop here */
3560 return num;
3561 }
3562
3563 /* have some sort of integer conversion.
3564 * first, skip white space in buffer.
3565 */
André Goddard Rosae7d28602009-12-14 18:01:06 -08003566 str = skip_spaces(str);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003567
3568 digit = *str;
3569 if (is_sign && digit == '-')
3570 digit = *(str + 1);
3571
3572 if (!digit
André Goddard Rosa7b9186f2009-12-14 18:00:57 -08003573 || (base == 16 && !isxdigit(digit))
3574 || (base == 10 && !isdigit(digit))
3575 || (base == 8 && (!isdigit(digit) || digit > '7'))
3576 || (base == 0 && !isdigit(digit)))
3577 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003578
Jan Beulich53809752012-12-17 16:01:31 -08003579 if (is_sign)
3580 val.s = qualifier != 'L' ?
3581 simple_strtol(str, &next, base) :
3582 simple_strtoll(str, &next, base);
3583 else
3584 val.u = qualifier != 'L' ?
3585 simple_strtoul(str, &next, base) :
3586 simple_strtoull(str, &next, base);
3587
3588 if (field_width > 0 && next - str > field_width) {
3589 if (base == 0)
3590 _parse_integer_fixup_radix(str, &base);
3591 while (next - str > field_width) {
3592 if (is_sign)
3593 val.s = div_s64(val.s, base);
3594 else
3595 val.u = div_u64(val.u, base);
3596 --next;
3597 }
3598 }
3599
André Goddard Rosa7b9186f2009-12-14 18:00:57 -08003600 switch (qualifier) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003601 case 'H': /* that's 'hh' in format */
Jan Beulich53809752012-12-17 16:01:31 -08003602 if (is_sign)
3603 *va_arg(args, signed char *) = val.s;
3604 else
3605 *va_arg(args, unsigned char *) = val.u;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003606 break;
3607 case 'h':
Jan Beulich53809752012-12-17 16:01:31 -08003608 if (is_sign)
3609 *va_arg(args, short *) = val.s;
3610 else
3611 *va_arg(args, unsigned short *) = val.u;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003612 break;
3613 case 'l':
Jan Beulich53809752012-12-17 16:01:31 -08003614 if (is_sign)
3615 *va_arg(args, long *) = val.s;
3616 else
3617 *va_arg(args, unsigned long *) = val.u;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003618 break;
3619 case 'L':
Jan Beulich53809752012-12-17 16:01:31 -08003620 if (is_sign)
3621 *va_arg(args, long long *) = val.s;
3622 else
3623 *va_arg(args, unsigned long long *) = val.u;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003624 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003625 case 'z':
Jan Beulich53809752012-12-17 16:01:31 -08003626 *va_arg(args, size_t *) = val.u;
3627 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003628 default:
Jan Beulich53809752012-12-17 16:01:31 -08003629 if (is_sign)
3630 *va_arg(args, int *) = val.s;
3631 else
3632 *va_arg(args, unsigned int *) = val.u;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003633 break;
3634 }
3635 num++;
3636
3637 if (!next)
3638 break;
3639 str = next;
3640 }
Johannes Bergc6b40d12007-05-08 00:27:20 -07003641
Linus Torvalds1da177e2005-04-16 15:20:36 -07003642 return num;
3643}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003644EXPORT_SYMBOL(vsscanf);
3645
3646/**
3647 * sscanf - Unformat a buffer into a list of arguments
3648 * @buf: input buffer
3649 * @fmt: formatting of buffer
3650 * @...: resulting arguments
3651 */
André Goddard Rosa7b9186f2009-12-14 18:00:57 -08003652int sscanf(const char *buf, const char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003653{
3654 va_list args;
3655 int i;
3656
André Goddard Rosa7b9186f2009-12-14 18:00:57 -08003657 va_start(args, fmt);
3658 i = vsscanf(buf, fmt, args);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003659 va_end(args);
André Goddard Rosa7b9186f2009-12-14 18:00:57 -08003660
Linus Torvalds1da177e2005-04-16 15:20:36 -07003661 return i;
3662}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003663EXPORT_SYMBOL(sscanf);