1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include <stdarg.h>
20#include <linux/module.h>
21#include <linux/types.h>
22#include <linux/string.h>
23#include <linux/ctype.h>
24#include <linux/kernel.h>
25#include <linux/kallsyms.h>
26#include <linux/uaccess.h>
27#include <linux/ioport.h>
28#include <net/addrconf.h>
29
30#include <asm/page.h>
31#include <asm/div64.h>
32#include <asm/sections.h>
33
34#include "kstrtox.h"
35
36
37
38
39
40
41
42unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base)
43{
44 unsigned long long result;
45 unsigned int rv;
46
47 cp = _parse_integer_fixup_radix(cp, &base);
48 rv = _parse_integer(cp, base, &result);
49
50 cp += (rv & ~KSTRTOX_OVERFLOW);
51
52 if (endp)
53 *endp = (char *)cp;
54
55 return result;
56}
57EXPORT_SYMBOL(simple_strtoull);
58
59
60
61
62
63
64
65unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base)
66{
67 return simple_strtoull(cp, endp, base);
68}
69EXPORT_SYMBOL(simple_strtoul);
70
71
72
73
74
75
76
77long simple_strtol(const char *cp, char **endp, unsigned int base)
78{
79 if (*cp == '-')
80 return -simple_strtoul(cp + 1, endp, base);
81
82 return simple_strtoul(cp, endp, base);
83}
84EXPORT_SYMBOL(simple_strtol);
85
86
87
88
89
90
91
92long long simple_strtoll(const char *cp, char **endp, unsigned int base)
93{
94 if (*cp == '-')
95 return -simple_strtoull(cp + 1, endp, base);
96
97 return simple_strtoull(cp, endp, base);
98}
99EXPORT_SYMBOL(simple_strtoll);
100
101static noinline_for_stack
102int skip_atoi(const char **s)
103{
104 int i = 0;
105
106 while (isdigit(**s))
107 i = i*10 + *((*s)++) - '0';
108
109 return i;
110}
111
112
113
114
115
116
117
118
119#if BITS_PER_LONG != 32 || BITS_PER_LONG_LONG != 64
120
121static noinline_for_stack
122char *put_dec_full9(char *buf, unsigned q)
123{
124 unsigned r;
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145 r = (q * (uint64_t)0x1999999a) >> 32;
146 *buf++ = (q - 10 * r) + '0';
147 q = (r * (uint64_t)0x1999999a) >> 32;
148 *buf++ = (r - 10 * q) + '0';
149 r = (q * (uint64_t)0x1999999a) >> 32;
150 *buf++ = (q - 10 * r) + '0';
151 q = (r * (uint64_t)0x1999999a) >> 32;
152 *buf++ = (r - 10 * q) + '0';
153 r = (q * (uint64_t)0x1999999a) >> 32;
154 *buf++ = (q - 10 * r) + '0';
155
156 q = (r * 0x199a) >> 16;
157 *buf++ = (r - 10 * q) + '0';
158 r = (q * 0xcd) >> 11;
159 *buf++ = (q - 10 * r) + '0';
160 q = (r * 0xcd) >> 11;
161 *buf++ = (r - 10 * q) + '0';
162 *buf++ = q + '0';
163 return buf;
164}
165#endif
166
167
168
169
170
171static noinline_for_stack
172char *put_dec_trunc8(char *buf, unsigned r)
173{
174 unsigned q;
175
176
177 while (r >= 10000) {
178 q = r + '0';
179 r = (r * (uint64_t)0x1999999a) >> 32;
180 *buf++ = q - 10*r;
181 }
182
183 q = (r * 0x199a) >> 16;
184 *buf++ = (r - 10 * q) + '0';
185 if (q == 0)
186 return buf;
187 r = (q * 0xcd) >> 11;
188 *buf++ = (q - 10 * r) + '0';
189 if (r == 0)
190 return buf;
191 q = (r * 0xcd) >> 11;
192 *buf++ = (r - 10 * q) + '0';
193 if (q == 0)
194 return buf;
195 *buf++ = q + '0';
196 return buf;
197}
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216#if BITS_PER_LONG != 32 || BITS_PER_LONG_LONG != 64
217
218
219
220static
221char *put_dec(char *buf, unsigned long long n)
222{
223 if (n >= 100*1000*1000) {
224 while (n >= 1000*1000*1000)
225 buf = put_dec_full9(buf, do_div(n, 1000*1000*1000));
226 if (n >= 100*1000*1000)
227 return put_dec_full9(buf, n);
228 }
229 return put_dec_trunc8(buf, n);
230}
231
232#else
233
234
235
236
237static noinline_for_stack
238void put_dec_full4(char *buf, unsigned q)
239{
240 unsigned r;
241 r = (q * 0xccd) >> 15;
242 buf[0] = (q - 10 * r) + '0';
243 q = (r * 0xcd) >> 11;
244 buf[1] = (r - 10 * q) + '0';
245 r = (q * 0xcd) >> 11;
246 buf[2] = (q - 10 * r) + '0';
247 buf[3] = r + '0';
248}
249
250
251
252
253
254
255
256
257static
258unsigned put_dec_helper4(char *buf, unsigned x)
259{
260 uint32_t q = (x * (uint64_t)0x346DC5D7) >> 43;
261
262 put_dec_full4(buf, x - q * 10000);
263 return q;
264}
265
266
267
268
269
270
271static
272char *put_dec(char *buf, unsigned long long n)
273{
274 uint32_t d3, d2, d1, q, h;
275
276 if (n < 100*1000*1000)
277 return put_dec_trunc8(buf, n);
278
279 d1 = ((uint32_t)n >> 16);
280 h = (n >> 32);
281 d2 = (h ) & 0xffff;
282 d3 = (h >> 16);
283
284 q = 656 * d3 + 7296 * d2 + 5536 * d1 + ((uint32_t)n & 0xffff);
285 q = put_dec_helper4(buf, q);
286
287 q += 7671 * d3 + 9496 * d2 + 6 * d1;
288 q = put_dec_helper4(buf+4, q);
289
290 q += 4749 * d3 + 42 * d2;
291 q = put_dec_helper4(buf+8, q);
292
293 q += 281 * d3;
294 buf += 12;
295 if (q)
296 buf = put_dec_trunc8(buf, q);
297 else while (buf[-1] == '0')
298 --buf;
299
300 return buf;
301}
302
303#endif
304
305
306
307
308
309
310
311int num_to_str(char *buf, int size, unsigned long long num)
312{
313 char tmp[sizeof(num) * 3];
314 int idx, len;
315
316
317 if (num <= 9) {
318 tmp[0] = '0' + num;
319 len = 1;
320 } else {
321 len = put_dec(tmp, num) - tmp;
322 }
323
324 if (len > size)
325 return 0;
326 for (idx = 0; idx < len; ++idx)
327 buf[idx] = tmp[len - idx - 1];
328 return len;
329}
330
331#define ZEROPAD 1
332#define SIGN 2
333#define PLUS 4
334#define SPACE 8
335#define LEFT 16
336#define SMALL 32
337#define SPECIAL 64
338
339enum format_type {
340 FORMAT_TYPE_NONE,
341 FORMAT_TYPE_WIDTH,
342 FORMAT_TYPE_PRECISION,
343 FORMAT_TYPE_CHAR,
344 FORMAT_TYPE_STR,
345 FORMAT_TYPE_PTR,
346 FORMAT_TYPE_PERCENT_CHAR,
347 FORMAT_TYPE_INVALID,
348 FORMAT_TYPE_LONG_LONG,
349 FORMAT_TYPE_ULONG,
350 FORMAT_TYPE_LONG,
351 FORMAT_TYPE_UBYTE,
352 FORMAT_TYPE_BYTE,
353 FORMAT_TYPE_USHORT,
354 FORMAT_TYPE_SHORT,
355 FORMAT_TYPE_UINT,
356 FORMAT_TYPE_INT,
357 FORMAT_TYPE_NRCHARS,
358 FORMAT_TYPE_SIZE_T,
359 FORMAT_TYPE_PTRDIFF
360};
361
362struct printf_spec {
363 u8 type;
364 u8 flags;
365 u8 base;
366 u8 qualifier;
367 s16 field_width;
368 s16 precision;
369};
370
371static noinline_for_stack
372char *number(char *buf, char *end, unsigned long long num,
373 struct printf_spec spec)
374{
375
376 static const char digits[16] = "0123456789ABCDEF";
377
378 char tmp[66];
379 char sign;
380 char locase;
381 int need_pfx = ((spec.flags & SPECIAL) && spec.base != 10);
382 int i;
383 bool is_zero = num == 0LL;
384
385
386
387 locase = (spec.flags & SMALL);
388 if (spec.flags & LEFT)
389 spec.flags &= ~ZEROPAD;
390 sign = 0;
391 if (spec.flags & SIGN) {
392 if ((signed long long)num < 0) {
393 sign = '-';
394 num = -(signed long long)num;
395 spec.field_width--;
396 } else if (spec.flags & PLUS) {
397 sign = '+';
398 spec.field_width--;
399 } else if (spec.flags & SPACE) {
400 sign = ' ';
401 spec.field_width--;
402 }
403 }
404 if (need_pfx) {
405 if (spec.base == 16)
406 spec.field_width -= 2;
407 else if (!is_zero)
408 spec.field_width--;
409 }
410
411
412 i = 0;
413 if (num < spec.base)
414 tmp[i++] = digits[num] | locase;
415
416
417
418
419
420 else if (spec.base != 10) {
421 int mask = spec.base - 1;
422 int shift = 3;
423
424 if (spec.base == 16)
425 shift = 4;
426 do {
427 tmp[i++] = (digits[((unsigned char)num) & mask] | locase);
428 num >>= shift;
429 } while (num);
430 } else {
431 i = put_dec(tmp, num) - tmp;
432 }
433
434
435 if (i > spec.precision)
436 spec.precision = i;
437
438 spec.field_width -= spec.precision;
439 if (!(spec.flags & (ZEROPAD+LEFT))) {
440 while (--spec.field_width >= 0) {
441 if (buf < end)
442 *buf = ' ';
443 ++buf;
444 }
445 }
446
447 if (sign) {
448 if (buf < end)
449 *buf = sign;
450 ++buf;
451 }
452
453 if (need_pfx) {
454 if (spec.base == 16 || !is_zero) {
455 if (buf < end)
456 *buf = '0';
457 ++buf;
458 }
459 if (spec.base == 16) {
460 if (buf < end)
461 *buf = ('X' | locase);
462 ++buf;
463 }
464 }
465
466 if (!(spec.flags & LEFT)) {
467 char c = (spec.flags & ZEROPAD) ? '0' : ' ';
468 while (--spec.field_width >= 0) {
469 if (buf < end)
470 *buf = c;
471 ++buf;
472 }
473 }
474
475 while (i <= --spec.precision) {
476 if (buf < end)
477 *buf = '0';
478 ++buf;
479 }
480
481 while (--i >= 0) {
482 if (buf < end)
483 *buf = tmp[i];
484 ++buf;
485 }
486
487 while (--spec.field_width >= 0) {
488 if (buf < end)
489 *buf = ' ';
490 ++buf;
491 }
492
493 return buf;
494}
495
496static noinline_for_stack
497char *string(char *buf, char *end, const char *s, struct printf_spec spec)
498{
499 int len, i;
500
501 if ((unsigned long)s < PAGE_SIZE)
502 s = "(null)";
503
504 len = strnlen(s, spec.precision);
505
506 if (!(spec.flags & LEFT)) {
507 while (len < spec.field_width--) {
508 if (buf < end)
509 *buf = ' ';
510 ++buf;
511 }
512 }
513 for (i = 0; i < len; ++i) {
514 if (buf < end)
515 *buf = *s;
516 ++buf; ++s;
517 }
518 while (len < spec.field_width--) {
519 if (buf < end)
520 *buf = ' ';
521 ++buf;
522 }
523
524 return buf;
525}
526
527static noinline_for_stack
528char *symbol_string(char *buf, char *end, void *ptr,
529 struct printf_spec spec, char ext)
530{
531 unsigned long value = (unsigned long) ptr;
532#ifdef CONFIG_KALLSYMS
533 char sym[KSYM_SYMBOL_LEN];
534 if (ext == 'B')
535 sprint_backtrace(sym, value);
536 else if (ext != 'f' && ext != 's')
537 sprint_symbol(sym, value);
538 else
539 sprint_symbol_no_offset(sym, value);
540
541 return string(buf, end, sym, spec);
542#else
543 spec.field_width = 2 * sizeof(void *);
544 spec.flags |= SPECIAL | SMALL | ZEROPAD;
545 spec.base = 16;
546
547 return number(buf, end, value, spec);
548#endif
549}
550
551static noinline_for_stack
552char *resource_string(char *buf, char *end, struct resource *res,
553 struct printf_spec spec, const char *fmt)
554{
555#ifndef IO_RSRC_PRINTK_SIZE
556#define IO_RSRC_PRINTK_SIZE 6
557#endif
558
559#ifndef MEM_RSRC_PRINTK_SIZE
560#define MEM_RSRC_PRINTK_SIZE 10
561#endif
562 static const struct printf_spec io_spec = {
563 .base = 16,
564 .field_width = IO_RSRC_PRINTK_SIZE,
565 .precision = -1,
566 .flags = SPECIAL | SMALL | ZEROPAD,
567 };
568 static const struct printf_spec mem_spec = {
569 .base = 16,
570 .field_width = MEM_RSRC_PRINTK_SIZE,
571 .precision = -1,
572 .flags = SPECIAL | SMALL | ZEROPAD,
573 };
574 static const struct printf_spec bus_spec = {
575 .base = 16,
576 .field_width = 2,
577 .precision = -1,
578 .flags = SMALL | ZEROPAD,
579 };
580 static const struct printf_spec dec_spec = {
581 .base = 10,
582 .precision = -1,
583 .flags = 0,
584 };
585 static const struct printf_spec str_spec = {
586 .field_width = -1,
587 .precision = 10,
588 .flags = LEFT,
589 };
590 static const struct printf_spec flag_spec = {
591 .base = 16,
592 .precision = -1,
593 .flags = SPECIAL | SMALL,
594 };
595
596
597
598#define RSRC_BUF_SIZE ((2 * sizeof(resource_size_t)) + 4)
599#define FLAG_BUF_SIZE (2 * sizeof(res->flags))
600#define DECODED_BUF_SIZE sizeof("[mem - 64bit pref window disabled]")
601#define RAW_BUF_SIZE sizeof("[mem - flags 0x]")
602 char sym[max(2*RSRC_BUF_SIZE + DECODED_BUF_SIZE,
603 2*RSRC_BUF_SIZE + FLAG_BUF_SIZE + RAW_BUF_SIZE)];
604
605 char *p = sym, *pend = sym + sizeof(sym);
606 int decode = (fmt[0] == 'R') ? 1 : 0;
607 const struct printf_spec *specp;
608
609 *p++ = '[';
610 if (res->flags & IORESOURCE_IO) {
611 p = string(p, pend, "io ", str_spec);
612 specp = &io_spec;
613 } else if (res->flags & IORESOURCE_MEM) {
614 p = string(p, pend, "mem ", str_spec);
615 specp = &mem_spec;
616 } else if (res->flags & IORESOURCE_IRQ) {
617 p = string(p, pend, "irq ", str_spec);
618 specp = &dec_spec;
619 } else if (res->flags & IORESOURCE_DMA) {
620 p = string(p, pend, "dma ", str_spec);
621 specp = &dec_spec;
622 } else if (res->flags & IORESOURCE_BUS) {
623 p = string(p, pend, "bus ", str_spec);
624 specp = &bus_spec;
625 } else {
626 p = string(p, pend, "??? ", str_spec);
627 specp = &mem_spec;
628 decode = 0;
629 }
630 p = number(p, pend, res->start, *specp);
631 if (res->start != res->end) {
632 *p++ = '-';
633 p = number(p, pend, res->end, *specp);
634 }
635 if (decode) {
636 if (res->flags & IORESOURCE_MEM_64)
637 p = string(p, pend, " 64bit", str_spec);
638 if (res->flags & IORESOURCE_PREFETCH)
639 p = string(p, pend, " pref", str_spec);
640 if (res->flags & IORESOURCE_WINDOW)
641 p = string(p, pend, " window", str_spec);
642 if (res->flags & IORESOURCE_DISABLED)
643 p = string(p, pend, " disabled", str_spec);
644 } else {
645 p = string(p, pend, " flags ", str_spec);
646 p = number(p, pend, res->flags, flag_spec);
647 }
648 *p++ = ']';
649 *p = '\0';
650
651 return string(buf, end, sym, spec);
652}
653
654static noinline_for_stack
655char *hex_string(char *buf, char *end, u8 *addr, struct printf_spec spec,
656 const char *fmt)
657{
658 int i, len = 1;
659
660 char separator;
661
662 if (spec.field_width == 0)
663
664 return buf;
665
666 if (ZERO_OR_NULL_PTR(addr))
667
668 return string(buf, end, NULL, spec);
669
670 switch (fmt[1]) {
671 case 'C':
672 separator = ':';
673 break;
674 case 'D':
675 separator = '-';
676 break;
677 case 'N':
678 separator = 0;
679 break;
680 default:
681 separator = ' ';
682 break;
683 }
684
685 if (spec.field_width > 0)
686 len = min_t(int, spec.field_width, 64);
687
688 for (i = 0; i < len && buf < end - 1; i++) {
689 buf = hex_byte_pack(buf, addr[i]);
690
691 if (buf < end && separator && i != len - 1)
692 *buf++ = separator;
693 }
694
695 return buf;
696}
697
698static noinline_for_stack
699char *mac_address_string(char *buf, char *end, u8 *addr,
700 struct printf_spec spec, const char *fmt)
701{
702 char mac_addr[sizeof("xx:xx:xx:xx:xx:xx")];
703 char *p = mac_addr;
704 int i;
705 char separator;
706 bool reversed = false;
707
708 switch (fmt[1]) {
709 case 'F':
710 separator = '-';
711 break;
712
713 case 'R':
714 reversed = true;
715
716
717 default:
718 separator = ':';
719 break;
720 }
721
722 for (i = 0; i < 6; i++) {
723 if (reversed)
724 p = hex_byte_pack(p, addr[5 - i]);
725 else
726 p = hex_byte_pack(p, addr[i]);
727
728 if (fmt[0] == 'M' && i != 5)
729 *p++ = separator;
730 }
731 *p = '\0';
732
733 return string(buf, end, mac_addr, spec);
734}
735
736static noinline_for_stack
737char *ip4_string(char *p, const u8 *addr, const char *fmt)
738{
739 int i;
740 bool leading_zeros = (fmt[0] == 'i');
741 int index;
742 int step;
743
744 switch (fmt[2]) {
745 case 'h':
746#ifdef __BIG_ENDIAN
747 index = 0;
748 step = 1;
749#else
750 index = 3;
751 step = -1;
752#endif
753 break;
754 case 'l':
755 index = 3;
756 step = -1;
757 break;
758 case 'n':
759 case 'b':
760 default:
761 index = 0;
762 step = 1;
763 break;
764 }
765 for (i = 0; i < 4; i++) {
766 char temp[3];
767 int digits = put_dec_trunc8(temp, addr[index]) - temp;
768 if (leading_zeros) {
769 if (digits < 3)
770 *p++ = '0';
771 if (digits < 2)
772 *p++ = '0';
773 }
774
775 while (digits--)
776 *p++ = temp[digits];
777 if (i < 3)
778 *p++ = '.';
779 index += step;
780 }
781 *p = '\0';
782
783 return p;
784}
785
786static noinline_for_stack
787char *ip6_compressed_string(char *p, const char *addr)
788{
789 int i, j, range;
790 unsigned char zerolength[8];
791 int longest = 1;
792 int colonpos = -1;
793 u16 word;
794 u8 hi, lo;
795 bool needcolon = false;
796 bool useIPv4;
797 struct in6_addr in6;
798
799 memcpy(&in6, addr, sizeof(struct in6_addr));
800
801 useIPv4 = ipv6_addr_v4mapped(&in6) || ipv6_addr_is_isatap(&in6);
802
803 memset(zerolength, 0, sizeof(zerolength));
804
805 if (useIPv4)
806 range = 6;
807 else
808 range = 8;
809
810
811 for (i = 0; i < range; i++) {
812 for (j = i; j < range; j++) {
813 if (in6.s6_addr16[j] != 0)
814 break;
815 zerolength[i]++;
816 }
817 }
818 for (i = 0; i < range; i++) {
819 if (zerolength[i] > longest) {
820 longest = zerolength[i];
821 colonpos = i;
822 }
823 }
824 if (longest == 1)
825 colonpos = -1;
826
827
828 for (i = 0; i < range; i++) {
829 if (i == colonpos) {
830 if (needcolon || i == 0)
831 *p++ = ':';
832 *p++ = ':';
833 needcolon = false;
834 i += longest - 1;
835 continue;
836 }
837 if (needcolon) {
838 *p++ = ':';
839 needcolon = false;
840 }
841
842 word = ntohs(in6.s6_addr16[i]);
843 hi = word >> 8;
844 lo = word & 0xff;
845 if (hi) {
846 if (hi > 0x0f)
847 p = hex_byte_pack(p, hi);
848 else
849 *p++ = hex_asc_lo(hi);
850 p = hex_byte_pack(p, lo);
851 }
852 else if (lo > 0x0f)
853 p = hex_byte_pack(p, lo);
854 else
855 *p++ = hex_asc_lo(lo);
856 needcolon = true;
857 }
858
859 if (useIPv4) {
860 if (needcolon)
861 *p++ = ':';
862 p = ip4_string(p, &in6.s6_addr[12], "I4");
863 }
864 *p = '\0';
865
866 return p;
867}
868
869static noinline_for_stack
870char *ip6_string(char *p, const char *addr, const char *fmt)
871{
872 int i;
873
874 for (i = 0; i < 8; i++) {
875 p = hex_byte_pack(p, *addr++);
876 p = hex_byte_pack(p, *addr++);
877 if (fmt[0] == 'I' && i != 7)
878 *p++ = ':';
879 }
880 *p = '\0';
881
882 return p;
883}
884
885static noinline_for_stack
886char *ip6_addr_string(char *buf, char *end, const u8 *addr,
887 struct printf_spec spec, const char *fmt)
888{
889 char ip6_addr[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
890
891 if (fmt[0] == 'I' && fmt[2] == 'c')
892 ip6_compressed_string(ip6_addr, addr);
893 else
894 ip6_string(ip6_addr, addr, fmt);
895
896 return string(buf, end, ip6_addr, spec);
897}
898
899static noinline_for_stack
900char *ip4_addr_string(char *buf, char *end, const u8 *addr,
901 struct printf_spec spec, const char *fmt)
902{
903 char ip4_addr[sizeof("255.255.255.255")];
904
905 ip4_string(ip4_addr, addr, fmt);
906
907 return string(buf, end, ip4_addr, spec);
908}
909
910static noinline_for_stack
911char *uuid_string(char *buf, char *end, const u8 *addr,
912 struct printf_spec spec, const char *fmt)
913{
914 char uuid[sizeof("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")];
915 char *p = uuid;
916 int i;
917 static const u8 be[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
918 static const u8 le[16] = {3,2,1,0,5,4,7,6,8,9,10,11,12,13,14,15};
919 const u8 *index = be;
920 bool uc = false;
921
922 switch (*(++fmt)) {
923 case 'L':
924 uc = true;
925 case 'l':
926 index = le;
927 break;
928 case 'B':
929 uc = true;
930 break;
931 }
932
933 for (i = 0; i < 16; i++) {
934 p = hex_byte_pack(p, addr[index[i]]);
935 switch (i) {
936 case 3:
937 case 5:
938 case 7:
939 case 9:
940 *p++ = '-';
941 break;
942 }
943 }
944
945 *p = 0;
946
947 if (uc) {
948 p = uuid;
949 do {
950 *p = toupper(*p);
951 } while (*(++p));
952 }
953
954 return string(buf, end, uuid, spec);
955}
956
957static
958char *netdev_feature_string(char *buf, char *end, const u8 *addr,
959 struct printf_spec spec)
960{
961 spec.flags |= SPECIAL | SMALL | ZEROPAD;
962 if (spec.field_width == -1)
963 spec.field_width = 2 + 2 * sizeof(netdev_features_t);
964 spec.base = 16;
965
966 return number(buf, end, *(const netdev_features_t *)addr, spec);
967}
968
969int kptr_restrict __read_mostly;
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030static noinline_for_stack
1031char *pointer(const char *fmt, char *buf, char *end, void *ptr,
1032 struct printf_spec spec)
1033{
1034 int default_width = 2 * sizeof(void *) + (spec.flags & SPECIAL ? 2 : 0);
1035
1036 if (!ptr && *fmt != 'K') {
1037
1038
1039
1040
1041 if (spec.field_width == -1)
1042 spec.field_width = default_width;
1043 return string(buf, end, "(null)", spec);
1044 }
1045
1046 switch (*fmt) {
1047 case 'F':
1048 case 'f':
1049 ptr = dereference_function_descriptor(ptr);
1050
1051 case 'S':
1052 case 's':
1053 case 'B':
1054 return symbol_string(buf, end, ptr, spec, *fmt);
1055 case 'R':
1056 case 'r':
1057 return resource_string(buf, end, ptr, spec, fmt);
1058 case 'h':
1059 return hex_string(buf, end, ptr, spec, fmt);
1060 case 'M':
1061 case 'm':
1062
1063
1064 return mac_address_string(buf, end, ptr, spec, fmt);
1065 case 'I':
1066
1067
1068
1069
1070 case 'i':
1071
1072
1073
1074 switch (fmt[1]) {
1075 case '6':
1076 return ip6_addr_string(buf, end, ptr, spec, fmt);
1077 case '4':
1078 return ip4_addr_string(buf, end, ptr, spec, fmt);
1079 }
1080 break;
1081 case 'U':
1082 return uuid_string(buf, end, ptr, spec, fmt);
1083 case 'V':
1084 {
1085 va_list va;
1086
1087 va_copy(va, *((struct va_format *)ptr)->va);
1088 buf += vsnprintf(buf, end > buf ? end - buf : 0,
1089 ((struct va_format *)ptr)->fmt, va);
1090 va_end(va);
1091 return buf;
1092 }
1093 case 'K':
1094
1095
1096
1097
1098 if (kptr_restrict && (in_irq() || in_serving_softirq() ||
1099 in_nmi())) {
1100 if (spec.field_width == -1)
1101 spec.field_width = default_width;
1102 return string(buf, end, "pK-error", spec);
1103 }
1104 if (!((kptr_restrict == 0) ||
1105 (kptr_restrict == 1 &&
1106 has_capability_noaudit(current, CAP_SYSLOG))))
1107 ptr = NULL;
1108 break;
1109 case 'N':
1110 switch (fmt[1]) {
1111 case 'F':
1112 return netdev_feature_string(buf, end, ptr, spec);
1113 }
1114 break;
1115 }
1116 spec.flags |= SMALL;
1117 if (spec.field_width == -1) {
1118 spec.field_width = default_width;
1119 spec.flags |= ZEROPAD;
1120 }
1121 spec.base = 16;
1122
1123 return number(buf, end, (unsigned long) ptr, spec);
1124}
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146static noinline_for_stack
1147int format_decode(const char *fmt, struct printf_spec *spec)
1148{
1149 const char *start = fmt;
1150
1151
1152 if (spec->type == FORMAT_TYPE_WIDTH) {
1153 if (spec->field_width < 0) {
1154 spec->field_width = -spec->field_width;
1155 spec->flags |= LEFT;
1156 }
1157 spec->type = FORMAT_TYPE_NONE;
1158 goto precision;
1159 }
1160
1161
1162 if (spec->type == FORMAT_TYPE_PRECISION) {
1163 if (spec->precision < 0)
1164 spec->precision = 0;
1165
1166 spec->type = FORMAT_TYPE_NONE;
1167 goto qualifier;
1168 }
1169
1170
1171 spec->type = FORMAT_TYPE_NONE;
1172
1173 for (; *fmt ; ++fmt) {
1174 if (*fmt == '%')
1175 break;
1176 }
1177
1178
1179 if (fmt != start || !*fmt)
1180 return fmt - start;
1181
1182
1183 spec->flags = 0;
1184
1185 while (1) {
1186 bool found = true;
1187
1188 ++fmt;
1189
1190 switch (*fmt) {
1191 case '-': spec->flags |= LEFT; break;
1192 case '+': spec->flags |= PLUS; break;
1193 case ' ': spec->flags |= SPACE; break;
1194 case '#': spec->flags |= SPECIAL; break;
1195 case '0': spec->flags |= ZEROPAD; break;
1196 default: found = false;
1197 }
1198
1199 if (!found)
1200 break;
1201 }
1202
1203
1204 spec->field_width = -1;
1205
1206 if (isdigit(*fmt))
1207 spec->field_width = skip_atoi(&fmt);
1208 else if (*fmt == '*') {
1209
1210 spec->type = FORMAT_TYPE_WIDTH;
1211 return ++fmt - start;
1212 }
1213
1214precision:
1215
1216 spec->precision = -1;
1217 if (*fmt == '.') {
1218 ++fmt;
1219 if (isdigit(*fmt)) {
1220 spec->precision = skip_atoi(&fmt);
1221 if (spec->precision < 0)
1222 spec->precision = 0;
1223 } else if (*fmt == '*') {
1224
1225 spec->type = FORMAT_TYPE_PRECISION;
1226 return ++fmt - start;
1227 }
1228 }
1229
1230qualifier:
1231
1232 spec->qualifier = -1;
1233 if (*fmt == 'h' || _tolower(*fmt) == 'l' ||
1234 _tolower(*fmt) == 'z' || *fmt == 't') {
1235 spec->qualifier = *fmt++;
1236 if (unlikely(spec->qualifier == *fmt)) {
1237 if (spec->qualifier == 'l') {
1238 spec->qualifier = 'L';
1239 ++fmt;
1240 } else if (spec->qualifier == 'h') {
1241 spec->qualifier = 'H';
1242 ++fmt;
1243 }
1244 }
1245 }
1246
1247
1248 spec->base = 10;
1249 switch (*fmt) {
1250 case 'c':
1251 spec->type = FORMAT_TYPE_CHAR;
1252 return ++fmt - start;
1253
1254 case 's':
1255 spec->type = FORMAT_TYPE_STR;
1256 return ++fmt - start;
1257
1258 case 'p':
1259 spec->type = FORMAT_TYPE_PTR;
1260 return fmt - start;
1261
1262
1263 case 'n':
1264 spec->type = FORMAT_TYPE_NRCHARS;
1265 return ++fmt - start;
1266
1267 case '%':
1268 spec->type = FORMAT_TYPE_PERCENT_CHAR;
1269 return ++fmt - start;
1270
1271
1272 case 'o':
1273 spec->base = 8;
1274 break;
1275
1276 case 'x':
1277 spec->flags |= SMALL;
1278
1279 case 'X':
1280 spec->base = 16;
1281 break;
1282
1283 case 'd':
1284 case 'i':
1285 spec->flags |= SIGN;
1286 case 'u':
1287 break;
1288
1289 default:
1290 spec->type = FORMAT_TYPE_INVALID;
1291 return fmt - start;
1292 }
1293
1294 if (spec->qualifier == 'L')
1295 spec->type = FORMAT_TYPE_LONG_LONG;
1296 else if (spec->qualifier == 'l') {
1297 if (spec->flags & SIGN)
1298 spec->type = FORMAT_TYPE_LONG;
1299 else
1300 spec->type = FORMAT_TYPE_ULONG;
1301 } else if (_tolower(spec->qualifier) == 'z') {
1302 spec->type = FORMAT_TYPE_SIZE_T;
1303 } else if (spec->qualifier == 't') {
1304 spec->type = FORMAT_TYPE_PTRDIFF;
1305 } else if (spec->qualifier == 'H') {
1306 if (spec->flags & SIGN)
1307 spec->type = FORMAT_TYPE_BYTE;
1308 else
1309 spec->type = FORMAT_TYPE_UBYTE;
1310 } else if (spec->qualifier == 'h') {
1311 if (spec->flags & SIGN)
1312 spec->type = FORMAT_TYPE_SHORT;
1313 else
1314 spec->type = FORMAT_TYPE_USHORT;
1315 } else {
1316 if (spec->flags & SIGN)
1317 spec->type = FORMAT_TYPE_INT;
1318 else
1319 spec->type = FORMAT_TYPE_UINT;
1320 }
1321
1322 return ++fmt - start;
1323}
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
1369{
1370 unsigned long long num;
1371 char *str, *end;
1372 struct printf_spec spec = {0};
1373
1374
1375
1376 if (WARN_ON_ONCE((int) size < 0))
1377 return 0;
1378
1379 str = buf;
1380 end = buf + size;
1381
1382
1383 if (end < buf) {
1384 end = ((void *)-1);
1385 size = end - buf;
1386 }
1387
1388 while (*fmt) {
1389 const char *old_fmt = fmt;
1390 int read = format_decode(fmt, &spec);
1391
1392 fmt += read;
1393
1394 switch (spec.type) {
1395 case FORMAT_TYPE_NONE: {
1396 int copy = read;
1397 if (str < end) {
1398 if (copy > end - str)
1399 copy = end - str;
1400 memcpy(str, old_fmt, copy);
1401 }
1402 str += read;
1403 break;
1404 }
1405
1406 case FORMAT_TYPE_WIDTH:
1407 spec.field_width = va_arg(args, int);
1408 break;
1409
1410 case FORMAT_TYPE_PRECISION:
1411 spec.precision = va_arg(args, int);
1412 break;
1413
1414 case FORMAT_TYPE_CHAR: {
1415 char c;
1416
1417 if (!(spec.flags & LEFT)) {
1418 while (--spec.field_width > 0) {
1419 if (str < end)
1420 *str = ' ';
1421 ++str;
1422
1423 }
1424 }
1425 c = (unsigned char) va_arg(args, int);
1426 if (str < end)
1427 *str = c;
1428 ++str;
1429 while (--spec.field_width > 0) {
1430 if (str < end)
1431 *str = ' ';
1432 ++str;
1433 }
1434 break;
1435 }
1436
1437 case FORMAT_TYPE_STR:
1438 str = string(str, end, va_arg(args, char *), spec);
1439 break;
1440
1441 case FORMAT_TYPE_PTR:
1442 str = pointer(fmt+1, str, end, va_arg(args, void *),
1443 spec);
1444 while (isalnum(*fmt))
1445 fmt++;
1446 break;
1447
1448 case FORMAT_TYPE_PERCENT_CHAR:
1449 if (str < end)
1450 *str = '%';
1451 ++str;
1452 break;
1453
1454 case FORMAT_TYPE_INVALID:
1455 if (str < end)
1456 *str = '%';
1457 ++str;
1458 break;
1459
1460 case FORMAT_TYPE_NRCHARS: {
1461 u8 qualifier = spec.qualifier;
1462
1463 if (qualifier == 'l') {
1464 long *ip = va_arg(args, long *);
1465 *ip = (str - buf);
1466 } else if (_tolower(qualifier) == 'z') {
1467 size_t *ip = va_arg(args, size_t *);
1468 *ip = (str - buf);
1469 } else {
1470 int *ip = va_arg(args, int *);
1471 *ip = (str - buf);
1472 }
1473 break;
1474 }
1475
1476 default:
1477 switch (spec.type) {
1478 case FORMAT_TYPE_LONG_LONG:
1479 num = va_arg(args, long long);
1480 break;
1481 case FORMAT_TYPE_ULONG:
1482 num = va_arg(args, unsigned long);
1483 break;
1484 case FORMAT_TYPE_LONG:
1485 num = va_arg(args, long);
1486 break;
1487 case FORMAT_TYPE_SIZE_T:
1488 num = va_arg(args, size_t);
1489 break;
1490 case FORMAT_TYPE_PTRDIFF:
1491 num = va_arg(args, ptrdiff_t);
1492 break;
1493 case FORMAT_TYPE_UBYTE:
1494 num = (unsigned char) va_arg(args, int);
1495 break;
1496 case FORMAT_TYPE_BYTE:
1497 num = (signed char) va_arg(args, int);
1498 break;
1499 case FORMAT_TYPE_USHORT:
1500 num = (unsigned short) va_arg(args, int);
1501 break;
1502 case FORMAT_TYPE_SHORT:
1503 num = (short) va_arg(args, int);
1504 break;
1505 case FORMAT_TYPE_INT:
1506 num = (int) va_arg(args, int);
1507 break;
1508 default:
1509 num = va_arg(args, unsigned int);
1510 }
1511
1512 str = number(str, end, num, spec);
1513 }
1514 }
1515
1516 if (size > 0) {
1517 if (str < end)
1518 *str = '\0';
1519 else
1520 end[-1] = '\0';
1521 }
1522
1523
1524 return str-buf;
1525
1526}
1527EXPORT_SYMBOL(vsnprintf);
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
1545{
1546 int i;
1547
1548 i = vsnprintf(buf, size, fmt, args);
1549
1550 if (likely(i < size))
1551 return i;
1552 if (size != 0)
1553 return size - 1;
1554 return 0;
1555}
1556EXPORT_SYMBOL(vscnprintf);
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572int snprintf(char *buf, size_t size, const char *fmt, ...)
1573{
1574 va_list args;
1575 int i;
1576
1577 va_start(args, fmt);
1578 i = vsnprintf(buf, size, fmt, args);
1579 va_end(args);
1580
1581 return i;
1582}
1583EXPORT_SYMBOL(snprintf);
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596int scnprintf(char *buf, size_t size, const char *fmt, ...)
1597{
1598 va_list args;
1599 int i;
1600
1601 va_start(args, fmt);
1602 i = vscnprintf(buf, size, fmt, args);
1603 va_end(args);
1604
1605 return i;
1606}
1607EXPORT_SYMBOL(scnprintf);
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623int vsprintf(char *buf, const char *fmt, va_list args)
1624{
1625 return vsnprintf(buf, INT_MAX, fmt, args);
1626}
1627EXPORT_SYMBOL(vsprintf);
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641int sprintf(char *buf, const char *fmt, ...)
1642{
1643 va_list args;
1644 int i;
1645
1646 va_start(args, fmt);
1647 i = vsnprintf(buf, INT_MAX, fmt, args);
1648 va_end(args);
1649
1650 return i;
1651}
1652EXPORT_SYMBOL(sprintf);
1653
1654#ifdef CONFIG_BINARY_PRINTF
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678int vbin_printf(u32 *bin_buf, size_t size, const char *fmt, va_list args)
1679{
1680 struct printf_spec spec = {0};
1681 char *str, *end;
1682
1683 str = (char *)bin_buf;
1684 end = (char *)(bin_buf + size);
1685
1686#define save_arg(type) \
1687do { \
1688 if (sizeof(type) == 8) { \
1689 unsigned long long value; \
1690 str = PTR_ALIGN(str, sizeof(u32)); \
1691 value = va_arg(args, unsigned long long); \
1692 if (str + sizeof(type) <= end) { \
1693 *(u32 *)str = *(u32 *)&value; \
1694 *(u32 *)(str + 4) = *((u32 *)&value + 1); \
1695 } \
1696 } else { \
1697 unsigned long value; \
1698 str = PTR_ALIGN(str, sizeof(type)); \
1699 value = va_arg(args, int); \
1700 if (str + sizeof(type) <= end) \
1701 *(typeof(type) *)str = (type)value; \
1702 } \
1703 str += sizeof(type); \
1704} while (0)
1705
1706 while (*fmt) {
1707 int read = format_decode(fmt, &spec);
1708
1709 fmt += read;
1710
1711 switch (spec.type) {
1712 case FORMAT_TYPE_NONE:
1713 case FORMAT_TYPE_INVALID:
1714 case FORMAT_TYPE_PERCENT_CHAR:
1715 break;
1716
1717 case FORMAT_TYPE_WIDTH:
1718 case FORMAT_TYPE_PRECISION:
1719 save_arg(int);
1720 break;
1721
1722 case FORMAT_TYPE_CHAR:
1723 save_arg(char);
1724 break;
1725
1726 case FORMAT_TYPE_STR: {
1727 const char *save_str = va_arg(args, char *);
1728 size_t len;
1729
1730 if ((unsigned long)save_str > (unsigned long)-PAGE_SIZE
1731 || (unsigned long)save_str < PAGE_SIZE)
1732 save_str = "(null)";
1733 len = strlen(save_str) + 1;
1734 if (str + len < end)
1735 memcpy(str, save_str, len);
1736 str += len;
1737 break;
1738 }
1739
1740 case FORMAT_TYPE_PTR:
1741 save_arg(void *);
1742
1743 while (isalnum(*fmt))
1744 fmt++;
1745 break;
1746
1747 case FORMAT_TYPE_NRCHARS: {
1748
1749 u8 qualifier = spec.qualifier;
1750 void *skip_arg;
1751 if (qualifier == 'l')
1752 skip_arg = va_arg(args, long *);
1753 else if (_tolower(qualifier) == 'z')
1754 skip_arg = va_arg(args, size_t *);
1755 else
1756 skip_arg = va_arg(args, int *);
1757 break;
1758 }
1759
1760 default:
1761 switch (spec.type) {
1762
1763 case FORMAT_TYPE_LONG_LONG:
1764 save_arg(long long);
1765 break;
1766 case FORMAT_TYPE_ULONG:
1767 case FORMAT_TYPE_LONG:
1768 save_arg(unsigned long);
1769 break;
1770 case FORMAT_TYPE_SIZE_T:
1771 save_arg(size_t);
1772 break;
1773 case FORMAT_TYPE_PTRDIFF:
1774 save_arg(ptrdiff_t);
1775 break;
1776 case FORMAT_TYPE_UBYTE:
1777 case FORMAT_TYPE_BYTE:
1778 save_arg(char);
1779 break;
1780 case FORMAT_TYPE_USHORT:
1781 case FORMAT_TYPE_SHORT:
1782 save_arg(short);
1783 break;
1784 default:
1785 save_arg(int);
1786 }
1787 }
1788 }
1789
1790 return (u32 *)(PTR_ALIGN(str, sizeof(u32))) - bin_buf;
1791#undef save_arg
1792}
1793EXPORT_SYMBOL_GPL(vbin_printf);
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf)
1818{
1819 struct printf_spec spec = {0};
1820 char *str, *end;
1821 const char *args = (const char *)bin_buf;
1822
1823 if (WARN_ON_ONCE((int) size < 0))
1824 return 0;
1825
1826 str = buf;
1827 end = buf + size;
1828
1829#define get_arg(type) \
1830({ \
1831 typeof(type) value; \
1832 if (sizeof(type) == 8) { \
1833 args = PTR_ALIGN(args, sizeof(u32)); \
1834 *(u32 *)&value = *(u32 *)args; \
1835 *((u32 *)&value + 1) = *(u32 *)(args + 4); \
1836 } else { \
1837 args = PTR_ALIGN(args, sizeof(type)); \
1838 value = *(typeof(type) *)args; \
1839 } \
1840 args += sizeof(type); \
1841 value; \
1842})
1843
1844
1845 if (end < buf) {
1846 end = ((void *)-1);
1847 size = end - buf;
1848 }
1849
1850 while (*fmt) {
1851 const char *old_fmt = fmt;
1852 int read = format_decode(fmt, &spec);
1853
1854 fmt += read;
1855
1856 switch (spec.type) {
1857 case FORMAT_TYPE_NONE: {
1858 int copy = read;
1859 if (str < end) {
1860 if (copy > end - str)
1861 copy = end - str;
1862 memcpy(str, old_fmt, copy);
1863 }
1864 str += read;
1865 break;
1866 }
1867
1868 case FORMAT_TYPE_WIDTH:
1869 spec.field_width = get_arg(int);
1870 break;
1871
1872 case FORMAT_TYPE_PRECISION:
1873 spec.precision = get_arg(int);
1874 break;
1875
1876 case FORMAT_TYPE_CHAR: {
1877 char c;
1878
1879 if (!(spec.flags & LEFT)) {
1880 while (--spec.field_width > 0) {
1881 if (str < end)
1882 *str = ' ';
1883 ++str;
1884 }
1885 }
1886 c = (unsigned char) get_arg(char);
1887 if (str < end)
1888 *str = c;
1889 ++str;
1890 while (--spec.field_width > 0) {
1891 if (str < end)
1892 *str = ' ';
1893 ++str;
1894 }
1895 break;
1896 }
1897
1898 case FORMAT_TYPE_STR: {
1899 const char *str_arg = args;
1900 args += strlen(str_arg) + 1;
1901 str = string(str, end, (char *)str_arg, spec);
1902 break;
1903 }
1904
1905 case FORMAT_TYPE_PTR:
1906 str = pointer(fmt+1, str, end, get_arg(void *), spec);
1907 while (isalnum(*fmt))
1908 fmt++;
1909 break;
1910
1911 case FORMAT_TYPE_PERCENT_CHAR:
1912 case FORMAT_TYPE_INVALID:
1913 if (str < end)
1914 *str = '%';
1915 ++str;
1916 break;
1917
1918 case FORMAT_TYPE_NRCHARS:
1919
1920 break;
1921
1922 default: {
1923 unsigned long long num;
1924
1925 switch (spec.type) {
1926
1927 case FORMAT_TYPE_LONG_LONG:
1928 num = get_arg(long long);
1929 break;
1930 case FORMAT_TYPE_ULONG:
1931 case FORMAT_TYPE_LONG:
1932 num = get_arg(unsigned long);
1933 break;
1934 case FORMAT_TYPE_SIZE_T:
1935 num = get_arg(size_t);
1936 break;
1937 case FORMAT_TYPE_PTRDIFF:
1938 num = get_arg(ptrdiff_t);
1939 break;
1940 case FORMAT_TYPE_UBYTE:
1941 num = get_arg(unsigned char);
1942 break;
1943 case FORMAT_TYPE_BYTE:
1944 num = get_arg(signed char);
1945 break;
1946 case FORMAT_TYPE_USHORT:
1947 num = get_arg(unsigned short);
1948 break;
1949 case FORMAT_TYPE_SHORT:
1950 num = get_arg(short);
1951 break;
1952 case FORMAT_TYPE_UINT:
1953 num = get_arg(unsigned int);
1954 break;
1955 default:
1956 num = get_arg(int);
1957 }
1958
1959 str = number(str, end, num, spec);
1960 }
1961 }
1962 }
1963
1964 if (size > 0) {
1965 if (str < end)
1966 *str = '\0';
1967 else
1968 end[-1] = '\0';
1969 }
1970
1971#undef get_arg
1972
1973
1974 return str - buf;
1975}
1976EXPORT_SYMBOL_GPL(bstr_printf);
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988int bprintf(u32 *bin_buf, size_t size, const char *fmt, ...)
1989{
1990 va_list args;
1991 int ret;
1992
1993 va_start(args, fmt);
1994 ret = vbin_printf(bin_buf, size, fmt, args);
1995 va_end(args);
1996
1997 return ret;
1998}
1999EXPORT_SYMBOL_GPL(bprintf);
2000
2001#endif
2002
2003
2004
2005
2006
2007
2008
2009int vsscanf(const char *buf, const char *fmt, va_list args)
2010{
2011 const char *str = buf;
2012 char *next;
2013 char digit;
2014 int num = 0;
2015 u8 qualifier;
2016 u8 base;
2017 s16 field_width;
2018 bool is_sign;
2019
2020 while (*fmt) {
2021
2022
2023
2024
2025 if (isspace(*fmt)) {
2026 fmt = skip_spaces(++fmt);
2027 str = skip_spaces(str);
2028 }
2029
2030
2031 if (*fmt != '%' && *fmt) {
2032 if (*fmt++ != *str++)
2033 break;
2034 continue;
2035 }
2036
2037 if (!*fmt)
2038 break;
2039 ++fmt;
2040
2041
2042
2043
2044 if (*fmt == '*') {
2045 if (!*str)
2046 break;
2047 while (!isspace(*fmt) && *fmt != '%' && *fmt)
2048 fmt++;
2049 while (!isspace(*str) && *str)
2050 str++;
2051 continue;
2052 }
2053
2054
2055 field_width = -1;
2056 if (isdigit(*fmt))
2057 field_width = skip_atoi(&fmt);
2058
2059
2060 qualifier = -1;
2061 if (*fmt == 'h' || _tolower(*fmt) == 'l' ||
2062 _tolower(*fmt) == 'z') {
2063 qualifier = *fmt++;
2064 if (unlikely(qualifier == *fmt)) {
2065 if (qualifier == 'h') {
2066 qualifier = 'H';
2067 fmt++;
2068 } else if (qualifier == 'l') {
2069 qualifier = 'L';
2070 fmt++;
2071 }
2072 }
2073 }
2074
2075 if (!*fmt)
2076 break;
2077
2078 if (*fmt == 'n') {
2079
2080 *va_arg(args, int *) = str - buf;
2081 ++fmt;
2082 continue;
2083 }
2084
2085 if (!*str)
2086 break;
2087
2088 base = 10;
2089 is_sign = 0;
2090
2091 switch (*fmt++) {
2092 case 'c':
2093 {
2094 char *s = (char *)va_arg(args, char*);
2095 if (field_width == -1)
2096 field_width = 1;
2097 do {
2098 *s++ = *str++;
2099 } while (--field_width > 0 && *str);
2100 num++;
2101 }
2102 continue;
2103 case 's':
2104 {
2105 char *s = (char *)va_arg(args, char *);
2106 if (field_width == -1)
2107 field_width = SHRT_MAX;
2108
2109 str = skip_spaces(str);
2110
2111
2112 while (*str && !isspace(*str) && field_width--)
2113 *s++ = *str++;
2114 *s = '\0';
2115 num++;
2116 }
2117 continue;
2118 case 'o':
2119 base = 8;
2120 break;
2121 case 'x':
2122 case 'X':
2123 base = 16;
2124 break;
2125 case 'i':
2126 base = 0;
2127 case 'd':
2128 is_sign = 1;
2129 case 'u':
2130 break;
2131 case '%':
2132
2133 if (*str++ != '%')
2134 return num;
2135 continue;
2136 default:
2137
2138 return num;
2139 }
2140
2141
2142
2143
2144 str = skip_spaces(str);
2145
2146 digit = *str;
2147 if (is_sign && digit == '-')
2148 digit = *(str + 1);
2149
2150 if (!digit
2151 || (base == 16 && !isxdigit(digit))
2152 || (base == 10 && !isdigit(digit))
2153 || (base == 8 && (!isdigit(digit) || digit > '7'))
2154 || (base == 0 && !isdigit(digit)))
2155 break;
2156
2157 switch (qualifier) {
2158 case 'H':
2159 if (is_sign) {
2160 signed char *s = (signed char *)va_arg(args, signed char *);
2161 *s = (signed char)simple_strtol(str, &next, base);
2162 } else {
2163 unsigned char *s = (unsigned char *)va_arg(args, unsigned char *);
2164 *s = (unsigned char)simple_strtoul(str, &next, base);
2165 }
2166 break;
2167 case 'h':
2168 if (is_sign) {
2169 short *s = (short *)va_arg(args, short *);
2170 *s = (short)simple_strtol(str, &next, base);
2171 } else {
2172 unsigned short *s = (unsigned short *)va_arg(args, unsigned short *);
2173 *s = (unsigned short)simple_strtoul(str, &next, base);
2174 }
2175 break;
2176 case 'l':
2177 if (is_sign) {
2178 long *l = (long *)va_arg(args, long *);
2179 *l = simple_strtol(str, &next, base);
2180 } else {
2181 unsigned long *l = (unsigned long *)va_arg(args, unsigned long *);
2182 *l = simple_strtoul(str, &next, base);
2183 }
2184 break;
2185 case 'L':
2186 if (is_sign) {
2187 long long *l = (long long *)va_arg(args, long long *);
2188 *l = simple_strtoll(str, &next, base);
2189 } else {
2190 unsigned long long *l = (unsigned long long *)va_arg(args, unsigned long long *);
2191 *l = simple_strtoull(str, &next, base);
2192 }
2193 break;
2194 case 'Z':
2195 case 'z':
2196 {
2197 size_t *s = (size_t *)va_arg(args, size_t *);
2198 *s = (size_t)simple_strtoul(str, &next, base);
2199 }
2200 break;
2201 default:
2202 if (is_sign) {
2203 int *i = (int *)va_arg(args, int *);
2204 *i = (int)simple_strtol(str, &next, base);
2205 } else {
2206 unsigned int *i = (unsigned int *)va_arg(args, unsigned int*);
2207 *i = (unsigned int)simple_strtoul(str, &next, base);
2208 }
2209 break;
2210 }
2211 num++;
2212
2213 if (!next)
2214 break;
2215 str = next;
2216 }
2217
2218 return num;
2219}
2220EXPORT_SYMBOL(vsscanf);
2221
2222
2223
2224
2225
2226
2227
2228int sscanf(const char *buf, const char *fmt, ...)
2229{
2230 va_list args;
2231 int i;
2232
2233 va_start(args, fmt);
2234 i = vsscanf(buf, fmt, args);
2235 va_end(args);
2236
2237 return i;
2238}
2239EXPORT_SYMBOL(sscanf);
2240