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